小米抢购限流峰值系统「大秒」架构解密2
为此,小米网技术团队基于对 golang 应对高并发、大规模分布式系统能力的肯定,完全基于 golang,重新设计了抢购系统,也就是我们目前使用的抢购限流峰值系统——“大秒”。
-
灵活性及可运营性;
-
可运维性及可伸缩性;
-
限流与抢购放号的精准性;
-
限流集群 HTTP 服务
-
放号策略集群 Middle 服务
-
监控数据中心 Dcacenter
-
监控管理体系 Master
-
准实时防刷模块 antiblack
-
基础存储与日志队列服务: Redis 集群、Kafka 集群等
-
限流集群 HTTP 服务
-
策略集群 Middle 服务
-
准实时反作弊 antiblack 服务
HTTP 模块将满足条件用户的请求按照 uid 哈希的规则,转发到 Middle 集群中相应的节点,Middle 集群根据商品放号策略判断 (uid:sku:time) 组合是否可以分配购买资格,并返回给相应的 HTTP 服务;
(2) 系统级数据: 大秒前端服务集群通信地址配置,限流队列初始长度配置,系统服务资源占用情况,包括:CPU、MEM、连接数等;
由数据中心控制监控数据采集的粒度,在数据中心处理能力既定的情况下,可以根据前端集群的伸缩规模,灵活的调整数据采集的粒度,比如米粉节时,大秒前端集群扩容至过百台,管理的过大秒商品的数量在400个左右,业务级监控数据量很大,此时监控数据采集时间间隔很容易降配至 2s。
同步商品的仓储系统中的实时库存到秒杀系统,大秒系统拥有双库存保障,一个是实时仓储库存,一个是虚拟库存也就是资格号,在抢购场景下只有当两个库存都有货时,才能正常销售。
基于相应的策略触发器(时间区间与库存区间),当策略触发时,比如12点整,抢购开始,为相应的商品配置策略,并向大秒前端广播商品配置变更命令,在通信基础模块的保障下,整个过程秒级内完成。
基于监控数据中心获取大秒前端的实时销售数据,自动化的控制活动中的各个状态,活动开始前逐层打开开关,活动开始时打开最后开关,活动过程中维护活动的售罄状态,活动结束后初始化,整个抢购活动的过程无需人工介入;
从监控数据中心提取实时的结构化系统级监控数据和业务级监控数据,将活动过程中的详细数据实时可视化到管理页面上,让运营与销售以及大秒管理员能够及时了解当前活动状态,并人工干预活动;
监控规则引擎建立在监控数据中心之上,根据结构化监控数据判断当前整个抢购系统的状态,及时报警,以及半自动化控制。
大秒管理端管理大秒前端所有的数据、配置以及状态,Master体系提供了详细的管理工具与自动化服务。如果清理大秒前端Middle服务中的用户购买信息等。
-
bigtap体系中大秒前端服务负责抢购时限流放号,并控制放号策略以及维护用户在本地缓存中的购买记录。
-
cart服务验证token的有效性,并向counter服务发起销量验证请求;
-
counter服务是整个抢购系统最终的计数器, 海量的请求在bigtap服务的作用下已经被限制在可以承受的压力范围内,并且复杂的放号策略已经在大秒Middle服务中实现,counter只负责最终的计数即可。counter服务采用redis记录相应商品的放号情况,根据预设的销量,判断当前请求加购物车商品是否有库存余量,并维护商品销量;
-
bigtap体系中的dcacenter服务实时采集商品销量,Master中活动自动化控制服务依据商品销量判断当前商品是否售罄,售罄则通过设置商品的售罄状态,并通知大秒前端;
在上述文章中,已经介绍了一些服务设计的出发点,每一次优化的背后,都至少有一次惨痛的经历。
-
减少垃圾产生:降低数据结构或者缓冲区的开销;
-
手动管理内存:使用内存池,手动管理内存;
-
脏数据尽快释放,增大空闲内存比。
从 golang 1.3 开始,HTTP 原生的包中已经使用了sync.Pool 维护读写缓存池,但是 sync.Pool 中的数据会被自动的回收,同样会小量的增加 GC 压力,我们此处自己维护缓存池来减少垃圾回收。
原生的 HTTP 包默认使用 keep-alive 的方式,小米抢购场景下,恶意流量占用了大量的连接,我们通过主动设置 response header 的 connection 为 close 来主动关闭恶意连接,加快 goroutine 资源的释放。
跟进使用 golang 最新的版本,golang 后续的每个版本都有针对 GC 能力的调整。
具体参数调整如下:
net.ipv4.tcp_tw_recycle = 1 (打开TIME-WAIT sockets快速回收)">net.ipv4.tcp_tw_recycle = 1 (打开TIME-WAIT sockets快速回收)
net.ipv4.tcp_tw_reuse = 1 (允许TIME-WAIT sockets复用)
net.ipv4.tcp_max_tw_buckets=10000 (降低系统连接数和资源占用,默认为18w)高并发场景下,操作系统层网络模块参数的调整,会起到事半功倍的效果。
3、没有通信就谈不上分布式系统整个大秒系统模块之间面临的通信要求是非常苛刻的,Master 节点与 HTTP、Middle 节点要频繁的广播控制命令,dcacenter要实时的收集 HTTP、Middle 节点的监控管理数据,HTTP 要将用户的购买请求路由到 Middle 节点之间,Middle 节点要返回给相应的 HTTP 节点放号信息;
我们基于 TCP 定制了简单、高效的通信协议,对于 HTTP 层和 Middle 层通信,通信模块能够合并用户请求,减少通信开销,保障整个大秒系统的高效通信,增加服务的处理能力。
4、服务闭环设计从上述抢购的服务闭环架构中可以看出,整个抢购流程处理bigtap系统之外,还有 cart 服务,中心 counter 服务,这三者与 bigtap 系统构成了一个数据流的闭环,但是在大秒最初的设计中,是没有 counter 服务的,Middle层策略集群在放号的同时,又作为计数服务存在,但是整个抢购流程却是以商品加入购物车代表最终的抢购成功,这在设计上有一个漏洞,假如 bigtap 计数了,但是token 并没有请求加购物车成功,这是不合理的。为了保证整个系统的准确性,我们增加了计数器服务,计数操作发生在加购物车下游,bigtap 在从计数中心取出商品实时销量,由此,构成一个服务闭环设计。在提升了系统的准确性,同时也保证了用户体验。
5、技术的选择要可控我们一开始选择使用 ZooKeeper 存放商品的配置信息,在抢购活动的过程伴随着大量的配置变更操作,ZooKeeper 的 watch 机制不适合用于频繁写的场景,造成消息丢失,大秒前端集群状态与配置不一致。
后来,我们将所有的配置信息存放在 Redis 中,基于通信模块,在发生配置变更时,伴随着一次配置项变更的广播通知,大秒前端根据相应的通知命令,拉取 Redis 中相应的配置信息,变更内存中配置及状态。
大秒的几点设计原则分治是解决复杂问题的通则;我们从第一代抢购系统演进到当前的大秒系统,衍生出了很多服务,每个服务的产生都是为了专门解决一个问题,分离整个复杂系统,针对每个服务需要解决的问题,各个击破,重点优化。由此,才保障了秒杀体系整体性能、可靠性的提升;
服务化设计;系统解耦,增强系统的伸缩性与可靠性;
无状态设计,增强系统的伸缩性,提升集群整体处理能力;
状态数据局部化,相对于数据中心化,提升集群整体处理能力。
中心化监控管理,热备部署,既保证了服务的高可用性,又能够提升开发和管理效率。随着集群规模的增大以及管理数据的增多,分离管理信息到不同的数据管理节点,实现管理能力的扩容。通常情况下,中小型分布式系统,单机管理能力即可满足。
避免过度设计,过早的优化;小步快跑,频繁迭代。
没有华丽的技术,把细小的点做好,不回避问题,特别是在高并发系统中,一个细小的问题,都可以引发整个服务雪崩。
( generated by haroopad )
Q&A1、实时仓库怎么避免超卖?
我们的抢购系统以加入购物车代表购买成功,因为用户要买配件等,库存是由计数器控制的,先限流,在计数,在可控的并发量情况下,不会出现超卖。
2、有了放号系统计算放号规则,为什么还需要一个外围的 counter?
主要是 bigtap 到 cart 的环节 token 有丢失,在 cart 之后再加一个计数器,保障销量,bigtap 再读取计数器的数据控制前端商品销售状态,整个延迟不超 3s。
3、HTTP 集群通过 uuid hash 到 Middle,如果目标 Middle 已经死掉怎么应对?这个问题在文章中有强调,在我们的场景下,商品迅速卖完,这块没有做高可用,只是从代码层面做 review,完善异常处理机制,并且通常情况下,middle 负载不是特别高,几百次活动下来,还没出现过挂掉情况。
4、防刷系统是离线计算的吗,还是有在线识别的策略?基于日志,准实时,因为请求量比较大,专门搭了一套 Kafka 服务转储日志,基于 golang 开发 logcollect 与 antiblack 模块,可以达到很高的处理性能。
5、请问如何模拟大量请求做测试?我们遇到的情况是,由于压测机单机端口限制造成早期不好测试,我们这边压测团队基于开源模块开发了能够模拟虚拟IP的模块,打破了单机端口的限制。
6、即使广播和 Redis 拉取商品配置信息,仍有可能配置信息不一致如何解决?这个主要是商品的配置和状态信息,不涉及到强一致性要求的场景,我们这样可以在秒级达到最终一致性。
想更多了解小米抢购的架构,可阅读抢购系统架构演进介绍 【年度案例】小米抢购限流峰值系统架构历年演进历程
来源:https://mp.weixin.qq.com/s/enRMYmss6Y5AUCvAMfpHtA
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
