微服务下的数据一致性

分布式事务并不适用于微服务

  1. **两阶段提交(2PC)**会有单点故障
  2. 由于的原因降低吞吐量
  3. NoSql并不支持两阶段提交

数据最终一致性(替代微服务中事务强一致性)

根据不同服务节点在一段时间后,节点间的数据会最终达到一致的状态,有两种模式可以完成最终一致性

可靠事件模式

优点

  1. 借助消息队列内部表完成
  2. 前述事件发生,后述事件一定会发生

缺点

  1. 事务无法回滚

案例 (支付宝转余额宝)

在这里插入图片描述

  1. 首先用户发起请求调起支付包服务来进行扣款,记录该事件到数据库中,该事件的作用在于我们向余额宝发送消息的时候,需要定时的去检测余额宝服务是否进行了加款的操作
  2. 开始发送消息到队列中
  3. 消息队列向余额宝服务投递消息
  4. 余额宝服务在收到消息之后进行加款操作并记录该事件到数据库中,和我们支付宝服务记录的事件id是相同的,这样通过事件id就可以唯一的记录用户发起的一个转账事件
  5. 加款之后呢会像消息队列发送一个消息(该消息是一个确认消息)
  6. 经过消息队列投递给支付宝服务
  7. 支付报服务收到这个确认的消息后,就会将本地数据库的事件记录进行删除
  8. 也有可能余额宝服务不稳定,假设有一段事件宕机了,或者消费事件消息失败了
  9. 这需要支付宝服务发起一个定时任务,定期检测数据库中的事件记录,定期的进行发送消息
  10. 直到余额宝服务投递出确认的消息,如果已加款,那么下次支付宝服务再发送重复的消息之后,余额宝服务会通过数据库看一下该事件是否执行,如果已执行,那么就会发送一个确认信息
  11. 最终结果就是支付宝会删除本地事件记录
  12. 整个过程没有一个回滚的过程,只是保证了支付宝服务进行了扣款,余额宝服务进行了加款

为什么在进行可靠事件模式通过消息队列而不是RPC调用呢

  1. 一方面调用支付报服务并不依赖余额宝服务返回结果,这个时候可以使用异步消息来处理,来提升系统的吞吐量
  2. 我们的数据库记录及定时任务这些,可以集成到消息队列来一起完成,例如:RocketMQ是支持事务消息的,RabbitMQ这些数据库记录的事情是不需要去关心的

补偿模式 -sagas模型

优点

  1. 实际上是一个常事务,saga是一系列有序的本地事务
  2. 每个本地事务通过更新数据库发送消息触发下一个本地事务
  3. 如果本地事务失败,那么saga会有序的执行补偿事务,来回滚刚才的操作

缺点

  1. 本地事物和补偿子事务都需要严格按照顺序来执行
  2. 操作比较复杂,目前还没有一个开源框架来支持sagas补偿模式

案例(外卖)

在这里插入图片描述

  1. 订单服务,餐馆备餐服务,骑士服务,配送服务
  2. 一次完成四个事务,每一个本地事务,它都对应着一个发送消息以及接收消息的操作
  3. 下单支付要发送消息给餐馆备餐
  4. 餐馆备餐也要发送确认消息给下单支付,就合刚才的可靠事件一样,都需要有一个定时任务来进行发送(上述双箭头)
  5. 餐馆备餐到骑士取餐也是一样,骑士取餐和送餐到家也是一样,都是发送消息-确认消息
  6. 当我们本地事务失败的时候,我们会发起一个补偿子事务(Compensating transaction)
  7. 蓝色就是一个补偿子事务,它实际上和本地事务效果一样,只不过是针对本地事务的一个反向操作
  8. 例如当我们的骑士取餐失败之后,我们会在本地记录一下取餐失败的记录,然后呢就会发消息到消息队列,通知商家服务触发备餐失败的子事务
  9. 那么备餐失败的子事务又会发消息给订单服务,订单服务又会发起给客户退款的补偿子事务
  10. 无论我们的本地事物还是子事务,都是严格按照顺序来执行的,补偿子事物也是需要按照顺序来进行反向操作的
  11. 补偿子事物就类似于发起了一次回滚,无论是本地事物还是补偿子事物都需要进行发送消息以及消费消息
  12. 所以说这个案例中的每一个服务都需要发送2个消息和消费2个消息,也造成了代码比较复杂
发布了9 篇原创文章 · 获赞 9 · 访问量 614

猜你喜欢

转载自blog.csdn.net/weixin_41241629/article/details/94578640