大并发下的抽奖有什么好的实现思路吗?

2020-02-12 22:06:58 +08:00
 woshipanghu

并发的时候 怎么保证被抽的奖品确实还有数量

数据库 mysql 和 redis 都可以用

v 友们有什么好思路吗

4366 次点击
所在节点    程序员
25 条回复
woshipanghu
2020-02-12 22:23:09 +08:00
我自己想的一个逻辑
奖品数量如果只剩下 1 个的时候,用户抽到这个奖品的时候需要去 redis 拿一个令牌,拿到令牌的用户获得这个奖品。
其他用户,随机获取剩余奖品中的一样。
jindeq
2020-02-12 22:27:10 +08:00
@woshipanghu 并发量足够大的情况下,redis 可能崩的情况下,还需要其他的途径确保唯一性
woshipanghu
2020-02-12 22:30:20 +08:00
@jindeq 只要服务器正常 redis 我倒不担心崩掉,并发只要抢最后一个奖品的时候会用 redis redis 的并发不会太高
lsylsy2
2020-02-12 22:35:42 +08:00
比如奖品有 100 件,中奖率 1%
那么就建一个队列,里面有 10000 个 object,object 的内容是中奖或不中奖,提前生成内容随机打乱
每个“抽奖”的行为就是从队列取一个 object,取不到=谢谢惠顾
高并发的话,可以把 1 个 10000 长度的队列切成 100 个 100 长度的队列,互相独立,每个 client 随机选一个队列去取。
sujin190
2020-02-12 22:43:03 +08:00
@lsylsy2 #4 抽奖不是秒杀,假设活动持续三天那么应该是尽可能的匹配人流分布在整个时间段内平均的抽中,否则万一一开始就全抽完了,后面就没法玩了,所以用队列看起来不是很科学吧
optional
2020-02-12 22:47:33 +08:00
@sujin190 用队列是可以的,把奖品按照时间分片,分成 n 个几个队列就好(比如队列名加入小时参数)。
sujin190
2020-02-12 22:47:38 +08:00
我感觉不需要那么复杂,加锁就是了吧,反正概率算法确定是否中奖这个不需要加锁,所以完全可以先抽中从奖池真正取奖品的时候加锁保证唯一性就好了,抽奖人可能很多,中奖人不可能也很多吧

如果中奖人也很多,那说明你这奖品也不值钱,那就更无所谓了,就算有并发问题,多发个几十几百的这算个毛事,根本无需考虑吧
sujin190
2020-02-12 22:50:44 +08:00
@optional #6 队列的问题是抽奖人数无法准确预估,如果预估比实际少,一开始很快抽完了会影响活动效果,预估比实际多,受队列限制无法自适应提高中奖概率,也会影响活动效果
abcbuzhiming
2020-02-12 23:21:59 +08:00
我见过一个简单的思路,抽奖的请求全部排队,只允许和当前奖品剩余数量相等的请求数进入队列,超出的请求立刻返回“未中奖”。然后进入队列的请求再进行抽奖逻辑,绝不会超出剩余奖品,而且用户体验也还可以,当然对上专业黑产羊毛党会很头疼
lxml
2020-02-12 23:24:33 +08:00
提前按照机器分好,放在内存里,然后对账,准确性和并发你只能选一样
FaceBug
2020-02-12 23:26:33 +08:00
@sujin190 抽奖时段如果有三天这种跨度,一般都会分场次了。不需要绝对的考虑公平的问题,因为没法预估第二天流量是否还会保持第一天的热度,也没法确认第一天的热度到底有多高是吧。如果只有一个场次,持续三年,人为的限制了第一天的中奖率,结果第二天第三天没人来了,要么奖品送不完,要么认为干预,导致来的几乎都有奖。
FaceBug
2020-02-12 23:28:13 +08:00
本质上是和秒杀一个思路的。先判断是否中奖,中奖了再从奖品队列弹出一个奖品。如果奖品不足,也认为是没有中奖。
fewok
2020-02-12 23:33:31 +08:00
预估下多少并发,每秒 100W 次? 1 亿次?
wAtcher789
2020-02-12 23:35:07 +08:00
@abcbuzhiming 小米 :我怀疑你看了我们代码
aliipay
2020-02-13 00:37:35 +08:00
@wAtcher789 小米: 前端 js hash 一下 uid,直接过滤大部分用户请求 (当然后端也会同样 hash 处理), 你不中奖有可能是你 uid 不好 [:doge]
horkooo
2020-02-13 00:54:04 +08:00
题目描述比较简单,可以理解成秒杀的场景。对应秒杀场景的解决方案。同时也要兼顾活动的可持续性。每天放出的奖是剩余奖品除以剩余天数。抽奖,奖品,中奖数据全部放 redis,最后合并写库就行了。
EminemW
2020-02-13 01:00:01 +08:00
@aliipay 所以有的人很容易中奖,身边一个长辈,有一段很迷小米一元购,抽中很多
18ac0877
2020-02-13 01:02:30 +08:00
将抽奖和公布结果分离,xxx-xxx 时间抽奖,xxx-xxx 时间后台根据算法抽奖,xxx 时间公布结果。
18ac0877
2020-02-13 01:09:34 +08:00
另一个办法:后台先预定哪些用户能中奖,提前算好,如果该用户抽奖了直接返回中奖。
murmur
2020-02-13 07:36:38 +08:00
return 未中奖

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

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

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

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

© 2021 V2EX