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 提升系统的可扩展性。

相关推荐
李少兄1 小时前
记一次 Spring Boot 项目中 Redis 工具类的重构实践
spring boot·redis·重构
姚远Oracle ACE1 小时前
如何判断Oracle AWR报告中的SQL在多大程度能代表整个系统的负载?
数据库·oracle·1024程序员节
chushiyunen2 小时前
neo4j图数据库笔记
数据库·笔记·neo4j
一 乐2 小时前
宠物管理|宠物店管理|基于SSM+vue的宠物店管理系统(源码+数据库+文档)
java·前端·数据库·vue.js·论文·毕设·宠物
Merlos_wind2 小时前
【Redis典型应用——缓存详解】
数据库·redis·缓存
Han.miracle3 小时前
数据库圣经-----最终章JDBC
java·数据库·学习·maven·database
摇滚侠3 小时前
Spring Boot3零基础教程,整合 Redis,笔记69
spring boot·redis·笔记
折翼的恶魔3 小时前
SQL188 每月及截止当月的答题情况
数据库
Thepatterraining3 小时前
MySQL Java开发终极教程:三种技术栈对比,大厂资深开发经验分享
数据库·mysql
DemonAvenger3 小时前
Redis性能优化实战:从配置调优到代码实现的全面指南
数据库·redis·性能优化