Commit a6c92816f0fb5801c27f6dc74cc0ac9542622b86
1 parent
0f31ce7e
fix: 解决 redis mq 消息丢失问题
Showing
1 changed file
with
20 additions
and
1 deletions
yudao-framework/yudao-spring-boot-starter-mq/src/main/java/cn/iocoder/yudao/framework/mq/scheduler/PendingMessageScheduler.java
| ... | ... | @@ -3,6 +3,8 @@ package cn.iocoder.yudao.framework.mq.scheduler; |
| 3 | 3 | import cn.iocoder.yudao.framework.mq.core.RedisMQTemplate; |
| 4 | 4 | import cn.iocoder.yudao.framework.mq.core.stream.AbstractStreamMessageListener; |
| 5 | 5 | import lombok.extern.slf4j.Slf4j; |
| 6 | +import org.redisson.api.RLock; | |
| 7 | +import org.redisson.api.RedissonClient; | |
| 6 | 8 | import org.springframework.beans.factory.annotation.Autowired; |
| 7 | 9 | import org.springframework.beans.factory.annotation.Value; |
| 8 | 10 | import org.springframework.data.redis.connection.stream.Consumer; |
| ... | ... | @@ -17,6 +19,7 @@ import org.springframework.scheduling.annotation.Scheduled; |
| 17 | 19 | |
| 18 | 20 | import java.util.List; |
| 19 | 21 | import java.util.Map; |
| 22 | +import java.util.concurrent.TimeUnit; | |
| 20 | 23 | |
| 21 | 24 | /** |
| 22 | 25 | * 这个定时器用于处理,crash 之后的消费者未消费完的消息 |
| ... | ... | @@ -24,19 +27,35 @@ import java.util.Map; |
| 24 | 27 | @Slf4j |
| 25 | 28 | @EnableScheduling |
| 26 | 29 | public class PendingMessageScheduler { |
| 27 | - | |
| 30 | + private static final String LOCK_KEY = "redis:pending:msg:lock"; | |
| 28 | 31 | @Autowired |
| 29 | 32 | private List<AbstractStreamMessageListener<?>> listeners; |
| 30 | 33 | @Autowired |
| 31 | 34 | private RedisMQTemplate redisTemplate; |
| 32 | 35 | @Value("${spring.application.name}") |
| 33 | 36 | private String groupName; |
| 37 | + @Autowired | |
| 38 | + private RedissonClient redissonClient; | |
| 34 | 39 | |
| 35 | 40 | /** |
| 36 | 41 | * 一分钟执行一次 |
| 37 | 42 | */ |
| 38 | 43 | @Scheduled(fixedRate = 60 * 1000) |
| 39 | 44 | public void processPendingMessage() { |
| 45 | + final RLock lock = redissonClient.getLock(LOCK_KEY); | |
| 46 | + try { | |
| 47 | + // 尝试加锁,最多等待 30 秒,上锁以后 60 秒自动解锁 | |
| 48 | + boolean lockFlag = lock.tryLock(30, 60, TimeUnit.SECONDS); | |
| 49 | + if (lockFlag) { | |
| 50 | + execute(); | |
| 51 | + } | |
| 52 | + } catch (InterruptedException e) { | |
| 53 | + log.error("获取锁失败", e); | |
| 54 | + } | |
| 55 | + | |
| 56 | + } | |
| 57 | + | |
| 58 | + private void execute() { | |
| 40 | 59 | StreamOperations<String, Object, Object> ops = redisTemplate.getRedisTemplate().opsForStream(); |
| 41 | 60 | |
| 42 | 61 | for (AbstractStreamMessageListener<?> listener : listeners) { | ... | ... |