关于抢红包的几种实现方式

随着双十一的临近,每天空闲时间除了睡觉就是抢红包,想想也是蛮拼的。周五晚回家的时候,在跟黄尼玛的闲聊中提到了抢红包背后的逻辑,觉得这是个挺有意思的问题,回来思考过后做一下分享。

我所理解的抢红包思路:接收到用户发来的请求,先查询是否有红包剩余,有则进行抽奖;如果抽不中直接返回,抽中了返回的同时把结果告诉数据库,红包库存减一。其实这跟秒杀商品是一个思路,只不过秒杀就不需要中间抽奖那一个过程。

对于抢红包这种流量特别大的活动,SLB(负载均衡)肯定是少不了的。假设现在一共有20台应用服务器,那如何保证应用服务器跟数据库间的同步就是一个难题。因为20台机器同时做这样的事情,会给数据库带来巨大的压力。下面就分享一下我想到的几种解决办法。

PS.先插一句,上面这个难题对于阿里来说根本不是事,在HFS、TDDL等强大中间件面前就是小菜一碟。


1⃣️

比较原始的办法,数据库采用主从结构。所有的写库操作都指向 master,读取则从 slave 里面取。

这里面有两个瓶颈,一个是主从直接同步的速度,另一个是 master 写入的效率。对于每一次写入,数据库都要上锁,因此很容易造成阻塞。同时,由于读取效率比写入效率高很多,所以每一次读取到的并不是最新的数据,到最后容易造成“超卖”现象。所以,这是一种实时性非常低的做法。


2⃣️

既然一个主数据库撑不住,那我们能不能多搞几个数据库呢?

这个也很简单,我们把红包数量一分为二十,每一台应用服务器搭配一套只属于自己的数据库。

这样做之后,每台服务器之间互不干扰,对于数据库的压力也变为原来的二十分之一。这种做法的好处是不言而喻的,但它的弊端也很明显,就是所有机器的库存不会在同一时刻卖光。对于红包活动来说还好,但如果是秒杀活动,就很可能出现“同时点击下单,你抢到我抢不到”的现象出现。


3⃣️

有没有能综合上述两种方式优点的方法呢?答案还是有的,只不过听起来可能“怪怪的”。既要实现同时抢光,又要让数据库只应对一台应用服务器给的压力,可以采用下面的办法:

20台服务器,其中的19台部署同样的100%返回不中奖的代码,而剩下的那一台则部署抽奖的代码。

在这种情况下,数据库只需要应对抽奖服务器带来的压力,而另外19台服务器因为不需要跟数据库进行通信,因此整体的响应时间比以前更短了。乍看可能会觉得这样做法不公平,因为访问命中那19台机器就意味着100%不中奖,而且在短时间内的多次请求都会命中同一台机器。但实际上在海量的访问面前,上面的三种办法中奖率都是一致的,具体的估算方式就不列出来了。


除了这三种方式,肯定还会存在更优的办法,不过暂时就没想出来咯~

« 返回