1 本地事务
-
支付宝账户表:A(id,userId,amount)
-
余额宝账户表:B(id,userId,amount)
-
用户的userId=1;
-
1)支付宝表扣除1万:update A set amount=amount-10000 where userId=1;
-
2)余额宝表增加1万:update B set amount=amount+10000 where userId=1;
1
2
3
4
5
|
Begin transaction
update A
set
amount=amount-
10000
where userId=
1
;
update B
set
amount=amount+
10000
where userId=
1
;
End transaction
commit;
|
1
2
3
4
5
|
@Transactional
(rollbackFor=Exception.
class
)
public
void
update() {
updateATable();
//更新A表
updateBTable();
//更新B表
}
|
2 分布式事务—两阶段提交协议
-
1)两阶段提交涉及多次节点间的网络通信,通信时间太长!
-
2)事务时间相对于变长了,锁定的资源的时间也变长了,造成资源等待时间也增加好多!
3 使用消息队列来避免分布式事务
3.1 如何可靠保存凭证(消息)
3.1.1 业务与消息耦合的方式
1
2
3
4
5
|
Begin transaction
update A
set
amount=amount-
10000
where userId=
1
;
insert into message(userId, amount,status) values(
1
,
10000
,
1
);
End transaction
commit;
|
3.1.2 业务与消息解耦方式
3.2 如何解决消息重复投递的问题
1
2
3
4
5
6
7
8
|
for
each
msg
in
queue
Begin transaction
select count(*)
as
cnt from message_apply where msg_id=msg.msg_id;
if
cnt==
0
then
update B
set
amount=amount+
10000
where userId=
1
;
insert into message_apply(msg_id) values(msg.msg_id);
End transaction
commit;
|
参考文献
-
Dan Pritchett《Base: An Acid Alternative》
-
程立,大规模SOA系统中的分布式事务处理