那么如何保证副本间的数据一致性?
首先,先确定合法的数据。这里的关键词是“承诺”。比如用户要写入“hello world”,数据通过网络发给存储系统,在存储系统没有反馈之前,用户不能确定写入是否成功,更不能假设写入已经成功。只有当存储系统反馈给用户“你的hello world写入成功”之后 ,数据才算写入成功 —— 这里称之为“承诺”,即底层分布式存储系统承诺数据已经写入,且由多副本机制保护,不会出现错乱或丢失,用户能够读到自己之前写入的数据。
其次,分布式存储系统要遵守“承诺”。在反馈写入成功之后,即使发生部分副本硬件损坏,也不能发生数据丢失。如果出现上述例子中A1损坏,则就是数据丢失,因为余下A2、A3的数据都是跟“承诺”不一样的。
如何做到“遵守”,是分布式存储系统的核心之一。我们举例说明这个问题,以Ceph为例,数据写入请求最终是要发送给三个副本,不过Ceph为这三个副本建立了一主两从的主从关系,数据会单独发送给主副本,再由主副本转达给另外两个从副本。另外数据在三个副本节点上写入的时候,都会先以直写方式写入本地Journal,然后再以非直写的方式写入数据盘。
这里有两个疑问:
1. 为什么采用“一主两从”这样的主从模式?
2. 为什么要写Journal?
先讨论第一个问题“为什么采用主从模式”。首先主副本作为一个结果收集点和用户反馈人。三个副本写入的结果如何,需要有人统一汇总、处理并反馈给用户。如果用户自己来收集和处理,则相当于副本机制侵入到了用户的业务逻辑中,明显不合理。如果另外使用一个专门的节点Cordinator作为中心协调人,三个副本写入的结果都先反馈给Cordinator,再由Cordinator处理和反馈给用户,这样缺点之一是IO路径上多了Cordinator这一跳,则增加了每次IO的耗时。缺点之二是增加了物理资源投入。缺点之三是如果Cordinator故障后,三个副本群龙无首,且Cordinator的重新选取将面临各种不便。
如果使用主从模式,三个副本一主两从,首先避免了上面提到的缺点之一和缺点之二。对比上述缺点之三,主从模式下主副本故障之后,重新选主会更自然轻松。
再讨论第二个问题“为什么要写Journal”。Ceph中“臭名昭著”的double write现象,正是因为写Journal引起的。数据副本在写入时,要求先以直写方式写入Journal,然后再以非直写方式写入文件。如此成本高昂,却仍不得不为之,正体现了Ceph存储系统对数据可靠这一生命线的尊重。因为Ceph Journal的主要作用类似于数据库中的WAL(Write Ahead Log),提供数据写入的原子性,避免故障时造成无法回溯的中间数据。
不过,进一步思考,会产生新的疑问。Journal能避免故障时产生中间数据,即使用Journal之后,数据写入要么完全成功,要么完全失败,不会部分成功。但我们仍然不能判定故障恢复后,副本数据分别是处于“完全成功”还是“完全失败”。Ceph是通过pglog来决定的,pglog由主副本生成并在副本间同步的,它包含了本次数据写入的版本号,并也会被持久化到Journal中。因此故障后副本会比较数据中的版本信息和Journal中的版本信息,由此判定是“完全成功”还是“完全失败”,为集群级别的故障恢复流程提供明确的输入。
综上所述,“遵守”“承诺”并非易事,从其中可见Journal至关重要,没有Journal的分布式存储系统,其数据一致性都将存疑。
来源: http://mp.weixin.qq.com/s/cR1bRBFM-1FZBAu643mgjg