大促节零点时,抽奖从关注的设计用户中抽出N个人进行礼品发放,预计全网超过千万用户参加关注抽奖活动,千万要求:
2.1 最原始
rand(),用s级对每行随机产生一个随机数
select * from 关注用户表 order by rand() desc limit,0,100
预计千万级别的对技术倒排大概率凉凉。
2.2 N次随机选择SQL
效率可以,设计不过要先后执行两条SQL,千万并发时有原子性问题,用s级且RAND函数不能保证不重复中奖。抽奖
offset = SELECT FLOOR(RAND() * COUNT(*)) AS offset from 关注用户表
select * from 关注用户表 limit offset,1
2.3 Redis Set随机弹出
step1:在用户关注直播间在写入MySQL关注用户表时,再往Redis增加一个userlist Set,存储用户编号。可保证用户全局唯一(避免用户反复的取消和关注影响数据记录),且数据基于Hash乱序存储,取出的直接就是随机值。
sadd userlist xxxid
预计用户编号long类型,100万50MB, 1000万用户也仅500MB。
step2:抽奖时,直接使用spop,弹出随机的100个用户编号,该操作是原子性,先弹出再返回,在加上Redist命令队列单线程,不存在并发问题,杜绝重复中奖。
step3:执行1次select in,提取数据,因为都是通过主键提取,效率快也不存在in索引失效问题,但要注意in的数量上限是1000个,超过1000个备选项要拆成多个in。
2.4 纯Redis
内存充足不差钱时可用。因为抽奖结果页面通常只显示用户昵称,还可使用Rdis提速,用内存换时间。
sadd userlist '123456:ikun'
sadd userlist '123456:akun'
sadd userlist '123456:bkun'
估算千万用户需3G内存,spop提取速度完全可控制在3ms内完成,且不重复。
Redis不怕Key多,只是怕大Key。测试结果:
1000次pop执行时间2565,即每次 pop 只需 2.5ms。
责任编辑:武晓燕 来源: JavaEdge ms级抽奖MySQL(责任编辑:热点)
光正眼科(002524.SZ):3月18日首次回购103.5万元股份 最高成交价为10.35元/股
京津城际铁路将检测调试 铁路部门提醒旅客关注12306网站公告