背景
在MQ使用过程中要考虑很多异常情况,重复消费,幂等性是系统设计里必须考虑的一环。MQ本身对这个问题有做一些处理。比如kafka在内部定义了一个offset,每一条消息写入后都有一个offset,代表消息序号,消费端消费数据后,隔一段时间就会把自己消费过的消息的offset提交一下,下一次重启时候会从上次的offset处继续往下消费。
正常的情况下这样运行是没有问题的,但是系统设计需要考虑很多的宕机,断电,网络异常等极端情况,假设在消费端消费完数据还未上报offset的时候,这时消费端挂了,那么在下次消费时就可能出现重复消费的情况。
解决方案
重复消费只是个行为,重要的是如何保证系统幂等性。所谓幂等性就是保证系统不管接受多少次同样的请求,要能保证返回的结果是相同的。
为了保证幂等性,首先可以看后端的具体操作,比如后端接收数据后存入redis,并且使用的是string存储,那完全不需要做其他的操作,同一个key的value是会被覆盖的。但是这种场景一般比较少吧,既然都使用MQ来削峰了,后端何必搭个缓存,如果后端服务器处理速度跟不上,反而会造成redis中的数据冗余
如果后端接收数据后是存入MYSQL之类的数据库,重复消费甚至可能导致主键相同的异常,这时在消费端应该做主键的验证,可以在每一次消费后将消费过的消息ID存入redis,每一条消息过来先去redis中验证一下是否已经消费过。
网友评论