redis用list做消息隊列的實現示例
leftPush消息入隊,rightPop對應,消息出隊。
rightPop(RedisConstant.MQ_LIST, 0L, TimeUnit.SECONDS)阻塞出隊,0表示永久阻塞
生產消息服務
@Service public class RedisService { @Autowired private RedisTemplate<String, String> redisTemplate; public Object publish() { OrderDTO dto = new OrderDTO(); dto.setId(1); dto.setCreateTime(new Date()); dto.setMoney("12.34"); dto.setOrderNo("orderNo1"); String s = JSON.toJSONString(dto); ListOperations<String, String> listOperations = redisTemplate.opsForList(); //leftPush和rightPop對應,左邊入隊,右邊出隊 listOperations.leftPush(RedisConstant.MQ_LIST, s); //因為出隊是阻塞讀取的,所以上一步入隊後,數據立刻就被驅走瞭,下一步size=0 Long size = listOperations.size(RedisConstant.MQ_LIST); List<String> list = new ArrayList<>(); if (size != null && size > 0) { list = listOperations.range(RedisConstant.MQ_LIST, 0, size - 1); } return list; } }
測試
@RestController @RequestMapping("redisList") public class RedisListController { @Autowired private RedisService redisService; @GetMapping("publish") public Object publish() { return redisService.publish(); } }
消費消息服務,定時任務
@Component public class RedisConsumeTask { @Autowired private RedisService redisService; @TaskLock(RedisConstant.CONSUME_REDIS_LIST) @Scheduled(cron = "0/10 * * * * ?") public void consumeMqList() { redisService.consumeMqList(); } } @Service @Slf4j public class RedisService { @Autowired private RedisTemplate<String, String> redisTemplate; public void consumeMqList() { ListOperations<String, String> listOperations = redisTemplate.opsForList(); //0時間,表示阻塞永久 //待機一小時後,再次發消息,消費不瞭瞭,阻塞有問題啊。還得輪尋啊 //String s = listOperations.rightPop(RedisConstant.MQ_LIST, 0L, TimeUnit.SECONDS); String s = listOperations.rightPop(RedisConstant.MQ_LIST); if (s == null) { return; } log.info("{} = {}", RedisConstant.MQ_LIST, s); OrderDTO dto = JSON.parseObject(s, OrderDTO.class); log.info("dto = {}", dto); } }
日志
@Component @Aspect public class TaskLockAop { @Autowired private RedisLockRegistry redisLockRegistry; @Around("execution(@TaskLock * * (..))") public Object taskAround(ProceedingJoinPoint pjp) throws Throwable { TaskLock taskAnnotation = ((MethodSignature)pjp.getSignature()).getMethod().getAnnotation(TaskLock.class); String lockKey = taskAnnotation.value(); Lock lock = redisLockRegistry.obtain(lockKey); try { lock.tryLock(30L, TimeUnit.SECONDS); System.out.println("任務開始, " + lockKey + ", " + new Date()); return pjp.proceed(); } finally { lock.unlock(); System.out.println("任務結束, " + lockKey + ", " + new Date()); } } }
測試
http://localhost:9040/redisList/publish
["{“createTime”:1574394538430,“id”:1,“money”:“12.34”,“orderNo”:“orderNo1”}"]
下面一直阻塞,任務開始瞭,不收到消息,永遠不會結束。
阻塞有問題,改用輪詢瞭。
先啟動發送消息服務,發送消息。後啟動消費消息服務,可以消費消息。這一點,比發佈訂閱要穩定。
關聯項目https://github.com/mingwulipo/cloud-demo.git
到此這篇關於redis用list做消息隊列的實現示例的文章就介紹到這瞭,更多相關redis list消息隊列內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- java如何使用redis加鎖
- 關於SpringBoot 使用 Redis 分佈式鎖解決並發問題
- SpringBoot基於Redis的分佈式鎖實現過程記錄
- Redis中pop出隊列多個元素思考
- Redis在項目中的使用(JedisPool方式)