在SpringBoot中使用RedisTemplate重新消费Redis Stream中未ACK的消息

消费组从stream中获取到消息后,会分配给自己组中其中的一个消费者进行消费,消费者消费完毕,需要给消费组返回ACK,表示这条消息已经消费完毕了。

当消费者从消费组获取到消息的时候,会先把消息添加到自己的pending消息列表,当消费者给消费组返回ACK的时候,就会把这条消息从pending队列删除。(每个消费者都有自己的pending消息队列)

消费者可能没有及时的返回ACK。例如消费者消费完毕后,宕机,没有及时返回ACK,此时就会导致这条消息占用2倍的内存(stream中保存一份, 消费者的的pending消息列表中保存一份)

关于Stream的基础姿势,可以先看看这篇贴帖子
如何在Springboot中使用Redis5的Stream

开始之前,通过Redis客户端模拟一点数据

1,新打开Redis客户端(我们称之为:生产端), 创建streamm,名称叫做:my_stream

XADD my_stream * hello world

随便添加一条消息,目的是为了初始化stream

2,创建一个消费组,名称叫做:my_group

XGROUP CREATE my_stream my_group $

3,再新启动一个Redis客户端(我们称之为:消费端1),使用消费组进行阻塞消费,指定消费者:my_consumer1

XREADGROUP GROUP my_group  my_consumer1  BLOCK 0 STREAMS my_stream >

4,再新启动一个Redis客户端(我们称之为:消费端2),使用消费组进行阻塞消费,指定消费者:my_consumer2

XREADGROUP GROUP my_group  my_consumer2  BLOCK 0 STREAMS my_stream >

5,通过生产端,推送3条消息

XADD my_stream * message1 Hello
XADD my_stream * message2 SpringBoot
XADD my_stream * message3 Community
生产端

消费端1

消费端2

可以看到,一共Push了3条消息,它们的ID分别是

  • 1605524648266-0 (message1 )
  • 1605524657157-0 (message2)
  • 1605524665215-0 (message3)

现在的状况是,消费者1,消费了2条消息(message1和message3),消费者2,消费了1条消息(message2)。都是消费成功了的,但是它们都还没有进行ACK

在客户端,消费者消费到一条消息后会立即返回,需要重新执行命令,来回到阻塞状态

ACK消息

现在我们打算,把消费者1,消费的那条message1进行ACK

XACK my_stream my_group  1605524648266-0

获取指定消费组中,待确认(ACK)的消息

查看消费组的所有待确认消息统计

127.0.0.1:6379> XPENDING my_stream  my_group
1) (integer) 2       # 消费组中,所有消费者的pending消息数量
2) "1605524657157-0" # pending消息中的,最小消息ID
3) "1605524665215-0" # pending消息中的,最大消息ID
4) 1) 1) "my_consumer1"  # 消费者1
      2) "1"             # 有1条待确认消息
   2) 1) "my_consumer2"  # 消费者2
      2) "1"             # 有2条待确认消息

查看消费者1的待确认消息详情

127.0.0.1:6379> XPENDING my_stream  my_group 0 + 10 my_consumer1
1) 1) "1605524665215-0"  # 待ACK消息ID
   2) "my_consumer1"     # 所属消费者
   3) (integer) 847437   # 消息自从被消费者获取后到现在过去的时间(毫秒) - idle time
   4) (integer) 1        # 消息被获取的次数	- delivery counter

这条命令,表示查询消费组my_group中消费者my_consumer1的opending队列,开始ID是0,结束ID是最大,最多检索10个结果。

现在的情况就是,一共3条消息,消费者1消费了2条,ack了1条。消费者2消费了1条,没有ack。消费者1和2,各自的pending队列中都有一条未ack的消息

如何实现将未被成功消费的消息获取出来重新进行消费?之前的演示,目的都是为了造一些数据,所以是用的客户端命令,从这里开始,所有的演示,都会使用spring-data-redis中的RedisTemplate

遍历消费者的pending列表,读取到未ACK的消息,直接进行ACK

import java.time.Duration;
import java.util.List;
import java.util.Map;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.data.domain.Range;
import org.springframework.data.redis.connection.stream.Consumer;
import org.springframework.data.redis.connection.stream.MapRecord;
import org.springframework.data.redis.connection.stream.PendingMessages;
import org.springframework.data.redis.connection.stream.PendingMessagesSummary;
import org.springframework.data.redis.connection.stream.RecordId;
import org.springframework.data.redis.core.StreamOperations;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.test.context.junit4.SpringRunner;

import io.springboot.jwt.SpringBootJwtApplication;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringBootJwtApplication.
  • 4
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 在 Spring Boot 使用 RedisTemplate 存储 hash 类型的数据到 Redis,可以使用以下步骤: 1. 在 pom.xml 文件添加 Redis 的依赖: ``` <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 2. 在 application.properties 或 application.yml 配置 Redis 连接信息: ``` spring.redis.host=your_redis_host spring.redis.port=your_redis_port ``` 3. 在需要使用 Redis 的类注入 RedisTemplate 对象: ``` @Autowired private RedisTemplate<String, Object> redisTemplate; ``` 4. 使用 redisTemplate 的 hash 相关方法来存储数据,如 hset()、hget()、hdel() 等。 示例代码: ``` redisTemplate.opsForHash().put("hashName","key","value"); redisTemplate.opsForHash().get("hashName","key"); ``` 注意: RedisTemplate 默认会使用 JDK 序列化器来序列化对象,如果需要使用 JSON 序列化器,需要在配置类进行配置。 ### 回答2: 在Spring Boot使用RedisTemplate存放hash类型进Redis,我们需要进行以下步骤: 1. 配置RedisTemplate 首先,在Spring Boot的配置文件(例如application.properties)配置Redis的连接信息,包括主机地址、端口号、密码等。可以使用以下配置代码: ```java spring.redis.host=127.0.0.1 spring.redis.port=6379 spring.redis.password=yourpassword ``` 然后,在你的Spring Boot应用程序创建一个RedisTemplate的Bean,并设置相关的Redis连接工厂、Key和Value的序列化方式等配置项。 2. 使用RedisTemplate操作hash类型 在你的代码,注入RedisTemplate,并使用它对Redis的hash类型进行操作。例如,你可以在某个Service类使用RedisTemplate进行hash的存储和获取操作,示例如下: ```java @Service public class RedisHashService { @Autowired private RedisTemplate<String, Object> redisTemplate; public void saveHash(String key, Map<String, Object> hash) { redisTemplate.opsForHash().putAll(key, hash); } public Map<Object, Object> getHash(String key) { return redisTemplate.opsForHash().entries(key); } } ``` 在上述示例,`saveHash`方法使用RedisTemplate的`opsForHash`方法来将一个Map对象保存为hash类型的数据到Redis。`getHash`方法则使用`opsForHash`方法获取指定hash的所有字段和值,返回一个Map对象。 这样,你就可以在Spring Boot使用RedisTemplate存放hash类型进Redis了。通过注入RedisTemplate,并使用其提供的操作方法,你可以方便地进行哈希类型的数据存储和获取操作。 ### 回答3: 在Spring Boot使用RedisTemplate存储hash类型数据到Redis,可以按照以下步骤进行操作: 首先,我们需要在Spring Boot项目引入Redis依赖,在pom.xml文件添加以下依赖: ```xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-data-redis</artifactId> </dependency> ``` 接下来需要配置Redis连接信息,可以在application.properties文件添加以下配置: ```properties spring.redis.host=127.0.0.1 spring.redis.port=6379 ``` 然后,在需要使用Redis的类注入RedisTemplate实例: ```java @Autowired private RedisTemplate<String, Object> redisTemplate; ``` 接下来就可以使用RedisTemplate存储hash类型数据到Redis了。假设我们要存储一个名为"myHash"的hash数据到Redis,可以使用以下代码: ```java String hashKey = "myHash"; String field1 = "field1"; String value1 = "value1"; String field2 = "field2"; String value2 = "value2"; redisTemplate.opsForHash().put(hashKey, field1, value1); redisTemplate.opsForHash().put(hashKey, field2, value2); ``` 可以使用opsForHash()方法获取HashOperations对象,然后调用put()方法将指定字段和对应值存储到hash。 当然,还可以使用其他的方法进行操作,例如获取hash指定字段的值、获取全部字段和值等等。详细的操作可以查看RedisTemplate和HashOperations类的方法。 最后,记得在应用程序关闭时释放Redis连接资源。 以上就是使用RedisTemplate存储hash类型数据到Redis的简要步骤,希望对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值