高并发情景下的抢红包设计方案

假设一个需求,在某个预告活动中准备了10w个红包,100w人在某个时间点去开抢,每人只能抢1次,如何保证性能和准确性:

  1. 分析瓶颈
    • 查询用户是否已参与过活动
    • 获取一个可抢的红包,保证多个人不能获取到同一个红包
    • 建立红包与用户的关系
  2. 设计数据结构解决瓶颈问题
    • 查询用户是否已参与过活动:可以使用Set的特性,集合中不能出现重复的数据,每个用户发起抢的动作就将用户标识放入Set中,如果Set中已存在这个用户标识,则说明用户不可再抢了
    • 获取一个可抢的红包:可以使用队列的数据结构,每次获取红包都是一个出队的动作,解决了多人获取同一个红包和超发的问题
    • 建立红包与用户的关系:同样使用队列的数据结构,每次建立都是一个入队动作,使用单独线程每秒尝试出队多个,批量存储到数据库中
  3. 实现功能
    • 准备工作:生成可抢红包,入队redis的list结构,命令为RPUSH
    • 用户发出抢的请求:用户标识写入redis的Set中,命令SADD,返回1标识插入成功,可继续获取红包,返回0则为已抢,直接返回
    • 获取红包:list出队一条红包数据,命令为LPOP,如果返回不为nil时,代表获取成功,继续下一步,反之则说明已抢完,返回
    • 建立红包与用户的关系:构建红包与用户的关系对象,入队Redis的list,使用单独线程每秒尝试出队1000个(举例),批量存储到数据库中
  4. 需求扩展
    • 10w红包不是先到先得,而是有一定随机性
      (1)可以在构建可抢红包列表时,根据需求算法,构建一个包含无红包item的的列表入队,出队判断如果此item代表 无红包时返回,反之则进行建立红包与用户的关系
    • 每人可以抢N次,N>=1
      (1)使用redis的string数据结构中的INCR命令,用户发起抢的动作,则调用INCR,如果返回数据>N,说明抢的次数已达到上限
  5. 其他
    • redis并不是必须的,如果web服务器无横向扩展需要也可以使用内存内的相关数据结构实现,同样的如果其他中间件可提供相似的数据结构功能,也可以替换redis
  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值