这是我参与「第五届青训营 」伴学笔记创作活动的第 8 天
诈骗,木马,黄牛,盗号,博彩...
今天的课程比较短,只有40分钟,而且是科普性质的,笔记字数不够,所以写一下分布式事务。分布式事务也是我现在想要学习的内容,不知道是不是因为我们的微服务拆分的过于细节,点赞的时候,需要更新记录也需要更新video表中的点赞数字段。由于这两个对数据库的更改不在一个库中(模拟数据库分开),两个微服务,怎么保证这两个位置保持数据一致性呢?
银行跨行转账业务是一个典型分布式事务场景,假设A需要跨行转账给B,那么就涉及两个银行的数据,无法通过一个数据库的本地事务保证转账的ACID,只能够通过分布式事务来解决。分布式事务就是指事务的发起者、资源及资源管理器和事务协调者分别位于分布式系统的不同节点之上。在上述转账的业务中,用户A-100操作和用户B+100操作不是位于同一个节点上。本质上来说,分布式事务就是为了保证在分布式场景下,数据操作的正确执行。
图片来源:zhuanlan.zhihu.com/p/388357329
req := &gin.H{"amount": 30} // 微服务的载荷 // DtmServer为DTM服务的地址 saga := dtmcli.NewSaga(DtmServer, dtmcli.MustGenGid(DtmServer)). // 添加一个TransOut的子事务,正向操作为url: qsBusi+"/TransOut", 逆向操作为url: qsBusi+"/TransOutCompensate" Add(qsBusi+"/TransOut", qsBusi+"/TransOutCompensate", req). // 添加一个TransIn的子事务,正向操作为url: qsBusi+"/TransIn", 逆向操作为url: qsBusi+"/TransInCompensate" Add(qsBusi+"/TransIn", qsBusi+"/TransInCompensate", req) // 提交saga事务,dtm会完成所有的子事务/回滚所有的子事务 err := saga.Submit()
在这个例子中:
-
定义了一个Saga事务
-
Saga事务中的第一个子事务TransOut负责扣减A的余额
-
Saga事务中的第一个子事务TransIn负责增加B的余额
-
完成了Saga事务定义之后,将事务提交给DTM
-
DTM将按顺序完成各项子事务
-
如果中间出现临时的网络错误,DTM会负责重试
-
如果业务返回失败,DTM会调用子事务的补偿操作,保证最终数据一致性