分布式事务问题
背景
- 积分支付,需要查询用户积分;
- 商品扣减库存;
- 保存订单;
这些一定要保证一致性;
解决办法有
- 基于XA协议的两阶段提交
- 事务补偿机制
- 本地消息表+定时任务
- MQ
XA协议
一个事务管理器和多个资源管理器组成
提交分为两阶段
- prepare
- commit
第一阶段
第二阶段
这个需要事务管理器给所有RM发送准备指令和执行指令,效率特别低。
DEMO:
MySql5.7支持XA,尽量使用8.0版本
Mysql连接器,Mysql Connector/J 5.0以上支持
Atomikos做分布式事务,管理分布式数据库
分库分表的组件:MyCat和Sharding-JDBC这两个都已经集成Atomikos了,直接使用就可以。
事务补偿机制
我们现在用的这个,分布式事务处理,就是事务补偿机制的原理。嗯,这个存在的问题就是有可能A扣减了,B也扣减了,但是B扣钱失败了。然后此时A回滚的时候会有问题,嗯,这是一个待解决的一块儿。
在catch里写回滚逻辑。涉及到重试,这块有一些复杂,具体怎么处理才能尽可能一致?
本地消息表+定时任务
这个就是落一个表,定时任务扫表处理
基于MQ
不同公司之间,因为机房不一致,就无法使用MQ来达到消息一致性,可以使用本地消息表,推送信息去处理,例如对接支付宝微信。
消息的重试
rocketmq有messageExt.getReconsumeTimes()可以记录重试次数,可以达到一定次数后进行consume,然后报警,人工处理。
幂等
怎么防止重复下单
表单怎么防止重复提交
接口重复调用,重试,怎么幂等
UPDATE时,使用乐观锁
insert使用版本号,可以是token
混合操作,可以使用分布式锁来锁住业务单号,如果没有业务单号,也是可以用token
UPDATE幂等
列表更新时,可以使用数据的version来做乐观锁,加上数据库的行锁来保证。
insert幂等
有唯一业务号的insert操作,例如下单场景,商品id+用户id ,
分布式锁来保证幂等,保证接口幂等,
这个也可以作为一个唯一索引到数据库,
业务执行后,不进行锁的释放,过期自动释放。
没有这种唯一业务号的就用token作为key来获取分布式锁。