我将请求的端口日志信息写到了 ./stat.log 文件当中,然后使用 AB 压测工具做压测:
ab -n 1000 -c 100 http://www.load_balance.com/buy/ticket
统计日志中的结果,3001-3004 端口分别得到了 100、200、300、400 的请求量。
这和我在 Nginx 中配置的权重占比很好的吻合在了一起,并且负载后的流量非常的均匀、随机。
具体的实现大家可以参考 Nginx 的 Upsteam 模块实现源码,这里推荐一篇文章《Nginx 中 Upstream 机制的负载均衡》:
https://www.kancloud.cn/digest/understandingnginx/202607
秒杀抢购系统选型
回到我们最初提到的问题中来:火车票秒杀系统如何在高并发情况下提供正常、稳定的服务呢?
从上面的介绍我们知道用户秒杀流量通过层层的负载均衡,均匀到了不同的服务器上,即使如此,集群中的单机所承受的 QPS 也是非常高的。如何将单机性能优化到极致呢?
要解决这个问题,我们就要想明白一件事:通常订票系统要处理生成订单、减扣库存、用户支付这三个基本的阶段。
我们系统要做的事情是要保证火车票订单不超卖、不少卖,每张售卖的车票都必须支付才有效,还要保证系统承受极高的并发。
这三个阶段的先后顺序该怎么分配才更加合理呢?我们来分析一下:
下单减库存

当用户并发请求到达服务端时,首先创建订单,然后扣除库存,等待用户支付。
这种顺序是我们一般人首先会想到的解决方案,这种情况下也能保证订单不会超卖,因为创建订单之后就会减库存,这是一个原子操作。
但是这样也会产生一些问题:
在极限并发情况下,任何一个内存操作的细节都至关影响性能,尤其像创建订单这种逻辑,一般都需要存储到磁盘数据库的,对数据库的压力是可想而知的。
如果用户存在恶意下单的情况,只下单不支付这样库存就会变少,会少卖很多订单,虽然服务端可以限制 IP 和用户的购买订单数量,这也不算是一个好方法。