08、你的代码有Bug!
不知道看完上面的代码你们有没有看出问题, 有喜欢点赞的帅逼 就很直接看出两个问题:
- 你的去重功能为什么是在发送消息之前就做了?万一你发送消息失败了怎么办?
- 你的去重功能存在并发的问题吧?假设我有两条一样的消息,消费的线程有多个,然后该两条线程同时查询Redis,发现都不在Redis内,那这不就有并发的问题吗
没错,上面这两个问题都是存在的。 但是,我这边都不会去解决 。
先来看第一个问题:

对于这个问题,我能扯出的理由有两个:
- 假设我发送消息失败了,在该系统也不会通过回溯MQ的方式去重新发送消息( 回溯MQ重新消费影响太大了 )。我们完全可以把发送失败的 userId 给记录下来(后面会把相关的日志系统给完善),有了 userId 以后,我们 手动批量重新发 就好了。这里手动也不需要业务方调用接口,直接通过类似 excel 的方式导入就好了。
- 在业务上,很多发送消息的场景 即便真的丢了几条数据,都不会被发现 。有的消息很重要,但有更多的消息并没那么重要,并且我们 即便在调用接口才把数据写入Redis,但很多渠道的消息其实在调用接口后,也不知道是否真正发送到用户上了 。

再来看第二个问题:

如果我们要仅靠Redis来实现去重的功能,想要完全没有并发的问题,那得上 lua 脚本,但上 lua 脚本是需要成本的。去重的实现需要依赖两个操作: 查询和插入 。查询后如果没有,则需要添加。那查询和插入需要保持 原子性 才能避免并发的问题
再把视角拉回到我们 为什么要实现去重功能 :
