[!]小白请教高并发确保不会有重复数据的问题

2020-11-30 23:26:36 +08:00
 zhuzhibin

想请教一下各位大佬们,我们假想一个现在有几十万或者几百万的用户在点击一个图片,点击图片我们会发送一个短信给用户,同个用户不论点击多少次图片,我们期望每个用户只能收到一条消息,也就是一个用户只能发送一条消息。

每点击图片,我们 new 一个 message 一个进程异步扔到队列去消费,当消息发送出去我们会记录一条 log,发送前我们会去 count 一次 log,如果发过就不要发。

针对这种场景,大家有啥建议,发散思维,一起聊聊,跟老哥们请教一下。

我想到的是:
1.表唯一索引
2.事务+乐观锁

如果这样还是会存在部分用户发送了多条消息会是什么情况?

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

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/730772

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX