千万级用户ms级抽奖N名设计方案

数据库 MySQL
在用户关注直播间在写入MySQL关注用户表时,再往Redis增加一个userlist Set,存储用户编号。可保证用户全局唯一(避免用户反复的取消和关注影响数据记录),且数据基于Hash乱序存储,取出的直接就是随机值。

1 需求

大促节零点时,从关注的用户中抽出N个人进行礼品发放,预计全网超过千万用户参加关注抽奖活动,要求:

  • 同一用户不能重复参与
  • 同一用户不允许二次中奖

2 设计方案

2.1 最原始

rand(),对每行随机产生一个随机数

select * from 关注用户表 order by rand() desc limit,0,100

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

2.2 N次随机选择SQL

效率可以,不过要先后执行两条SQL,并发时有原子性问题,且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
相关推荐

2019-12-09 09:52:38

设计软件数据库

2017-10-24 10:15:05

CDN突发池系统架构

2022-02-28 10:11:22

查询数据SQL

2012-08-21 09:42:24

设计架构设计原则

2018-04-09 13:40:55

防火墙支付平台方案

2012-08-09 09:52:41

移动APP推广沙龙

2011-05-10 14:53:27

专业显卡评测

2019-08-16 09:25:07

缓存NginxTomcat

2019-08-01 08:36:51

缓存系统并发

2022-05-18 10:07:29

EMQ车联网MQTT

2009-07-17 13:35:41

微软操作系统Windows 7升级方案

2011-11-09 11:05:38

惠普激光打印机

2022-02-22 10:29:24

分布式架构高可用

2018-08-17 10:43:00

2010-09-08 16:17:37

SIP协议栈

2020-08-25 16:55:05

云原生AWS金科文化

2012-02-14 00:01:22

2022-07-05 09:38:47

模型RBACABAC

2009-10-12 16:50:00

2009-10-19 13:50:57

布线设计方案
点赞
收藏

51CTO技术栈公众号