Redis Stream队列与多线程模型

本文介绍了Redis Stream数据结构及其在消息队列中的应用,详细讲解了生产端、消费者组和消费者的概念。此外,文章还探讨了Redis的IO模型,包括Reactor模型和Redis6中的多线程改进,解释了如何利用多线程优化网络数据的读写和协议解析,以提升处理高QPS请求的能力。
摘要由CSDN通过智能技术生成

Stream队列与多线程模型

Stream队列

Redis5.0版本新出stream数据结构,是实现消息队列的功能的。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-74lgX177-1679989407529)(picture/Redis/9882)]

Redis Stream 的结构如上图所示,每一个Stream都有一个消息链表,将所有加入的消息都串起来,每个消息都有一个唯一的 ID 和对应的内容。

每个 Stream 都有唯一的名称,它就是 Redis 的 key,在我们首次使用xadd指令追加消息时创建的。

每个 Stream 都可以挂多个消费组,每个消费组会有个游标last_delivered_id在 Stream 数组之上往前移动,表示当前消费组已经消费到哪条消息了。每个消费组都有一个 Stream 内唯一的名称,消费组不会自动创建,它需要单独的指令xgroup create进行创建,需要指定从 Stream 的某个消息 ID 开始消费,这个 ID 用来初始化last_delivered_id变量。

每个消费组 (Consumer Group) 的状态都是独立的,相互不受影响。也就是说同一份 Stream 内部的消息会被每个消费组都消费到。

同一个消费组 (Consumer Group) 可以挂接多个消费者 (Consumer),这些消费者之间是竞争关系,任意一个消费者读取了消息都会使游标last_delivered_id往前移动。每个消费者有一个组内唯一名称。

消费者 (Consumer) 内部会有个状态变量pending_ids,它记录了当前已经被客户端读取,但是还没有 ack的消息。

消息 ID 的形式是timestampInMillis-sequence,时间戳-流水号。消息 ID 可以由服务器自动生成,也可以由客户端自己指定,但是形式必须是整数-整数,而且必须是后面加入的消息的 ID 要大于前面的消息 ID。建议不要自己指定

消息内容就是键值对,形如 hash 结构的键值对



生产端

生产端常用命令如下所示:

# 追加消息
# xadd stream名字 消息id key value [key value ...]
xadd streamtest * name hushang age 23

# 删除消息,这里的删除仅仅是设置了标志位,不会实际删除消息。如果不指定消息id直接执行则是删除整个stream中的消息
# xdel 	stream名字 消息id
xdel streamtest 165847589548-0

# 获取消息,会过滤掉删除了的消息,也可以用- + 表示获取所有消息,-表示最小值  + 表示最大值
# xrange stream名字 最小消息id 最大消息id
xrange streamtest - +

# 获取stream中消息数量
# xlen stream名字
xlen streamtest

# 删除stream
del stream名字

案例

# 首先新增三条消息
127.0.0.1:6379> xadd streamtest * name hushang age 23
"1679980604367-0"
127.0.0.1:6379> xadd streamtest * name zhangsan age 24
"1679980624235-0"
127.0.0.1:6379> xadd streamtest * name lisi age 18
"1679980635354-0"


# 查询消息
127.0.0.1:6379> xrange streamtest - +
1) 1) "1679980604367-0"
   2) 1) "name"
      2) "hushang"
      3) "age"
      4) "23"
2) 1) "1679980624235-0"
   2) 1) "name"
      2) "zhangsan"
      3) "age"
      4) "24"
3) 1) "1679980635354-0"
   2) 1) "name"
      2) "lisi"
      3) "age"
      4) "18"
127.0.0.1:6379> xrange streamtest - 1679980624235-0
1) 1) "1679980604367-0"
   2) 1) "name"
      2) "hushang"
      3) "age"
      4) "23"
2) 1) "1679980624235-0"
   2) 1) "name"
      2) "zhangsan"
      3) "age"
      4) "24"
     
# 获取消息数量与删除消息     
127.0.0.1:6379> xlen streamtest
(integer) 3
127.0.0.1:6379
Spring Boot提供了对Redis Stream队列的支持。Redis Stream是一个高效的持久化消息队列,可以用于实现发布-订阅模式、任务队列等应用场景。 要在Spring Boot中使用Redis Stream队列,需要进行以下步骤: 1. 添加RedisSpring Data Redis的依赖:在`pom.xml`文件中添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 配置Redis连接信息:在`application.properties`或`application.yml`文件中配置Redis连接信息,包括主机、端口、密码等。 ```properties spring.redis.host=your_redis_host spring.redis.port=your_redis_port spring.redis.password=your_redis_password ``` 3. 创建Redis Stream队列:在Spring Boot中,可以使用`StreamOperations`接口来操作Redis Stream队列。可以通过自动注入`RedisTemplate`或`StringRedisTemplate`来获取`StreamOperations`对象。 ```java @Autowired private RedisTemplate<String, String> redisTemplate; ... StreamOperations<String, String, String> streamOperations = redisTemplate.opsForStream(); ``` 4. 发布消息到Redis Stream队列:使用`XADD`命令将消息发布到Redis Stream队列中。 ```java Map<String, String> message = new HashMap<>(); message.put("key1", "value1"); message.put("key2", "value2"); streamOperations.add("your_stream_key", message); ``` 5. 消费Redis Stream队列消息:使用`XREADGROUP`命令消费Redis Stream队列中的消息。 ```java Consumer<String, String> consumer = StreamOffset.create("your_stream_key", ReadOffset.lastConsumed()); while (true) { List<MapRecord<String, String, String>> records = streamOperations.read(consumer, StreamReadOptions.empty()); for (MapRecord<String, String, String> record : records) { // 处理消息 System.out.println(record.getValue()); } } ``` 以上是使用Spring Boot操作Redis Stream队列的基本步骤,你可以根据实际需求进行修改和扩展。希望对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值