2016年2月17日星期三

使用Redis + Rails来实现一个抽奖系统

春节期间,做了一系列的关于抽奖的小游戏,当大量的用户同时涌入的时候,需要能够快速正确的发出奖品。数据库全部使用的是 MySQL + Redis,MySQL用来存储用户的相关信息,Redis仅仅用来存储奖品数量和待发奖品。为此,对学习到的相关内容以及过程中出现的问题进行说明。

1、A公司的抽奖项目。抽奖比较简单,每人一次,抽到的奖品也都是同一种,因此使用一个计数器来控制奖品数量即可,抽奖的代码很简单:

if  $redis.decr(today_redis_key) > 0
# 更新MySQL中对应用户的中奖信息
end

2、B公司的一个优惠码抽奖项目。这个比上面这种又多了一个限制条件,就是优惠码的面额是不同的,从5元到200元不等,每天放出的数量也是不同的。这里面主要的问题是用户中奖了怎么才能随机的发出这些数量不同的优惠码,而且要保证不能多发,重复发。
         我的处理方法是设置一个奖池,将今天放出的所有优惠码放到 Redis 的 Set 里面,中奖用户从里面随机拿出一个,由于 Redis 中 Set 的 spop 函数是随机的,因此可以保证随机性。具体可以参考这里

项目中出现的问题:

  1. 高估了 MySQL在做 count 操作时候的性能,当几十万用户同时涌入的时候,抽奖函数没有问题,页面上显示中奖人数的地方反而成了性能瓶颈,这个也是当时测试不充分造成的;
  2. 对Redis操作尽量保证数据的一致性;