订单状态一致性维护的高鲁棒性实践——以接单系统为例
订单系统最难的就是一致性维护,关于状态机,同事有很好的总结,参见:https://www.jianshu.com/c/fcf...
接单系统作为订单系统的后路,对一致性要求更高
接单系统特点与要求
- TPS高,要求高并发,存在峰值流量
- 稳定性要求高,不能漏接单,需要有较高的容错性,接单系统依赖的任何服务短时挂掉都不应该影响接单,尤其是在电商系统中,到接单这一步,用户之前其实已经支付了,所以对稳定性有着异常严格的要求。
技术实现
1.对于高TPS要求,实现的套路是固定的。
消息中间件在工程实现中主要用来削峰,异步和解耦。接单接口的入口首先要用消息队列来削峰,以解决峰值高流量问题。
削峰之后收到要保证消息不堆积并支持高并发,还需要做分流,接单系统需要落日志并增删改查业务表数据,数据库性能就会成为瓶颈,数据库的分库分表就是必须的,
消息加数据库分库分表基本就能满足。
2.对于稳定性要求
需要考虑到各种异常情况。出现异常情况要有自恢复能力,状态机加延迟队列再加脚本可解决问题。
为什么要有状态机呢,接单系统的业务逻辑一般都很复杂,在接单的过程中可能由于各种原因导致异常,这时候状态机的作用就凸显,
刚接到单,就需要数据落库,这是状态机的初始态。之后的业务逻辑流转过程中的各种可能异常情况都需要被记录下来,这些是状态机的中间态,属于异常情况,
需要某种机制将中间态转化为最终态。技术要需要利用延迟队列,如果某个订单出现了异常,或者说出现了中间态,需要将这个异常订单扔到延迟队列中,待会重试,
绝大多数情况是依赖的某个微服务短时间存在不可用或者不稳定,待它稳定后需要进行重试。重试如果还有问题就再重试。
但是重试也需要有次数限制,如果有问题,不可能一直在堆在q中,这时候补偿脚本的作用就显现了 ,脚本是最后的兜底,跟常规逻辑相比,脚本需要对业务稍微有损,是次优的,
在兜底脚本中可将部分接单过程中不重要的接口或者功能降级掉,优先保证接单的稳定。这是跟之前的延迟队列的业务逻辑相比不同的地方。