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