风雨雾凇 风雨雾凇
首页
  • 服务端

    • golang
  • 其他

    • leetcode
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

风雨雾凇

技术小渣渣
首页
  • 服务端

    • golang
  • 其他

    • leetcode
  • 学习
  • 面试
  • 心情杂货
  • 实用技巧
  • 友情链接
关于
收藏
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 从事务到分布式事务

    • 参考链接
    风雨雾凇
    2022-08-26
    学习笔记 事务 分布式
    目录

    从事务到分布式事务

    # 前置知识

    # CAP

    CAP理论是分布式系统、特别是分布式存储领域中被讨论的最多的理论。其中C代表一致性 (Consistency),A代表可用性 (Availability),P代表分区容错性 (Partition tolerance)。CAP理论告诉我们C、A、P三者不能同时满足,最多只能满足其中两个。

    cap描述

    • Consistency(一致性)一个写操作返回成功,那么之后的读请求都必须读到这个新数据;如果返回失败,那么所有读操作都不能读到这个数据。所有节点访问同一份最新的数据。
    • Availability(可用性)对数据更新具备高可用性,请求能够及时处理,不会一直等待,即使出现节点失效。
    • Partition tolerance(分区性容错性)能容忍网络分区,在网络断开的情况下,被分隔的节点仍能正常对外提供服务。
    # 思考题:对CAP的理解(为什么只能满足两个?)

    假设放弃P,考虑CA。

    # 现有系统符合的种类

    CA: 不需要分区的数据库(单机mysql、mongo等) CP: 需要分区和强一致性而放弃了可用性的系统(ACID强事务型数据库) AP: 需要分区和高可用而放弃了可用性的系统(非事务型数据库、大多数互联网应用)

    # BASE

    base 描述

    • Basically Available(基本可用)分布式系统在出现不可预知故障的时候,允许损失部分可用性
    • Soft state(软状态)软状态也称为弱状态,和硬状态相对,是指允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统在不同节点的数据副本之间进行数据同步的过程存在延时
    • Eventually consistent(最终一致性)最终一致性强调的是系统中所有的数据副本,在经过一段时间的同步后,最终能够达到一个一致的状态。因此,最终一致性的本质是需要系统保证最终数据能够达到一致,而不需要实时保证系统数据的强一致性

    BASE是对CAP中一致性和可用性权衡的结果,其来源于对大规模互联网系统分布式实践的结论,是基于CAP定理逐步演化而来的,其核心思想是即使无法做到强一致性(Strong consistency),更具体地说,是对 CAP 中 AP 方案的一个补充。 其基本思路就是:通过业务,牺牲强一致性而获得可用性,并允许数据在一段时间内是不一致的,但是最终达到一致性状态。

    # 数据库事务定义

    把多条语句作为一个整体进行操作的功能,被称为数据库事务。数据库事务可以确保该事务范围内的所有操作都可以全部成功或者全部失败。

    # ACID

    • Atomicity(原子性):事务被视为不可分割的最小单元,事务的所有操作要么全部提交成功,要么全部失败回滚。
    • Consistency(一致性):数据库在事务执行前后都保持一致性状态。在一致性状态下,所有事务对同一个数据的读取结果都是相同的。
    • Isolation(隔离性):一个事务所做的修改在最终提交以前,对其它事务是不可见的。
    • Durability(持久性):一旦事务提交,则其所做的修改将会永远保存到数据库中。即使系统发生崩溃,事务执行的结果也不能丢失。

    enter image description here

    # 思考题:如何实现原子性和持久性的回滚和丢失恢复?

    Undo Log、Redo Log

    # 并发一致性问题

    • 丢失修改
    • 读脏数据
    • 不可重复读
    • 幻影读

    # 事务隔离级别

    enter image description here

    # 不同隔离级别实现原理

    未提交读:一直读最新数据 提交读、可重复读:MVCC 可串行化隔离级别需要对所有读取的行都加锁(Next-Key Locks),单纯使用 MVCC 无法实现。

    # MVCC

    TODO

    # Next-Key Locks

    TODO

    # 封锁

    • 读写锁、意向锁: TODO
    • 封锁协议:TODO

    # 本地事务

    本地事务是指仅操作单一事务资源的、不需要全局事务管理器进行协调的事务。

    # 实现原理

    数据库本身支持事务。

    # 应用场景

    单个服务使用单个数据源的场景。 例如最简单的单机单数据源多表转账服务。

    # 全局事务

    # 定义

    与本地事务相对的是全局事务(Global Transaction) 全局事务被限定为一种适用于单个服务使用多个数据源场景的事务解决方案。

    # 实现原理

    • 思考题:以下代码有什么问题?
    public void buyBook(PaymentBill bill) {
        userTransaction.begin();
        warehouseTransaction.begin();
        businessTransaction.begin();
    	try {
            userAccountService.pay(bill.getMoney());
            warehouseService.deliver(bill.getItems());
            businessAccountService.receipt(bill.getMoney());
            userTransaction.commit();
            warehouseTransaction.commit();
            businessTransaction.commit();
    	} catch(Exception e) {
            userTransaction.rollback();
            warehouseTransaction.rollback();
            businessTransaction.rollback();
    	}
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    # XA

    XA是由X/Open组织提出的分布式事务的规范,XA规范主要定义了(全局)事务管理器(TM)和(局部)资源管理器(RM)之间的接口。本地的数据库如mysql在XA中扮演的是RM角色。

    # 2PC

    enter image description here

    准备阶段:又叫作投票阶段,在这一阶段,协调者询问事务的所有参与者是否准备好提交,参与者如果已经准备好提交则回复 Prepared,否则回复 Non-Prepared。这里所说的准备操作跟人类语言中通常理解的准备并不相同,对于数据库来说,准备操作是在重做日志中记录全部事务提交操作所要做的内容,它与本地事务中真正提交的区别只是暂不写入最后一条 Commit Record 而已,这意味着在做完数据持久化后并不立即释放隔离性,即仍继续持有锁,维持数据对其他非事务内观察者的隔离状态。 提交阶段:又叫作执行阶段,协调者如果在上一阶段收到所有事务参与者回复的 Prepared 消息,则先自己在本地持久化事务状态为 Commit,在此操作完成后向所有参与者发送 Commit 指令,所有参与者立即执行提交操作;否则,任意一个参与者回复了 Non-Prepared 消息,或任意一个参与者超时未回复,协调者将自己的事务状态持久化为 Abort 之后,向所有参与者发送 Abort 指令,参与者立即执行回滚操作。对于数据库来说,这个阶段的提交操作应是很轻量的,仅仅是持久化一条 Commit Record 而已,通常能够快速完成,只有收到 Abort 指令时,才需要根据回滚日志清理已提交的数据,这可能是相对重负载的操作。

    • 2PC存在的问题
      • 单点问题
      • 性能问题
      • 一致性风险
    # 3PC

    增加CanCommit询问阶段,增加成功概率,一定程度解决单点和性能问题。

    enter image description here

    # 共享事务

    # 定义

    共享事务(Share Transaction)是指多个服务共用同一个数据源。

    # 实现原理

    • 多个服务共享数据库链接(新增应用用于串行化执行多个微服务对于数据库的操作)
    • 使用消息队列
    • 分布式锁

    # 应用场景

    目前软总线服务上多个微服务同时读写设备表。

    # 分布式事务

    • 思考题:以下流程存在什么问题?

    场景事例
    
    Fenix's Bookstore 是一个在线书店。每当一本书被成功售出时,需要确保以下三件事情被正确地处理:
    
    用户的账号扣减相应的商品款项。
    商品仓库中扣减库存,将商品标识为待配送状态。
    商家的账号增加相应的商品款项。
    
    1
    2
    3
    4
    5
    6
    7

    # 定义

    多个服务同时访问多个数据源的事务处理机制,目前仅支持柔性事务。

    • 刚性事务:达到实现强一致性的事务(目前无法实现,具体参考:https://www.dtm.pub/practice/theory.html#无法强一致 (opens new window))
    • 柔性事务:达到实现最终一致性的事务

    # 解决方案

    • 最大努力交付/通知(接收方保证一致性)
    • 本地/事务消息表消息表(消息队列保证)
    • AT
    • XA
    • 二阶段消息
    • Workflow
    • SAGA
    • TCC
    # 本地消息表

    enter image description here

    # SAGA

    enter image description here

    # TCC

    enter image description here

    # XA

    enter image description here

    # 二阶消息

    enter image description here

    # 如何选择合适的模式

    • 二阶段消息模式: 适合不需要回滚的场景
    • saga模式: 适合需要回滚的场景
    • tcc事务模式: 适合一致性要求较高的场景
    • xa事务模式: 适合并发要求不高,没有数据库行锁争抢的场景

    # 应用场景

    https://dtm.pub/app/intro.html (opens new window)

    # NPC问题

    # 定义
    • 网络延迟
    • 进程暂停
    • 时钟漂移
    # 异常分类
    • 空补偿
    • 悬挂
    • 幂等

    enter image description here

    # 解决方案

    https://www.dtm.pub/practice/barrier.html (opens new window)

    # 最佳实践

    https://github.com/nivin-studio/go-zero-mall (opens new window)

    # 参考链接

    凤凰架构:http://icyfenix.cn/architect-perspective/general-architecture/transaction/ (opens new window) 数据库系统原理:https://github.com/CyC2018/CS-Notes/blob/master/notes/数据库系统原理.md#一事务 (opens new window) DTM官网:https://www.dtm.pub/ (opens new window)

    编辑 (opens new window)
    #分布式事务#学习笔记
    上次更新: 2023/02/17, 16:53:03
    最近更新
    01
    builtin
    02-12
    02
    导读
    02-12
    03
    13-罗马数字转整数
    01-30
    更多文章>
    Theme by Vdoing | Copyright © 2017-2023 风雨雾凇 | 粤ICP备16018321号-2
    博客内容遵循署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议
    • 跟随系统
    • 浅色模式
    • 深色模式
    • 阅读模式