分布式事务
CAP理论
- C 强一致性
- A 高可用性
- P 分区容错性
- 不存在同时满足一致性、可用性和分区容错性的系统,往往只能三者取其二。
BASE理论
- BA 基本可用
- S 软状态,即允许系统中的数据存在中间状态
- E 最终一致性
- BASE理论是对CAP中一致性和可用性权衡的结果,核心思想是即使无法做到强一致性,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性。
分布式事务解决方案
- 两阶段提交协议(2PC)
- 事务补偿(TCC)
- 消息事务
- 本地消息表
- Seata
什么是2PC
- 第一阶段:准备阶段(prepare)
协调者通知参与者准备数据,参与者开始投票。
协调者完成准备工作向协调者回应Yes。 -
第二阶段:提交(commit)/回滚(rollback)阶段
协调者根据参与者的投票结果发起最终的提交指令。
如果有参与者没有准备好则发起回滚指令。
- 强一致性事务控制
- 缺点:需要引入协调者在多个节点之间去协调,性能较低,
什么是TCC
- Try 提交事务前的检查,并预留好资源。
- Confirm 确定执行业务操作。
- Cancel 取消执行业务操作,释放预留的资源。
- 最终一致性事务控制
- 缺点:需要额外维护三个接口,增加了开发成本。
消息事务
消息事务的原理是将两个事务「通过消息中间件进行异步解耦」,和本地消息表有点类似,但是是通过消息中间件的机制去做的,其本质就是'将本地消息表封装到了消息中间件中',例如RocketMQ。
本地消息表
Seata的三种角色说明
- TC: 全局事务协调者,用来协调全局事务和各个分支事务(不同服务)的状态, 驱动全局事务和各个分支事务的回滚或提交。
- TM: 事务管理者,业务层中用来开启/提交/回滚一个整体事务(在调用服务的方法中用注解开启事务)。
- RM: 资源管理者,一般指业务数据库代表了一个分支事务(Branch Transaction),管理分支事务与 TC 进行协调注册分支事务并且汇报分支事务的状态,驱动分支事务的提交或回滚。
- UNDO_LOG:回滚日志记录表
Seata实现原理
- 第一阶段:
- 分析执行的sql语句,在UNDO_LOG中生成一条回滚日志
- RM事务提交,释放锁资源
- 第二阶段:
- 如若全局提交,RM异步删除对应的UNDO_LOG
- 如若全局回滚,RM根据UNDO_LOG回滚数据
DDD
传统开发方式的缺陷
- 臃肿的service
- 技术导向分层,导致业务分离
传统开发方式同DDD的比较
传统方式 | DDD方式 | |
---|---|---|
接到需求 | 将其切割成数据和行为,数据用数据库实现,行为使用服务实现 | 首先考虑的是业务语言,而不是数据 |
设计时 | 开发人员 | 需同设计人员统一领域术语 |
拆解服务 | 比较复杂,涉及的问题较多 | 根据界限上下文快速拆解 |
定位代码 | 实现方式同业务语言不符,较难定位 | 由于开发过程使用的是业务语言,所以根据业务可以快速找到对应的代码模块 |
其他
如何做到服务高可用
- 一致性,例如配置、版本、环境等,影响问题定位
- 消除单点,容灾
- 群组,防止单个交换机故障导致服务不可用
- 流量隔离,分而治之
- 同城双活,防止单个机房故障导致服务不可用
- N+1冗余,防止实例故障导致服务应付不了高并发请求
分布式id的实现
- 雪花算法,高位时间戳,中间工作机器id,低位自增序列
- 如何分配工作机器id,使用zk
- 如何解决时间回拨问题,方案一、跟前一个id的时间戳比较,如果小发生了时间回拨,短则等待,长则抛异常;方案二、使用历史时间
负载均衡的常用算法
- 随机
- 轮询
- 加权轮询
- 加权随机
- 最小链接数
如何做到系统高可用的
- 消除单点:所有的服务乃至中间件都需要做到消除单点,服务冗余
- 故障转移:通过注册中心做到故障转移
- 负载均衡:服务调用需要选择合适的负债均衡策略
- 容错:应对异常情况需要做好容错策略和限流
- 削峰:可以通过消息队列对流量削峰
- 缓存:采用缓存减少DB或CPU压力,可以采用redis的高可用集群架构
- 读写分离:DB可以使用主写从读的方式分摊压力。