记录一下,rabbitmq重复消费问题

前段时间,在portainer看调试日志,发现一个问题,一个业务插入了两条数据。我滴个乖乖,这还得了,赶紧排查(dev环境_);
赶紧看代码,找业务逻辑,整体流程是:前端数据上传->入队->mq消费->入库;然后看入库部分的代码逻辑是没问题的;但是走了MQ,就考虑到了可能是重复消费了。
借此记录一下,关于重复消费问题以及我的解决办法。鄙人不擅长组织语言,经过一些资料查找(万能的百度),总结了一下网络大神的专业解释:
1.生产者在发送消息给mq时,由于网络波动,可能导致生产者收不到mq的应答,这时候,生产者会再次发送消息。
2.同样的,mq在把消息给到消费者时,网络波动,mq没有收到消费者的应答,mq就会再次发送给消费者。
3.多消费者,如果未配置消费组,同样可能导致重复消费。
接下来说说我的解决方案,重复消费,最终导致的问题就是产生了重复数据,那何不再产生数据的时候,确定数据的唯一性。由于是大批量的数据,不可能用数据库的唯一约束来保证,那就从业务处入手。论一台机器什么读写最快?当然是内存,MQ终究是网络传输,速度能快得过内存?
说到内存,那就是首先选redis,利用redis设置一个唯一标识,作为锁,redis直接在消费开始时,判断是否锁已经存在,如果存在则跳过本次业务,否则上锁,业务处理完毕,释放锁。
放一段code思路:

//加锁,超时视情况酌情而定
 public boolean getLock(String lockId, long timeout) {
   Boolean success = redisTemplate.opsForValue().setIfAbsent(lockId, "lock",timeout, TimeUnit.SECONDS);
   return success != null && success;
 }
 //释放锁
 public void releaseLock(String lockId) {
	redisTemplate.delete(lockId);
 }
 -------------------业务中----------------------
 if(getLock("uni-key",3)){
   try{
    	//TODO
   }catch(Exception e){
   	releaseLock("uni-key");
   }finally{
   	releaseLock("uni-key");
   }
 }

有想法或建议,欢迎讨论、指正~