接口幂等性:只要保证接口内的逻辑不涉及接口外的对象状态累积或变迁即可。
幂等性在技术上同时要求可重入性;在分布式系统中,重试和并发都是常态。
1.接口入口做来源+单号检验
2.分布式锁
3.数据库(单库多表【本地事务】、多库【分布式事务】、单库单字段【业务保证】)乐观锁(单号+【版本号、状态机:单向 支付中、支付成功 和 双向 可用、不可用,库存扣减】)、悲观锁(唯一健约束)、去重表、插入前状态检验。
状态机原理:
在设计单据或任务相关的业务,肯定会涉及到有限状态机,状态在不同的情况下会发生变更。如果状态机已经处于下一个状态,新发起的上一个状态的变更,理论上是不能够变更的,可有效保证了有限状态机的幂等。
分布式事务不可能实现绝对的一致性。从概率的角度思考问题,如果能将不一致的概率降到最低,比如保证幂等+重试(衰减重试),再辅以业务监控和人工干预,就可以实现系统整体上较高的一致性。
幂等的对象(交易流水和用户ID)和范围(几秒、几分钟、永久)
比如订单回传凭证码环节:
场景1:如果我们先做本地的凭证码数据落盘到数据库,在调用订单中心;可能因为网络中断而没有调用到订单中心;结果是 本地成功,订单中心失败;
场景2:如果先调用订单中心;再做数据落盘;可能因为本地数据库忽然断连;结果是本地失败, 订单中心成功。
核心思想:1.分布式事务降纬为本地化事务; 2.可靠事件投递+幂等调用= 数据最终一致性;
1.本地化事务

1.服务在同一个本地事务中记录业务数据和事件数据
2.事件恢复服务定时从事件表中恢复未发布成功的事件,重新发布,重新发布成功后删除记录的事件,这样能够保证事件一定能够被投递。
优点:实现起来比较安全, 外部依赖比较少;
缺点:事件表和本地表在统一数据库中;以后事件表可能是性能瓶颈;系统扩展性差;消息实时性差;
2.本地化事务+非事务性MQ

1.服务在同一个本地事务中记录业务数据和事件数据
2.服务实时发布一个事件到MQ中,通过mq消费事件,但是在消费事件之前到数据库中check 该事件是否真是落库;如果没有落库放弃执行该事件;这样能够保证事件投递的实时性。
3.事件恢复服务定时从事件表中恢复未发布成功的事件,重新发布,重新发布成功后删除记录的事件,这样能够保证事件一定能够被投递。
优点:实现起来比较安全,外部依赖比较少;比方案一消息实时性强
缺点:事件表和本地表在统一数据库中;以后事件表可能是性能瓶颈;系统扩展性差。
3.事务性MQ

1.业务服务在事务提交前,通过实时事件服务向事件系统请求发送事件,事件系统只记录事件并不真正发送
2.业务服务在提交后,通过实时事件服务向事件系统确认发送,事件得到确认后事件系统才真正发布事件到消息代理
3.业务服务在业务回滚时,通过实时事件向事件系统取消事件
4.事件系统的事件恢复服务会定期找到未确认发送的事件向业务服务查询状态,根据业务服务返回的状态决定事件是要发布还是取消
优点:系统扩展性强;事件表和本地表解耦;
缺点:系统比较复杂;业务服务还要时间查询未决事件接口。
4.有限状态机
1.只保证本地事务的完整性;所有的对外的调用和交互通过基于当前业务库db的当前数据的状态判断;基于类似状态机模式;向下游发起重复调用;
2.本身业务状态机代表了一定的事件性质;
优点:基于现有业务;初期实现成本低;
缺点:系统扩展性差;依赖于对于业务状态机的考虑;如果有后续缺少状态或者新增状态会很麻烦;后续改造成本高
结论
基于时间成本:
暂时决定实现方案一;
二期实现方案二(实时性考虑);
方案三依赖于事务性MQ支持,另外对现有系统改动比较大;侵入比较高;放弃该方案。