有个各个模块的请求量后,汇总之后就可以得到各个接口,红包系统各个服务以及下游依赖的各个服务的流量请求,这个时候再做限流就比较方便了。
业务降级核心依赖降级
在春节活动期间,红包系统整个链路依赖的服务有很多,这些下游的链路依赖可以分为核心依赖和非核心依赖,当下游核心服务异常时,可能某一个链路就不可用,此时可以在 API 层直接降级返回一个比较友好的文案提示,等下游服务恢复后再放开。比如在 C2C 的红包发送流程中,用户需要完成支付才可以发红包,如果财经的支付流程异常或者支付成功状态长时间未完成,会造成用户支付后红包发送不成功,也会导致前端来不停的轮训查询红包状态,导致请求量陡增,造成服务压力,甚至影响 B2C 的红包发放和查询。此时可以通过接口降级的方式,将 C2C 的红包发放降级返回,减少服务压力,同时降低对其他业务逻辑的影响。
非核心依赖降级
除核心依赖外,红包系统还有一些非核心的下游依赖,对于这些依赖,如果服务出现异常,我们可以降低用户部分体验的方式来保证服务的可用。比如在 4.2 中我们提到的,用户在发 B2C 红包前需要先获取所有可用的红包补贴,我们会去奖励发放端查询到所有的 Token 列表,然后查询我们自己的 DB,然后进行 merge 返回。如果获取 Token 列表的接口异常时,我们可以降级只返回我们自己 DB 中的补贴数据,这样可以保证用户在这种情况下还可以进行红包的发放,只影响部分补贴的展示,而不是影响整个红包发送链路。
多重机制保证状态机的推进在红包系统中,如果某个订单长时间未到终态,比如用户领取红包后长时间未到账,或者用户 C2C 红包未领取长时间未给用户退款都有可能造成用户的客诉。因此需要及时准确地保证系统中各个订单的状态能推到终态。
这里我们有几种方式去保证,首先是回调,在依赖方系统订单处理完后会及时地通知给红包系统,这种方式也是最及时的一种方式。但是只依赖回调可能会出现依赖方异常或者网络抖动导致回调丢失,此时我们在红包的各个阶段都会给红包系统发一个 mq,间隔一定的时间去消费 mq 主动查询依赖方的订单状态进行更新。最后我们对每个状态机都会有一个定时任务用于兜底,在定时任务多次执行仍未到终态的会 lark 通知,及时人工介入发现问题。
资金安全保证交易幂等在编程中,幂等指任意多次执行一个请求所产生的影响与一次执行的影响相同。在资金安全中,通过订单号来进行相应的幂等逻辑处理可以防止资损的发生。具体来说在红包系统中,在红包的发放,领取和退款中,我们都通过订单号唯一键来保证接口幂等。另外红包系统的补贴发放接口是幂等的,外部同一个单号多次请求发放补贴,我们需要保证只会发一张券。
实现幂等的方案很多,包括有通过数据库或者 redis 来实现幂等的。最可靠的就是通过数据库的唯一键冲突来实现,但是这种方式在数据库存在分片实例时会引入一些额外的问题。这里我们就补贴的发放来简单介绍下,在业务系统的设计中,我们是按照 uid 分片的方式来建立业务的数据库表,这就导致补贴的分片键是 uid,虽然我们也设置了红包的补贴单号作为唯一键。但是其中存在一个风险就是如果上游的系统调用补贴发放时,同一个外部单号更换了 uid,就可能会导致两个请求分别打到不同的数据库实例上,导致唯一索引失效,造成资损。为了解决这个问题,我们又额外的引入一个以补贴发放外部单号作为分片键的数据库来解决这个风险。
B2C 红包核对除了在开发过程的系统设计上进行相应的资金安全考虑,我们还需要通过对账的方式来校验我们的系统是否有资金安全问题。
在 B2C 链路中,整个链路主要是从补贴发放到红包领取,我们对这几个链路的上下游的数据都进行相应的小时计 hive 对账。
C2C 红包核对在 C2C 链路中,整个主要从用户发起支付,到用户领取转账以及最后红包过期退款。在支付,转账,退款这三个流程都需要进行相应的核对。同时,还需要保证用户的红包发放金额大于等于红包转账金额 红包退款金额,这里大于等于是因为红包从发放成功到退款成功整个周期会在 24h 以上,另外可能存在转账在途的这种订导致会有多笔退款单,如果要求严格等于的话具体对账时机没法控制。
红包系统的压测前面提到过,红包系统的链路包含有多个接口,发领查等,需要模拟用户的真实行为来进行压测才能得到系统的真实性能。这里我们使用了压测平台的脚本压测方式来进行压测。
首先需要对整个压测链路整个改造,和上下游沟通是否可以压测,不能压测的需要进行相应的 mock 处理。另外对于存储服务,数据库,redis 和 mq 都要确保压测标的正确传递,否则可能会影响到线上。
改造完压测链路后,需要构造相应的压测脚本,对于 B2C 和 C2C 分为两个脚本。
B2C 红包链路压测