缘起
其实从2014年,微信推出微信红包,就有很多人揣测其中的算法是怎样的,知乎上很多人分析了很多。
我一直觉得,应该就是几个简单的约束,然后拍脑袋一个算法,不需要特别的要求。
但还是有很多人会替开发人员做一些考虑,比如“不能让一个人运气太差,连续抢到0.01,这会让用户体验很差”之类的要求,我觉得这是不可能的。
为什么?
很明显,微信红包这种极其高并发的请求,算法应该越简单越好,不可能有太复杂的人性化约束。另一方面,假设红包金额是完全随机的,那么一个人连续抢到0.01的概率其实是特别低的。
对于微信红包的建模和约束,很多人已经做过很好的分析了。
问题为:金额为M,分成N个红包。
约束其实就简单的一条——
每个红包的金额,都是精确到小数点后两位,且至少为0.01元。
没图没真相,我写的代码的效果如下(10块钱分成5个红包):
感觉结果还算正常,偶发太高的金额,这个可以通过控制最大的金额的上限,比如有人提出,微信内部的人员告知,最大的金额是剩余金额的平均值的两倍。这样是比较合理的,因为一旦一个人抢了太高的金额,后边的人很可能就只能在0.01左右徘徊了。
怎么办?
就随机而言,很容易想到正态分布。那么,均值选多少?方差选多少?
我的代码主体是下面这个函数:
它的逻辑很简单,每次把均值设为剩下金额的平均数,标准差设置为均值和最小金额(0.01)的差值,为何这样选取的理由其实是很明显了。
程序员的重点
我觉得算法不应该是重点,重点是如何设计一个适合收发红包的高并发架构!
以下观点来自于知乎上看文章(https://www.zhihu.com/question/22625187),以及自己的一些想法,不一定是好的,因为没实践过。
问题1:红包金额是事先分配好,然后逐个拿吗?
解释一下这个问题,意思是,比如10块钱分成3个,做法是分成2.00,3.00,5.00,然后第一个人来的时候占第一个位置,拿到了2.00……诸如此类。
答案是:肯定不需要啊。
如果事先分配好,假设你分配1000个红包,岂不是得用1000倍的空间来存放?
如果放在内存里,一台服务器岂不是很容易爆?
所以更好的方法应该是:
1. 类似查表的,给每个目前存活的红包(每个红包只能存活两天)编号,放在一张内存的表里;