总之,总会有各种各样不同的可能会导致消息被重复发送,并且消息被重复接收。
既然消息重复发送是很难避免的,那么最有效的方法就是从处理阶段入手,核心其实就是要做幂等性处理。无论消息被消费了几次,消费端的处理逻辑都能保证不会有副作用。
每次消费了一条下消息之后都会在数据库中插入一条记录,记录下消费的消息id,下次消息到来时,就从数据库对应表中查看该条记录是否存在,存在的话则证明已经消费过了,拒绝本次消费;不存在的话则证明本次消费有效。
数据库唯一索引: 我们可以利用数据库唯一索引的唯一性来进行幂等性处理,在每次消费消息的时候,都将该条消息记录插入到数据库中,如果插入成功则证明消费成功,如果插入失败,则证明该条消息已经被消费过了。
但是由于insert语句自带行锁,且每个请求都要访问数据库,涉及到网络IO+磁盘IO,这里的开销是很大的。所以这个方案性能并不是很好。
加Redis分布式锁: 我们可以利用Redis的setnx命令来获取分布式锁,以消息id为key,如果消息已经保存过了,则获取不到分布式锁,如果消息没有保存过,则获取到分布式锁。因为redis的命令是单线程的,所以满足原子性,不会有并发安全问题。获取到了分布式锁之后然后再把该条记录保存在Mysql数据库中,做持久化存储,保障最终安全。没获取到的就不会被消费。这样可以大大加快速度。避免了大量线程进入mysql中。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。