【架构设计】如何实现3ms内从1000w级别的用户里面随机抽奖出100名用户

        最近在学习it老齐的架构设计,课程里面有这样一个课题,如何实现3ms内从1000w级别的用户里面随机抽取出100m用户。

        首先,我们先从常规的常规的sql出发,如果要从数据表里面随机的选出几名员工的话,可能会使用mysql的相关函数

select username from user order by rand() limit 10

但是我们知道在mysql里面使用order by rand会让数据库性能呈指数级下降。因为MySQL会不得不去执行RAND()函数(很消耗CPU的时间),而且这是为每一条记录及取值,然后再对其排序,所以这种方法不推荐。

        那么,我们来考虑使用第二种改进的方案。

        方案二、

       offset = select FLOOR(RAND()*COUNT()) AS offset FROM 关注用户表;

        select * from 活动用户表 limit offset 1;

        性能尚可,但是因为要执行两条语句,所以可能存在原子性的问题,且不能保证不会存在重复中奖的可能性。

       接着,我们再深入思考,可不可以通过Redis这种方案来进行优化能

        方案三、基于redis set集合做随机弹出

        通过redis的set类型来做入栈和出栈的操作来随机抽出100名用户
     

        具体实现方法:在用户关注直播间的时候,写入MySQL的同时额外在Redis增加userlist Set集合,存储用户编号。

sadd userlist userid1 userid2 userid3...

添加完成之后,预计1000w用户预计占用500M内存空间。    

然后,从里面随机弹出100位用户即可。

 spop userlist 100

10000009
10000034
10000453
10000053
10000034
10000434
.....

select username from 关注用户表 where id in (10000009,10000034,10000453,10000053,10000034,10000434);

这种做法的好处是,使用redis来取代了mysql获取中奖员工编号,提升了效率, 属于用空间换时间的做法,大大的提升了效率,但是仍然没有完全摆脱MySQL,最后一步,仍然是从MySQL中取值,没有把效率发挥到极致。

最后,我来放大招了。

方案四、完全使用Redis实现

sadd userlist "10011515:gaos" "1004554454:ccf" "121432452:zhangxr"....

然后从里面随机弹出100个元素

spop userlist 100

最后,对于弹出的结果进行相应的处理,只显示对应的用户名称即可。

import redis
from random import randint

if __name__ == '__main__':
    redis_conn = redis.Redis(host="127.0.0.1", port=6379, password="")
    print(redis_conn)
    for i in range(100000):
        num_int = str(i).zfill(6)
        redis_conn.sadd("userlist", f"{randint(10000000,99999999)}:ccf{num_int}")
    s2 = redis_conn.spop("userlist", 10)
    print("获奖的员工为:")
    for s in s2:
        if len(s.decode("UTF-8").split(":")) > 1:
            print(s.decode("UTF-8").split(":")[1])

执行完成之后,可以发现pop操作的时间控制在了3ms内,该方案有效!

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值