redis stream机制

Redis Stream 是 Redis 5.0 引入的一种数据结构,旨在提供类似于消息队列的功能,但具备更强大的特性,如消费者组、持久化、消息确认和回溯读取等。Redis Stream 可以用于实现日志处理、消息队列、事件源等场景。下面是对 Redis Stream 机制的详细介绍。

1. 基本概念

a. Stream

Stream 是一种可变长的消息序列,每条消息由唯一的ID和一个键值对组成。Stream 是一个数据结构,它存储的不是单纯的字符串,而是一系列有序的、带有 ID 的键值对。

b. Entry

Stream 中的每条记录称为一个 Entry,它包含两个部分:

  • ID : 由 Redis 自动生成的唯一标识符,格式为 时间戳-序列号,如 1609459200000-0
  • 字段-值对: 一个或多个字段-值对,类似于 Redis 的哈希表。
c. Consumer

消费者是一个读取 Stream 中消息的客户端。消费者可以独立读取 Stream 中的消息。

d. Consumer Group

消费者组是 Redis Stream 中的一个重要特性,允许多个消费者协作消费同一个 Stream 中的消息。每个消费者组中的消息只会被一个消费者消费,消费者组有助于实现消息的负载均衡。

e. Pending Entries

消费者组中的挂起条目(Pending Entries)是指那些被某个消费者读取了但尚未确认的消息。

2. 基本操作

a. 添加消息

向 Stream 中添加消息,可以使用 XADD 命令。每条消息都由一个 ID 和多个字段值对组成。

bash 复制代码
XADD mystream * field1 value1 field2 value2
  • mystream 是 Stream 的名称。
  • * 表示让 Redis 自动生成 ID。
  • field1 value1 是消息体的字段和值。
b. 读取消息

使用 XRANGE 命令读取 Stream 中的消息,可以指定 ID 范围。

bash 复制代码
XRANGE mystream - +
  • -+ 分别表示从最早的消息到最新的消息。
c. 消费者组

消费者组允许多个消费者协作消费同一个 Stream。使用 XGROUP CREATE 命令创建一个消费者组:

bash 复制代码
XGROUP CREATE mystream mygroup $ MKSTREAM
  • mygroup 是消费者组的名称。
  • $ 表示从新消息开始消费。
d. 消费者读取消息

消费者从消费者组中读取消息时使用 XREADGROUP 命令:

bash 复制代码
XREADGROUP GROUP mygroup consumer1 COUNT 1 STREAMS mystream >
  • mygroup 是消费者组的名称。
  • consumer1 是消费者名称。
  • > 表示从未被其他消费者读取的消息开始读取。
e. 消息确认

消费者读取消息后,需要发送 XACK 命令确认已经处理完该消息:

bash 复制代码
XACK mystream mygroup 1609459200000-0
  • 1609459200000-0 是消息的 ID。

3. 高级特性

a. 持久化

Stream 中的消息是持久化的,Redis 会将它们存储在磁盘中,确保在服务器重启后仍然存在。

b. 自动修剪

Redis 提供 MAXLEN 参数,可以设置 Stream 的最大长度。当超过此长度时,旧消息会被自动删除。

bash 复制代码
XADD mystream MAXLEN 1000 * field1 value1
c. 消息回溯

消费者组中的消费者可以读取历史消息,即使这些消息已经被其他消费者消费。通过设置起始ID,消费者可以回溯到某个时刻重新读取消息。

4. 实现示例

a. 生产者示例

在 Java Spring Boot 中,可以使用 RedisTemplate 来向 Stream 中添加消息:

java 复制代码
@Autowired
private RedisTemplate<String, Object> redisTemplate;

public void produceMessage(String streamKey, Map<String, String> message) {
    redisTemplate.opsForStream().add(StreamRecords.newRecord().in(streamKey).ofMap(message));
}
b. 消费者示例

通过 StreamMessageListenerContainer 实现消费者组中的消费者,消费消息并确认处理:

java 复制代码
@Autowired
private RedisTemplate<String, Object> redisTemplate;

@PostConstruct
public void startConsumer() {
    StreamMessageListenerContainer.StreamMessageListenerContainerOptions<String, MapRecord<String, String, String>> options =
            StreamMessageListenerContainer.StreamMessageListenerContainerOptions.builder()
                    .pollTimeout(Duration.ofSeconds(1))
                    .build();

    StreamMessageListenerContainer<String, MapRecord<String, String, String>> listenerContainer =
            StreamMessageListenerContainer.create(redisTemplate.getConnectionFactory(), options);

    listenerContainer.receive(Consumer.from("mygroup", "consumer1"),
            StreamOffset.create("mystream", ReadOffset.lastConsumed()),
            new StreamListener<String, MapRecord<String, String, String>>() {
                @Override
                public void onMessage(MapRecord<String, String, String> message) {
                    System.out.println("Received message: " + message.getValue().get("field1"));
                    // 消费后确认消息
                    redisTemplate.opsForStream().acknowledge("mygroup", message);
                }
            });

    listenerContainer.start();
}

总结

Redis Stream 提供了强大的消息队列功能,支持消费者组、消息持久化、消息确认与重试等特性,非常适合构建高吞吐量、高可靠性的分布式消息系统。通过对 Redis Stream 的理解和应用,可以解决许多实际的消息队列需求,尤其是在分布式环境中。

a. 可以进一步学习 Redis Stream 中的高级功能,例如 XCLAIM 命令用于处理消费者故障恢复的场景。
b. 可以尝试实现一个基于 Redis Stream 的分布式消息系统,并考虑使用 Redis Cluster 提升系统的可扩展性。

相关推荐
Allen Bright10 分钟前
Redis主从架构
数据库·redis·架构
ZHOU西口14 分钟前
MySQL系列之远程管理(安全)
数据库·mysql·安全·tls·加密连接·require_secure
fcopy22 分钟前
Golang项目:实现生产者消费者模式
缓存·golang
Karoku06639 分钟前
【docker集群应用】Docker网络与资源控制
运维·数据库·docker·容器
2301_7930868743 分钟前
springboot+redis+lua实现分布式锁
spring boot·redis·lua
扬子鳄0081 小时前
Spring Boot自动配置机制
java·数据库·spring boot
秋意钟1 小时前
sql漏洞
数据库·oracle
cdut_suye2 小时前
C++11新特性探索:Lambda表达式与函数包装器的实用指南
开发语言·数据库·c++·人工智能·python·机器学习·华为
点点滴滴的记录2 小时前
延迟队列调研
redis
Mr_Xuhhh2 小时前
程序地址空间
android·java·开发语言·数据库