想请教一下各位大佬们,我们假想一个现在有几十万或者几百万的用户在点击一个图片,点击图片我们会发送一个短信给用户,同个用户不论点击多少次图片,我们期望每个用户只能收到一条消息,也就是一个用户只能发送一条消息。
每点击图片,我们 new 一个 message 一个进程异步扔到队列去消费,当消息发送出去我们会记录一条 log,发送前我们会去 count 一次 log,如果发过就不要发。
针对这种场景,大家有啥建议,发散思维,一起聊聊,跟老哥们请教一下。
我想到的是:
1.表唯一索引
2.事务+乐观锁
如果这样还是会存在部分用户发送了多条消息会是什么情况?
1
zhuzhibin OP 🚘🚘🚘🚘🚘🚘🚘🚘🚘🚘
|
2
936053688 2020-11-30 23:42:55 +08:00
redis 分布式锁如何?
|
3
Jooooooooo 2020-11-30 23:44:44 +08:00
这种防重不用特别严谨的场景 redis 的 setnx 搞定
|
4
zhuzhibin OP @Jooooooooo 如果说点击加 1s 锁 ,用户发起两次请求,第一次一直 loading 可能响应了 20s,用户觉得好像没点到在第一次响应完之前又点了很多次,这时候其实第一次的锁已经失效了。反正我遇到过类似场景,有部分的重复数据,很头疼,有什么好的定位排查方法吗
|
5
zhuzhibin OP 起 N 个进程同时消费队列 如果上面说的都做了 是一定会杜绝重复数据么 之前遇到过 review 代码该做的都做了,但是拉数据就是会有部分重复的,或者重复消费的,如果针对这种问题,有老哥可以大致分析一下整一个 flow 是如何流转的吗,以及会产生什么问题,要怎么去避免,出现问题如何更好的排查。小白请教哈,勿喷
|
7
crazyhorse 2020-12-01 08:43:21 +08:00
你这需求表唯一索引就可以了,你的顺序有点问题。图片 ID 和 user id 建个联合唯一索引,如果 insert 成功就执行你的队列、失败就直接结束
|
8
CURD663 2020-12-01 09:34:17 +08:00
@crazyhorse 同意,建个唯一索引,第一次能插入成功,后面插入失败不用管.
|
9
zhuzhibin OP @crazyhorse 如果说某个场景这个表同个用户会多条记录呢?例如某一天可以最多发两条消息 要怎么设计了 这时候不能唯一索引
|
10
zhuzhibin OP @CURD663 常规来说的确是这样 唯一索引 事务来保证唯一 如果说某种情况会存在两天记录呢
|
11
serical 2020-12-01 10:07:54 +08:00 via iPhone
给用户 id 加分布式锁
|
12
936053688 2020-12-01 11:38:14 +08:00
@zhuzhibin 哦,发现场景不一样。你是接收后推消息到队列,然后消费消息去发送短信;如果只是过滤用户的话,感觉可以参考前不久看到的布隆过滤器概念,用户点击过后,用户编码哈希过后校验位图,如果位图存在则已点击过,不发消息;未点击过,加入位图,发送消息。个人浅见,互相学习。
|
13
Dingjiangnan 2020-12-01 12:18:40 +08:00
@zhuzhibin Redisson
|