0
点赞
收藏
分享

微信扫一扫

千万用户3毫秒内抽奖100名如何实现?

千万用户3毫秒内抽奖100名如何实现?_数据

🍁 作者:知识浅谈,CSDN签约讲师,CSDN博客专家,华为云云享专家,阿里云专家博主
📌 擅长领域:全栈工程师、爬虫、ACM算法
💒 公众号:知识浅谈

🤞千万用户3毫秒内抽奖100名如何实现?🤞

正菜来了⛳⛳⛳

🎈场景再现

某618活动,零点的时候从关注的用户中抽出100个人进行超级某东e卡发放,预计全网超过1000万用户参加关注抽奖活动,要求 “同一用户不能重复参与,同一用户不允许二次开奖”,为了满足要求,请给出解决方案。

🎈解决方案

🍮原始实现方法

- rand() 随机产生一个随机数
select * from 关注用户表 order by rand() desc limit,0,100

预计千万级别的对技术倒排大概率凉凉。

🍮执行100次下边的sql

效率可以,不过要执行两次SQL,并发环境下有原子性问题,切不能保证不会重复中奖

offset = SELECT FLOOR(RAND() * COUNT(*)) AS offset from 关注用户表
select * from 关注用户表 limit offset,1

🍮基于Redis Set集合做随机弹出

📐第 1 步:
在用户关注直播间在写入MySQL关注用户表时额外在Redis:增加一个userlist Set集合,存储用户编号。
Redis Seti可以保证全局唯一,且数据基于Hash乱序存储,取出的直接就是随机值。

sadd userlist xxxid

预计用户编号长整型,1000万用户占用空间大概500MB。

100万50mb, 1000万500MB,不会对内存造成很大压力(redis虽然怕大key,但是在内存可控范围内,小key很多却不会有什么问题)

千万用户3毫秒内抽奖100名如何实现?_redis_02


📐第 2步:

抽奖的时候,直接使用spop弹出随机100个用户编号即可,这个操作是原子性的,先弹出再返回,在加上Redist命令队列单线程不存在并发问题,这样杜绝了重复获奖的可能。

千万用户3毫秒内抽奖100名如何实现?_redis_03


📐第 3步:

下一步执行1次select ini语句,提取数据,因为都是通过主键提取,效率快也不存在in索引失效问题,但要注意in的数量上限是1000个,超过1000个备选项要拆成多个in.

🍮摆脱MySQL,纯Redis方案

进阶方案,内存富裕可用

因为抽奖结果页面通常只显示用户昵称,我们还可以使用Rdis提速,用内存换时间。具体做法是

千万用户3毫秒内抽奖100名如何实现?_数据_04


估算千万用户需要3G左右内存,spop提取速度完全可控制在3ms内完成,且不会重复。

TIPS:Redis不怕Key多,就怕大Key.

测试结果:

千万用户3毫秒内抽奖100名如何实现?_解决方案_05


千万用户3毫秒内抽奖100名如何实现?_解决方案_06


1000 次pop执行时间2565

🍚总结

以上就是千万用户3毫秒内抽奖100名如何实现的。

举报

相关推荐

0 条评论