Skip to content

Latest commit

 

History

History
52 lines (39 loc) · 2.91 KB

数据一致性.md

File metadata and controls

52 lines (39 loc) · 2.91 KB

数据一致性

背景

  • 分布式事务不适用微服务
    • 首先 2pc 会出现同步阻塞和加锁,并且有单点故障,由于锁的原因又降低了吞吐量
    • Nosql 数据库并不支持 2pc
  • 在微服务架构下,使用最终一致性来替代分布式事务中的强一致性。
    • 最终一致性:是指不同服务节点在一段时间后,节点间的数据会最终达到一致的状态

方案 1:可靠事件模式

原理

  • 一般借助消息队列和内部表来完成
  • 可靠事件模式是只要他的前序时间发生后序事件就一定发生
  • 可靠性事件模式不能够回滚

轻量级实现 - mysql/redis + 重发机制

  • 发送消息前,记录消息 id,以及数据
  • 发送消息,如果成功,通知原服删除记录;如果失败则重试,直到消息被消费

实例分析

  • 举例,支付宝的余额转到余额宝
    • 用户发起请求调用支付宝扣款并记录该事件记录到数据库中
    • 发送消息,经过消息队列,消息队列向余额宝服务进行投递消息
    • 余额宝收到消息后进行加款并且记录事件到数据库中,通过事件 id 唯一的记录用户发起的一个转账事件
    • 余额宝加款后会发送一个确认消息,经过消息队列投递给支付宝,支付宝收到这个消息之后就会 将本地数据库的事件进行删除
  • 异常分析
    • 余额宝服务宕机了,或消费消息失败了,就需要支付宝服务发起一个定时任务,定期的检测数据库中的事件记录,并发送消息,直到余额宝服务投递出确认消息
    • 假如余额宝服务已经做了加款,那么下一次支付宝服务再发送重复的消息之后,余额宝服务会通过数据库去看一下该事件有没有进行执行。如果说已经执行了就会再触发确认消息的发送。结果就是支付宝系统会删除本地的事件记录

重量级实现 - kafka 方案

  • 生产者数据的不丢失
    • kafka 的 ack 机制,在 kafka 发送数据的时候,每次发送消息都会有一个确认反馈机制,确保消息正常的能够被收到。
  • 消费者数据的不丢失
    • 通过 offset commit 来保证数据的不丢失,kafka 自己记录了每次消费的 offset 数值,下次继续消费的时候,接着上次的 offset 进行消费即可
  • 缺点:
    • 因为 kafak 的分区缘故,没办法保证消息的顺序性
    • 每台业务逻辑服上需要维护 kafak 进程

方案 2:补偿模式

  • 通过 sagas 模型来实现的
  • sagas 模型实际上是一个长事务,它是一系列本地的有序事务,每个本地事务通过更新数据库发送消息来触发下一个本地事务
    • 如果本地事务失败,sagas 会有序的执行补偿事务,来回滚刚才的操作
  • 缺点
    • 本地事务和补偿子事务都需要严格按照顺序执行
    • 操作比较复杂,目前还没有框架来支持 sagas 的补偿模式