千万用户 3 毫秒内抽奖 100 名如何实现?
🍁 作者:知识浅谈,CSDN 签约讲师,CSDN 博客专家,华为云云享专家,阿里云专家博主
📌 擅长领域:全栈工程师、爬虫、ACM 算法
💒 公众号:知识浅谈
🔥 联系方式 vx:zsqtcc
🤞千万用户 3 毫秒内抽奖 100 名如何实现?🤞
正菜来了⛳⛳⛳
🎈场景再现
某 618 活动,零点的时候从关注的用户中抽出 100 个人进行超级某东 e 卡发放,预计全网超过 1000 万用户参加关注抽奖活动,要求 "同一用户不能重复参与,同一用户不允许二次开奖",为了满足要求,请给出解决方案。
🎈解决方案
🍮原始实现方法
预计千万级别的对技术倒排大概率凉凉。
🍮执行 100 次下边的 sql
效率可以,不过要执行两次 SQL,并发环境下有原子性问题,切不能保证不会重复中奖
🍮基于 Redis Set 集合做随机弹出
📐第 1 步:在用户关注直播间在写入 MySQL 关注用户表时额外在 Redis:增加一个 userlist Set 集合,存储用户编号。Redis Seti 可以保证全局唯一,且数据基于 Hash 乱序存储,取出的直接就是随机值。
预计用户编号长整型,1000 万用户占用空间大概 500MB。100 万 50mb, 1000 万 500MB,不会对内存造成很大压力(redis 虽然怕大 key,但是在内存可控范围内,小 key 很多却不会有什么问题)
📐第 2 步:抽奖的时候,直接使用 spop 弹出随机 100 个用户编号即可,这个操作是原子性的,先弹出再返回,在加上 Redist 命令队列单线程不存在并发问题,这样杜绝了重复获奖的可能。
📐第 3 步:下一步执行 1 次 select ini 语句,提取数据,因为都是通过主键提取,效率快也不存在 in 索引失效问题,但要注意 in 的数量上限是 1000 个,超过 1000 个备选项要拆成多个 in.
🍮摆脱 MySQL,纯 Redis 方案
进阶方案,内存富裕可用因为抽奖结果页面通常只显示用户昵称,我们还可以使用 Rdis 提速,用内存换时间。具体做法是
估算千万用户需要 3G 左右内存,spop 提取速度完全可控制在 3ms 内完成,且不会重复。TIPS:Redis 不怕 Key 多,就怕大 Key.测试结果:
1000 次 pop 执行时间 2565
🍚总结
以上就是千万用户 3 毫秒内抽奖 100 名如何实现的,希望有所帮助。
版权声明: 本文为 InfoQ 作者【知识浅谈】的原创文章。
原文链接:【http://xie.infoq.cn/article/c7ceba6e09cda7e05608c39de】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论