并发的时候 怎么保证被抽的奖品确实还有数量
数据库 mysql 和 redis 都可以用
v 友们有什么好思路吗
1
woshipanghu OP 我自己想的一个逻辑
奖品数量如果只剩下 1 个的时候,用户抽到这个奖品的时候需要去 redis 拿一个令牌,拿到令牌的用户获得这个奖品。 其他用户,随机获取剩余奖品中的一样。 |
2
jindeq 2020-02-12 22:27:10 +08:00 via Android
@woshipanghu 并发量足够大的情况下,redis 可能崩的情况下,还需要其他的途径确保唯一性
|
3
woshipanghu OP @jindeq 只要服务器正常 redis 我倒不担心崩掉,并发只要抢最后一个奖品的时候会用 redis redis 的并发不会太高
|
4
lsylsy2 2020-02-12 22:35:42 +08:00
比如奖品有 100 件,中奖率 1%
那么就建一个队列,里面有 10000 个 object,object 的内容是中奖或不中奖,提前生成内容随机打乱 每个“抽奖”的行为就是从队列取一个 object,取不到=谢谢惠顾 高并发的话,可以把 1 个 10000 长度的队列切成 100 个 100 长度的队列,互相独立,每个 client 随机选一个队列去取。 |
5
sujin190 2020-02-12 22:43:03 +08:00
@lsylsy2 #4 抽奖不是秒杀,假设活动持续三天那么应该是尽可能的匹配人流分布在整个时间段内平均的抽中,否则万一一开始就全抽完了,后面就没法玩了,所以用队列看起来不是很科学吧
|
7
sujin190 2020-02-12 22:47:38 +08:00
我感觉不需要那么复杂,加锁就是了吧,反正概率算法确定是否中奖这个不需要加锁,所以完全可以先抽中从奖池真正取奖品的时候加锁保证唯一性就好了,抽奖人可能很多,中奖人不可能也很多吧
如果中奖人也很多,那说明你这奖品也不值钱,那就更无所谓了,就算有并发问题,多发个几十几百的这算个毛事,根本无需考虑吧 |
8
sujin190 2020-02-12 22:50:44 +08:00
@optional #6 队列的问题是抽奖人数无法准确预估,如果预估比实际少,一开始很快抽完了会影响活动效果,预估比实际多,受队列限制无法自适应提高中奖概率,也会影响活动效果
|
9
abcbuzhiming 2020-02-12 23:21:59 +08:00
我见过一个简单的思路,抽奖的请求全部排队,只允许和当前奖品剩余数量相等的请求数进入队列,超出的请求立刻返回“未中奖”。然后进入队列的请求再进行抽奖逻辑,绝不会超出剩余奖品,而且用户体验也还可以,当然对上专业黑产羊毛党会很头疼
|
10
lxml 2020-02-12 23:24:33 +08:00
提前按照机器分好,放在内存里,然后对账,准确性和并发你只能选一样
|
11
FaceBug 2020-02-12 23:26:33 +08:00
@sujin190 抽奖时段如果有三天这种跨度,一般都会分场次了。不需要绝对的考虑公平的问题,因为没法预估第二天流量是否还会保持第一天的热度,也没法确认第一天的热度到底有多高是吧。如果只有一个场次,持续三年,人为的限制了第一天的中奖率,结果第二天第三天没人来了,要么奖品送不完,要么认为干预,导致来的几乎都有奖。
|
12
FaceBug 2020-02-12 23:28:13 +08:00
本质上是和秒杀一个思路的。先判断是否中奖,中奖了再从奖品队列弹出一个奖品。如果奖品不足,也认为是没有中奖。
|
13
fewok 2020-02-12 23:33:31 +08:00
预估下多少并发,每秒 100W 次? 1 亿次?
|
14
wAtcher789 2020-02-12 23:35:07 +08:00 via Android
@abcbuzhiming 小米 :我怀疑你看了我们代码
|
15
aliipay 2020-02-13 00:37:35 +08:00
@wAtcher789 小米: 前端 js hash 一下 uid,直接过滤大部分用户请求 (当然后端也会同样 hash 处理), 你不中奖有可能是你 uid 不好 [:doge]
|
16
horkooo 2020-02-13 00:54:04 +08:00 via Android
题目描述比较简单,可以理解成秒杀的场景。对应秒杀场景的解决方案。同时也要兼顾活动的可持续性。每天放出的奖是剩余奖品除以剩余天数。抽奖,奖品,中奖数据全部放 redis,最后合并写库就行了。
|
18
18ac0877 2020-02-13 01:02:30 +08:00
将抽奖和公布结果分离,xxx-xxx 时间抽奖,xxx-xxx 时间后台根据算法抽奖,xxx 时间公布结果。
|
19
18ac0877 2020-02-13 01:09:34 +08:00
另一个办法:后台先预定哪些用户能中奖,提前算好,如果该用户抽奖了直接返回中奖。
|
20
murmur 2020-02-13 07:36:38 +08:00
return 未中奖
|
21
lqw3030 2020-02-13 08:58:56 +08:00
削峰,然后进队列
|
22
hand515 2020-02-13 10:14:15 +08:00
先通过随机数,把一部分流量的直接返回没抽中,这个量可以根据实际流量配置,如 50%。
|
23
xiaoyouqiang 2020-02-13 10:55:30 +08:00
这个问题说的比较抽象,大并发解决方案本身就是一个大的领域。什么队列,缓存,复杂均衡都是手段,你要结合自己的情况,搭建一套大并发体系。
|
24
LoremIpSum 2020-02-13 22:29:53 +08:00
1.请求进来
2.根据预先配置好的中奖概率来判断这个请求能不能中奖 3.如果可以中奖,锁定库存( redis 分布式锁),返回结果,反之直接返回未中奖 |
25
hankai17 2020-02-13 23:24:52 +08:00
是微 xin 的发 red bag 吗?
|