前言
这篇文章主要是记录文,用于记录一下最近看到的关于分布式一致性的一些核心理念。
ACID
事务是由一系列对系统中数据进行访问与更新的操作所组成的一个程序执行逻辑单元,狭义上的事务特指数据库事务。事务具有ACID属性。
Atomicity 原子性
事务中包含的各项操作在一次执行过程中,只允许出现全部执行成功或是全部不执行两种状态。任何一项操作失败都将导致整个事务失败,同时其他已经被执行的操作都将被撤销并回滚。
Consistency 一致性
事务的执行不能破坏数据库数据的完整性和一致性。一个事务执行之前和执行之后,数据库都必须处于一致性的状态。当数据库只包含成功事务提交的结果时,就能说数据库处于一致性状态。而如果数据库系统在运行过程中发生故障,有些事务尚未完成被迫中断,这些未完成的事务对数据库所做的修改有一部分已经写入物理数据库。这时数据库就处于不一致状态。
Isolation 隔离性
并发的事务是相互隔离的,一个事务的执行不能被其它事务干扰。即,不同事务并发操纵相同的数据时,每个事务有各自完整的数据空间。事务的四个隔离级别如下:
Read Uncommited 读未提交
允许脏读,隔离界别最低。如果一个事务正在处理某一数据,并对其进行了更新,同时尚未完成事务,即没有进行事务提交。但是,与此同时,允许你另一个事务能够访问该数据。
Read Commited 读已提交
和读未提交的区别在于只允许获取已经被提交的数据。但是无法实现可重复读取。即如果事务A在同一个事务中执行了两次对同一条数据的select操作,同时事务B和C分别在第一条select之前和第二条select之前执行了对该数据的更新操作,那么A的两条select将得到不同的数据。
Repeatable Read 可重复读
在事务处理过程中,多次读取同一个数据时,其值和事务开始时刻是一致的。但是该级别会出现幻读。
幻读:第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
Serializable
要求所有的事务被串行执行,即事务只能一个接一个的进行处理,不能并发执行。
Durability 持久性
一个事务一旦提交,它对数据库中对应数据状态的变更就应该是持久性的。也就是说,即使发生系统崩溃,只要数据库能够重启,就一定能够将其恢复到事务成功结束时的状态。
CAP
Consistency 一致性
在分布式环境中,一致性是指数据在多个副本之间能够保持一致性。当一个系统在数据一致的状态下执行更新操作后,应该保证系统的数据仍然处于一致的状态。在分布式系统中,如果能够在一个数据项的更新操作执行成功后,所有的用户都可以读取到其最新的值,那么这样的系统就被任务具有强一致性。
Availability 可用性
系统一直处于可用的状态,对于每一个操作请求总能够在有限时间内返回结果。有限时间是指能够在指定的响应时间内返回对应的结果,超过这个时间即可认为系统不可用。指定的响应时间通常根据不同的系统有不同的标准。返回结果是指能够正常的相应结果,而不是看到系统错误等信息。
Partiion Tolerance 分区容忍性
分布式系统在遇到任何网络分区的故障的时候,仍然需要能够保持对外提供满足一致性和可用性的服务,除非整个网络环境都发生了故障。
BASE
Basically Available 基本可用
分布式系统在出现不可预知的故障的时候,允许损失可用性(不是说系统不可用)。比如响应时间比指定时间长一点,在功能上进行限流降级熔断等等。
Sofa State 弱状态
允许系统中的数据存在中间状态,并认为该中间状态的存在不会影响系统的整体可用性,即允许系统的不同节点之间的数据副本之间进行数据同步的过程中存在延时
Eventually Consistent 最终一致性
最终一致性强调系统中所有的数据副本,在经过一段时间的同步之后,最终能够达到一致的状态。这是相对于实时强一致而产生的概念。
Casual Consistency 因果一致性
进程A在更新完某个数据之后通知了进程B,那么进程B之后对该数据项的访问都应该能够获取到进程A更新后的最新值。即如果B依赖于A的更新,则更新必须顺序进行。但是与进程A无因果关系的进程C则无这样的限制。
Read Your Writes 读己之所写
进程A更新一个数据项之后,自己总是能够访问到更新过后的最新值,而不是看到旧值。即一种特殊的因果一致性。
Session Consistency 回话一致性
系统保证在一个有效的回话中实现读己之所写一致性。也就说,执行更新操作后,客户端能够在同一个回话中始终读取到该数据项的最新值。
Monotonic Read Consistency 单调读一致性
如果一个进程从系统中读取出一个数据项的某个值后,那么系统对于该进程后续的任何数据访问都不应该返回更旧的值。
Monotonic Write Consistency 单调写一致性
一个系统需要能够保证来自同一个进程的写操作能够顺序执行。
分布式事务中的两种角色
分布式事务中的组件有两种角色:
- 协调者:统一调度所有分布式节点的执行逻辑
- 参与者:被调度的分布式节点
Two-Phase Commit 2PC
阶段一:提交事务请求(投票阶段)
- 事务询问。协调者询问所有参与者发送事务内容,询问是否可以执行事务提交操作,并等待各个参与者的相应
- 执行事务。各参与者执行事务操作,并将undo和redo信息记入事务日志中
- 各参与者向协调者反馈事务询问的响应
阶段二:执行事务提交(执行阶段)
根据参与者额反馈情况来决定最终是否可以进行事务的提交
情况一:执行事务提交,即收到的反馈都是YES
- 协调者发送提交请求
- 事务提交:参与者收到提交请求之后,正式执行事务提交,提交之后释放在整个事务执行期间占用的事务资源
- 反馈事务提交ACK结果
- 完成事务
情况二:中断事务,即收到了No响应
- 协调者发送回滚请求
- 参与者利用undo日志的信息进行事务回滚,并在回滚完成之后释放在整个事务执行期间占用的事务资源
- 反馈事务回滚结果
- 完成事务中断
优点:原理简单,实现方便
缺点:同步阻塞,单点问题(协调者),太过保守
Three-Phase Commit 3PC
阶段一:CanCommit
- 事务询问。协调者向所有参与者发送一个包含事务内容的canCommit请求,询问是否可以执行事务提交操作
- 参与者根据自身情况向协调者反馈事务询问
阶段二:PreCommit
根据CanCommit的回复可以产生以下两种操作:
情况一:执行事务预提交
假设收到的ACK均为YES,则
- 发送PreCommit请求
- 参与者执行事务操作,并将Undo和Redo信息记录到事务日志中
- 参与者向协调者反馈事务执行的响应
情况二:中断事务
假设收到了至少一个ACk为NO或是等待超时
- 协调者发出中断请求
- 参与者收到协调请求或是等待超时,都会中断事务
阶段三:DoCommit
情况一:执行提交
收到PreCommit阶段的全部ACK
- 发送提交请求
- 事务提交
- 反馈事务提交结果
- 完成事务
情况二:中断事务
假设协调者没有收到全部的YES ACK则
- 发送中断请求
- 事务回滚
- 反馈事务回滚结果
- 中断事务
优点:降低参与者阻塞范围
缺点:参与者收到preCommit消息后,如果网络出现分区,此时协调者所在的节点和参与者无法进行正常的网络通信。这种情况下,参与者依然会进行事务提交,从而出现数据的不一致性,
想要了解更多开发技术,面试教程以及互联网公司内推,欢迎关注我的微信公众号!将会不定期的发放福利哦~
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。