您的位置:首页 > 运维架构 > 网站架构

A. 系统架构理论基础(理论) --- 数据一致性

2019-05-02 11:39 218 查看

[code]A. 系统架构理论基础(理论) --- 数据一致性
算法
事务算法
算法
Redo算法
Undo算法
Redo/Undo算法
一致性协议
两阶段提交协议
第一阶段请求
第二阶段提交
向量时钟
RWN协议
Paxos协议
Raft协议
一致性模型
强一致性
最终一致性:最终一致性不代表不能实时修改,而是异常情况下采用最终一致性,正常情况下可以实时一致性
因果一致性
“读你所写”一致性
会话一致性
单调读一致性
单调写一致性
分布式事务算法
分布式事务算法类型
类型一
崩溃不可恢复的
崩溃可恢复的
类型二
拜占庭问题
非拜占庭问题
分布式事务算法场景
可靠的复制状态机
可靠的复制数据存储和配置存储
使用领头人选举机制实现高可用的处理系统
分布式协调和锁服务
可靠的分布式消息队列和消息传递
分布式事务算法性能
系统负载变化因素
吞吐量:在负载峰值时,单位时间内提出提议的数量
请求类型:需要修改状态的写请求的比例
读请求的一致性要求
如果数据大小可变,请求的大小
部署策略
局部区域部署,还是广域部署?
采用的是哪种仲裁过程,大部分进程的分布情况如何?
该系统是否使用分片、流水线和批处理技术?
等等
强一致性 --- 法定租约
针对数据的一部分给系统中的法定人数进程发送了一个租约,这个租约是带有具体时间范围的(通常很短)。在这个租约有限期间,任何对该部分数据的操作都必须要被法定租约中的所有进程响应。如果租约中的任何一个副本不可用,那么该部分数据在租约过期前将服务被修改。
分布式事务解决方案
两阶段提交
优点:尽量保证了数据的强一致,适合对数据强一致要求很高的关键领域。
缺点: 实现复杂,牺牲了可用性,对性能影响较大,不适合高并发高性能场景,如果分布式系统跨接口调用,目前 .NET 界还没有实现方案。
补偿事务(TCC)
步骤
Try 阶段主要是对业务系统做检测及资源预留
Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。
Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。
优点: 跟2PC比起来,实现以及流程相对简单了一些,但数据的一致性比2PC也要差一些
缺点: 缺点还是比较明显的,在2,3步中都有可能失败。TCC属于应用层的一种补偿方式,所以需要程序员在实现的时候多写很多补偿的代码,在一些场景中,一些业务流程可能用TCC不太好定义及处理。
本地消息表(异步确保)
核心思想是将分布式事务拆分成本地事务进行处理,这种思路是来源于ebay。
步骤
消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交,也就是说他们要在一个数据库里面。然后消息会经过MQ发送到消息的消费方。如果消息发送失败,会进行重试发送。
消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,表明已经处理成功了,如果处理失败,那么就会重试执行。如果是业务上面的失败,可以给生产方发送一个业务补偿消息,通知生产方进行回滚等操作。
生产方和消费方定时扫描本地消息表,把还没处理完成的消息或者失败的消息再发送一遍。如果有靠谱的自动对账补账逻辑,这种方案还是非常实用的。
优点: 一种非常经典的实现,避免了分布式事务,实现了最终一致性。在 .NET中 有现成的解决方案。
缺点: 消息表会耦合到业务系统中,如果没有封装好的解决方案,会有很多杂活需要处理。
MQ 事务消息
RocketMQ
第一阶段Prepared消息,会拿到消息的地址
第二阶段执行本地事务
第三阶段通过第一阶段拿到的地址去访问消息,并修改状态
优点: 实现了最终一致性,不需要依赖本地数据库事务
缺点: 实现难度大,主流MQ不支持,没有.NET客户端,RocketMQ事务消息部分代码也未开源
Sagas 事务模型
核心思想就是拆分分布式系统中的长事务为多个短事务,或者叫多个本地事务,然后由 Sagas 工作流引擎负责协调,如果整个流程正常结束,那么就算是业务成功完成,如果在这过程中实现失败,那么Sagas工作流引擎就会以相反的顺序调用补偿操作,重新进行业务回滚。
幂等性
支付系统中的幂等机制
第一个因素是幂等令牌(Idempotency Key)。客户端和服务器端通过什么方式来识别,这实际上是同一个请求或是同一个请求的多次尝试。这往往需要双方有一个既定的协议, 比如账单号或者交易令牌,这种在同一个请求上具备唯一标识的元素,这种元素通常由客户端生成。
第二个因素是确保唯一性(Uniqueness Guarantee)。服务器端用什么机制去确保同一个请求一定不会被处理两次,也就是微信支付如何确保,同一笔交易不会因为客户端发送两 次请求就被处理多次。
机制
一是幂等令牌什么时候产生,怎样产生。这一点很重要。拿上面的例子来说,就算微信支付可以保证,每一个请求对应的支付交易一定只会被处理一次,但是这个请求的多次重复,一定要共有微信可以识别的某个标识。
二是令牌有没有被误删的可能。这是上面问题的一个特殊情况。幂等令牌是由客户端生成的,那如果生成的令牌在被使用后(一次微信支付请求中使用了),不小心因为数据库回滚 (DB Rollback) 等原因被删除了,那么客户端就不知道自己其实已经发过一次请求。这就有可能生成一个新的账单,并产生全新的令牌,而服务端对此则一无所知。
三是各种竞争条件。我在前面讲过,用数据库的读检查来确保唯一性经常因为竞争而不生效,其实一个需要幂等的系统中,保证唯一性的各个环节和实现,都要考虑竞争条件(Race Condition)。
四是对请求重试的处理。这大部分是服务器端要做的工作。一个常见的方法是:区分正在处理的请求、处理成功和处理失败的请求。这样当客户端重试的时候,根据情况或者直接返 回,或者再次处理。这就好像之前提到的微信支付的例子,微信支付服务需要知道每一笔交易的处理情况,只有这样,当面对再次转账请求时,才能知道应该用什么方式去处理相应 的请求。
五是一个系统中需要多层幂等。这是什么意思呢?A 发送请求给 B,B 处理的一部分是要发送请求给另一个系统 C,C 在处理的过程中还可能需要发请求给另一个系统 D ...... D 处理 完了返回给 C,C 返回给 B,B 返回给 A。在这个链条中,如果 A、B、C、D 中任何一个系统没有正确实现幂等,也就是出现了 “幂等漏洞”,那么一次请求还是有可能被多次执 行,产生区别于一次执行的影响。
部署
负载均衡
客户端集中的某个物理区域,最好把副本放在离客户端最近的地方。但是如果客户端突然流量猛增,可能导致最近的副本崩溃,然后是第二近的副本,以此类推,最终造成连锁故障。
当集群部署在不同的数据中心,有可能出现Leader失败,新的Leader所处的数据中心承受不住Leader的流量。因为Leader的流量会相对副本来说更大
多个集群的Leader,尽量平均部署在多个数据中心,防止一个数据中心的出口成为瓶颈。

1eee0
副本的数量
对可靠性的要求
计划内维护的频率
危险性
性能
成本
副本的位置:距离越远,性能月底,但是承受失败的程度也会增加
故障承受能力
延迟的敏感性
故障恢复
客户端可见性能
监控
每个集群的成员数量,以及每个成员的状态(健康/不健康)
始终落后的副本
领头人角色是否存在
领头人角色变化的次数
共识交易记录数字
系统中的提议数量,以及系统中被接受的提议数量
吞吐量的延迟
针对提议接收时间的延迟分布
系统不同部分之间观察到的网络延迟
接收者在持久化日志上花费的时间
系统每秒处理的字节数

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: