(二)分布式事务?No, 最终一致性(2)

最终一致性解决方案

1. 两阶段提交

2.异步确保(没有事务消息)

3.异步确保(事务消息)

4. 补偿交易(Compensating  Transaction)

5.消息重试

6.幂等(接口支持重入)

A给B转100元。

1. 两阶段提交

有协调者,协调操作流程。Pre commit资源,commit或rollback时提交或释放资源。

调用A的commit接口超时了,继续重试。要求下游接口幂等。下游故障,短时重试不能解决,定时处理中间状态:扔到重试MQ。重试策略,失败返回

(二)分布式事务?No, 最终一致性(2)_第1张图片

2.异步确保(没有事务消息)

不只为一致性考虑响应时间下游稳定性

关键要有消息表。一般有队列(不丢消息,但不支持事务消息),基本思路

生产方消息表记录消息发送状态和数据一个事务提交(存储耦合)。只是增加一个字段业务强耦合,处理不同交易数据可通用处理

消费方需处理消息成功,给生产方confirm失败放MQ支持重试省事儿,不支持回队尾或建队列处理。如成功才继续,block(不会这么做)。Kafka lowlevel接口是支持自己设置offset的,可实现block。

生产方定时扫描本地消息表,没处理完的消息由发送一遍自动对账补账,这一步可省略。丢消息或者下游处理失败场景少。看业务上能不能容忍不一致到对账补账周期。

ps:不要MQ脚本处理低频场景,离线扫表让人不爽。业务量初期也可以

一致性要求不高兜底方案(对账补账),不需要confirm扔给消息万事大吉

(二)分布式事务?No, 最终一致性(2)_第2张图片

3.异步确保(事务消息)

理想:消息扔到MQ,肯定被消费成功不用担心失败丢失

现实:处理失败继续消费直到成功为止

大部分MQ都不支持事务消息比如kafka。RocketMQ号称支持,事务消息关键封装消息状态和重发等。没成熟事务消息MQ。网传RMQ提供2PC提交接口。

1.生产方发送prepared消息给RMQ。、失败返回

2.执行本地事务,成功发Confirm消息给RMQ失败,调用RMQ cancel接口。

3.步超时如何处理呢?

4.生产方实现check接口告知RMQ自己本地事务是否执行成功(第4步)。定时轮训pre消息,调用check接口,决定是否可提交

5.可能失败。这时候需要RMQ支持消息重试。处理失败的消息果断时间再进行重试,直到成功为止(超过重试次数后会进死信队列,可能得人肉处理了,因为没用过所以细节不是很了解)。

支持消息重试

(二)分布式事务?No, 最终一致性(2)_第3张图片

P.S. 阿里内部因历史原因,用notify比RMQ要多,原理类似。

4. 补偿交易(Compensating  Transaction)

和操作本身一个事务里完成。跟2PC比,核心价值少锁代价

如A:-100  B:+100。如B:+100失败,补偿A:+100。看起来跟注册个单库事务一样简单。做到业务无感知。

(二)分布式事务?No, 最终一致性(2)_第4张图片

5.消息重试

事务消息解决生产者和MQ之间一致性,重试确保消费者MQ之间的一致性

pullpush模式。失败,放重试队列延迟时间固定(2s),队首消息时间到达才被消费

时间为水位,期望执行时间大于当前时间的消息高于水位。其他消息consumer不可见。如消息延迟时间不一样:

(1)基于队列方案:按秒建多个队列。按执行时间不同队列,一天86400个队列(一般丑陋)。按时间消费不同队列

(2)基于DB:不依赖队列,支付时消息进去时候,设置下次执行时间,时间做索引

(3)redis的延时队列,支持重试zset处理时间排序。遇到的持久化问题,内存数据丢失问题,重试次数控制,消息追溯等

总结:MQ提供消息重试最好

6.幂等(接口支持重入)

没有MQ,重试也是无处不在的。幂等怎么做?

insert依赖唯一键异常回滚事务

update,那么状态机控制和版本控制异常重要。这里要多加小心。

引入log表。该log对操作id(消息id?)插入log失败整个回滚

不能查log表或者用redis,加锁。除非在事务里查。唯一键冲突回滚掉就好

用唯一键挡重入是目前为止个人觉得最有安全感的方式。当然对数据库会有一些额外性能损耗。问题就变成了有多大的并发,其中又有多大是需要重试的?

Fasion IO卡+分库分表之后,不会到db性能瓶颈(对金融类场景)。

后记

最终一致性问题,万恶之源是RPC本身会失败。生涯大部分时间都会跟各种失败和timeout搏斗了。用MQ实现最终一致性原因:

1. MQ强大,可不丢数据。对事务消息更普及。

2. 异步处理能力(响应时间、吞吐量)和稳定性(99.99%的服务依赖99.9%的服务)服务之间解耦

https://zhuanlan.zhihu.com/p/25933039

你可能感兴趣的:((二)分布式事务?No, 最终一致性(2))