前言

Github:https://github.com/HealerJean

博客:http://blog.healerjean.com

我想在座的各位,应该没有人没抢过红包吧

一、发红包后台操作:

1、在数据库中增加一条红包记录 2、存储到Cache(Redis),设置过期时间(比如hash存储),存储抢红包的人数N,金额

二、抢红包后台操作:

1、抢红包

抢操作在Cache层完成,通过原子减操作进行红包数递减(拆红包会对他进行递减),到0就说明抢光了,最终实际进入后台拆操作的量不大,通过操作的分离将无效请求直接挡在Cache层外面。这里的原子减操作并不是真正意义上的原子减操作,是其Cache层提供的decr,通过比较版本号不断尝试,有时候可能进来的时候可以抢红包,但是会有抢到了拆开发现领完了的情况。

2、拆红包

2.1、金额如何分配

有的架构师想过预先分配金额,然后放到队列里面去,但是这种方法不好,以为你会占用内存

随机,额度在0.01和剩余平均值*2之间。

发100块钱,总共10个红包,那么平均值是10块钱一个,那么发出来的红包的额度在0.01元~20元之间波动。
 
当前面3个红包总共被领了40块钱时,剩下60块钱,总共7个红包,那么这7个红包的额度在:0.01~(60/7*2)=17.14之间。

  

将拆红包红包ID的请求放入请求队列中,如果发现超过红包的个数,直接返回。

拆完红包之后,当拆了红包后会更新剩余金额和个数。然后异步调用数据库保存数据,如果处理成功,然后调用财付通(存银子的地方) 相关操作,这样的话微信和财付通两边都保存了交易记录,方便以后对账。因为异步的原因,有可能我们抢到红包,看到后台看余额的时候回出现没有的情况。

3、一些问题

3.1、这样的红包分配,压力大不

抢到红包的人数和红包都在一条cache记录上,没有太大的查询压力。

3.2、有没有从数据上证明每个红包的概率是不是均等?

不是绝对均等,就是一个简单的拍脑袋算法。会出现金额一样的,但是手气最佳只有一个,先抢到的那个最佳。

3.3、采用实时算出金额是出于什么考虑?

实时效率更高,预算才效率低下。预算还要占额外存储。因为红包只占一条记录而且有效期就几天,所以不需要多大空间。就算压力大时,多加几台机器就是了。

3.4、为什么要分离抢和拆?

总思路是设置多层过滤网,层层筛选,层层减少流量和压力。因为抢操作是业务层,拆是入账操作,第一个操作太重了,而且中断率高。 从接口层面看,第一个接口纯缓存操作,搞压能力强,一个简单查询Cache挡住了绝大部分用户,做了第一道筛选,所以大部分人会看到已经抢完了的提示。

ContactAuthor