两个系统之前如何实现事务的同步
eBay架构
看一个例子:
中行账户A向建行账户B转账1000元,应该如何实现,
首先,中行本地有两张表,第一张表是账户表,第二张表是消息表。
- 开始转账后,中行账户A扣款1000元,通过本地事务将事务消息插入至消息表。
- 本地通常通过消息MQ(消息队列)的方式发送异步消息通知建行账户B,增加1000元。
对方订阅并监听消息后自动触发转账的操作,为了保证幂等性,防止触发重复的转账操作,需要在执行转账操作方新增一个trans_recv_log表用来做幂等,在第二阶段收到消息后,通过判断trans_recv_log表中的字段来检测相关记录是否被执行,如果未被执行则会对B账户余额执行加1000元的操作,并会将该记录增加至trans_recv_log,事件结束后通过回调更新trans_message的状态值。
在上述例子中,转账方由于网络原因出现多次发送请求的情况怎么处理
在中行账户中,每次请求都有个ID,hash值,在收款方的trans_recv_log表首先查询是否有这行请求的记录,没有的话就插入记录,并将这行的状态位标志为未处理,然后开始处理业务,在业务处理完成后,将状态位标志为已经处理。
这样当重复请求过来,查看到状态位为已经处理,就不再处理业务。在上述例子中,两次重复请求之间时间间隔很短怎么办,也就是第二次请求发过来的时候,第一次请求还在处理业务,还没来得及回调更新trans_recv_log表的标志位
给trans_recv_log表的每一行加锁,这样第二请求来的时候就会等待,等到第一个请求完成,第二请求查询到标志位已经完成就不会触发业务了在上述例子中,可能存在一个情况,就是第一个请求刚处理完业务,给行解锁准备更新标志位的时候,第二请求来了,因为还没来的及更新标志位,所以第二个请求会触发业务,业务被击穿了
在业务请求之前,一定要写上锁,再查询
在业务完成之后,一定要先更新状态,再解锁