【深度】分布式数据库数据一致性原理说明与实现

前言算法

分布式数据库的数据一致性管理是其最重要的内核技术之一,也是保证分布式数据库知足数据库最基本的 ACID特性中的 “一致性”(Consistency)的保障。在分布式技术发展下,数据一致性的解决方法和技术也在不断的演进,本文就以做者实际研发的分布式数据库做为案例,介绍分布式数据库数据一致性的原理以及实际实现。数据库

1. 数据一致性

1.1 数据一致性是什么

大部份使用传统关系型数据库的DBA在看到“数据一致性”时,第一反应可能都是数据在跨表事务中的数据一致性场景。可是本文介绍的“数据一致性”,指的是“数据在多份副本中存储时,如何保障数据的一致性”场景。安全

因为在大数据领域,数据的安全再也不由硬件来保证,而是经过软件手段,经过同时将数据写入到多个副本中,来确保数据的安全。数据库在同时向多个副本写入记录时,如何确保每一个副本数据一致,称为“数据一致性”。服务器

1.2 关系型数据库如何保障数据一致性

传统的关系型数据库对于运行环境--硬件要求都比较高,例如Oracle会建议用户使用小型机+共享存储做为数据库的运行环境,DB2 DPF也一样建议用户采用更好的服务器+高端存储来搭建数据库的运行环境。因此在数据存储安全的技术要求下,传统关系型数据库更可能是依赖硬件的技术来保障数据的安全性。并发

              

由于关系型数据库的数据安全是基于硬件来保障,而且数据也不会经过同时存储多份来保障数据的安全,因此关系型数据库的用户默认认为数据存储是一致的。异步

1.3 分布式存储如何保障数据一致性

本文在讨论分布式存储时,主要指的是大数据产品中的分布式文件系统和分布式数据库,例如:SequoiaDB和HDFS。分布式

用户在搞明白分布式存储的数据一致性原理时,必需要先明白为何他们就须要数据一致性,和分布式存储的数据存储与关系型数据库的数据存储又有什么区别。性能

大数据技术的诞生,确确实实让系统的性能有新的突破,而且支持硬件以水平扩展的方式来得到线性增加的性能和存储。这些都是过去传统关系型数据库所没法提供的。另外,大数据技术也抛弃了运行环境必须足够好的硬性要求,而是容许用户经过批量廉价X86服务器+本地磁盘的方式搭建规模集群,从而得到比过去依赖硬件垂直扩展所提供的更强的计算能力和更多的存储空间。大数据

大数据技术的核心思想就是分布式,将一个大的工做任务分解成多个小任务,而后经过分布式并发操做的方式将其完成,从而提升整个系统的计算效率或者是存储能力。而在分布式环境下,因为硬件的要求下降,必然须要大数据产品提供另一个重要的功能--数据安全。spa

大数据产品在解决数据安全的方式上,都比较接近,简单来讲,就是让一份数据经过异步或者同步的方式保存在多台机器上,从而保障数据的安全。

                             

分布式存储在解决数据安全的技术难点后,又引入了一个新的技术问题,就是如何保障多个副本中的数据一致性。目前SequoiaDB是使用Raft算法来保证数据在多个副本中一致性。

2. Raft算法

2.1 Raft算法背景

在分布式环境下,最著名的一致性算法应该是Paxos算法,可是因为它实在过于晦涩难懂,而且实现起来极度困难,因此在2013年,Diego Ongaro、John Ousterhout两我的以易懂(Understandability)为目标设计了一套一致性算法Raft。Raft算法最大的特色在于简单易懂,而且实现起来简单。

2.2 Raft算法概述

与Paxos不一样,Raft强调的是易懂,Raft和Paxos同样只要保证n/2+1节点正常就可以提供服务。

众所周知当问题较为复杂时能够把问题分解为几个小问题来处理,Raft也使用了分而治之的思想。Raft算法重点解决三个子问题:选举(Leader election)、日志复制(Log replication)、安全性(Safety)。

Raft算法强化了Leader节点的功能,Follower节点的数据只可以从Leader中获取,因此Follower节点的实现就变得简单,只要负责和Leader保持通讯,而且接受Leader推送的数据便可。

2.3 Raft算法原理

2.3.1 节点角色

Raft算法中,对节点的状态分为3种角色,分别是Leader(领导者)、Follower(追随者)和Candidate(候选者)。

Leader,负责处理来自客户端的请求,负责将日志同步到Follower中,而且保证与Follower之间的heartBeat联系;

Follower,当集群刚刚启动时,全部节点均为Follower状态,它的工做主要为响应Leader的日志同步请求,响应Candidate的请求,以及把请求到Follower的事务请求转发给Leader;

Candidate,选举Leader时负责投票,选举出来Leader后,节点将从Candidate状态变为Leader状态。

                  

2.3.2 Terms

在分布式环境下,“时间同步”一直都是老大难的技术难题。Raft为了解决这个问题,将时间划分为一个一个的Term(能够理解为“逻辑时间”)来处理在不一样时间段里的数据一致性。

Terms有如下原则

1 每一个Term中,至多存在一个Leader

2 某些Term中,有可能存在因为选举失败,没有Leader的状况

3 每一个节点本身维护本地的currentTerm

4 每一个Term都是一个连续递增的编号

5 若是Follower的Term编号比别的Follower Term编号小时,该Follower Term编号将更新Term编号,以保持与其余Follower Term编号一致

2.3.3 选举

Raft的选举由定时器触发,每一个节点的触发时间都不相同。

全部的节点在开始时状态都为Follower,当定时器触发选举后Term编号递增,该节点的状态由Follower转为Candidate,而且向其余节点发起RequestVote RPC请求,这时选举有3种状况可能发生:

1 发起RequestVote的节点收到n/2+1(过半数)个节点的投票,该节点将从Candidate状态变为Leader状态,开始向其余节点发送HeartBeat以保持Leader的正常状态

2 若是收到投票请求后,该节点发现发起投票的节点Term大于本身,则该节点状态从Candidate转为Follower,不然保持Candidate状态,而且拒绝该投票请求

3 选举期间发生了超时,则Term编号递增,从新发起选举

                     

2.3.4 日志复制

日志复制主要的做用就是用来保证节点的数据一致性与高可用性。

当Leader被选举出来后,全部的事务操做都必需要通过Leader处理。这些事务操做成功后,将会被按顺序写入到LOG中,每一个LOG都包含一个index编号。

Leader在LOG发生变化后,经过HeartBeat将新的LOG同步到Follower上,Follower在接收到LOG后,再向Leader发送ACK信息,当Leader接到大多数(2/n+1)Follower的ACK信息后,将该LOG设置为已提交,而且Leader将LOG追加到本地磁盘中。

同时Leader将在下一个HeartBeat中,通知全部的Follower将该LOG存储在各自的本地磁盘中。

2.3.5 安全性

安全性是用于确保每一个节点都是按照相同的日志序列进行执行的安全机制。

若是当某个Follower在同步Leader的日志时失败,可是将来该Follower又可能被选举为Leader时,就有可能致使前一个Leader已经commit的日志发生覆盖,这样就致使了节点执行不一样序列的日志。

Raft的安全性就是用于保证选举出来的Leader必定包含先前已经commit LOG 的机制,主要遵循的原则以下

1 每一个Term 只能选举一个Leader

2 Leader的日志完整性,则当Candidate从新选举Leader时,新的Leader必需要包含先前已经commit的LOG

3 Candidate在选举新的Leader时,使用Term来保证LOG的完整性

3. 分布式数据库数据一致性技术实现

以国产原厂的分布式数据库SequoiaDB为例,SequoiaDB在多副本的部署中,采用Raft算法保证数据在多副本环境中保持一致。

SequoiaDB集群中,总共包含3中角色节点,分别是协调节点、编目节点和数据节点。因为协调节点自己不存任何数据,因此只有编目节点和数据节点存在事务操做,换言之,编目分区组和数据分区组的副本同步采用Raft算法保证数据一致性。

                 

3.1 编目节点和数据节点的事务日志介绍

编目节点和数据节点因为都是须要存储数据的,而且在集群部署中该,为了确保数据的安全,都是建议采用分布式的方式进行部署,因此在数据同步中,须要采用Raft算法的基本原理进行数据同步。

编目节点和数据节点在存储数据时,共包含两大部分,一个真实的数据文件,另外一个是事务日志文件。

                

SequoiaDB的节点事务日志,默认状况下由20个64MB(总大小为1.25GB)的文件构成。节点的事务日志主要包含一个index编号和数据操做内容,index编号保持永远递增状态。

另外,SequoiaDB节点的事务日志不会永久保存,而是当全部的事务日志写满后,再从新从第一个文件开始进行覆盖写入。

3.2 编目分区组的数据一致性

因为编目分区组是保存SequoiaDB集群的元信息,数据同步要求高,因此编目分区组的数据一致性要求为强一致性,即每次向编目分区组执行事务操做时,必需要确保全部的编目节点操做成功,才计算该操做执行成功,不然该事务操做将在整个编目分区组中回退事务日志,以保证分区组内的数据一致性。

另外,编目分区组还有一个比较重要的特性,即编目分区组必需要存在主节点才可以正常工做,若是老的主节点宕机了,编目分区组暂时没有主节点,则该编目分区组不可以对外提供任何事务操做和数据查询操做。

3.3 数据分区组的数据一致性

数据分区组的数据一致性默认状况下为最终一致性性,即只要求主节点执行事务操做成功即视为操做成功,主节点将在将来异步同步ReplicaLOG到从节点上。

3.4 主从节点的事务日志同步

SequoiaDB的主从节点是经过事务日志同步来保证数据一致性的,而且主从节点的事务日志同步是单线程完成。

若是当主节点和从节点的LSN差距为一条记录,则主节点会主动将最新的事务日志推送给从节点。

若是主节点和从节点的LSN差距超过一条记录,则从节点会主动向主节点请求同步事务日志,主节点收到同步请求后,会将从节点的LSN号到主节点最新的LSN号对应的事务日志打包一次性发送给从节点。

 

3.5 从节点日志重放

当从节点获取到主节点推送过来的事务日志后,就会自动解析事务日志和重放。从节点在重放事务日志时,默认状况下会以10并发来重放事务日志。

从节点在执行并发重放日志时有条件限制,即在集合的惟一索引个数<=1的状况下,INSERT、DELETE、UPDATE、LOB WRITE、LOB UPDATE、LOB REMOVE操做能够支持并发重放事务日志。从节点在作并发重放时,是经过记录的OID进行打散并发执行,这样就能够保证对相同记录的操做不会因为并发重放致使数据不一致。

可是用户须要注意,从节点在重放事务日志时, DROP CL操做不可以支持并发重放。

4. SequoiaDB数据一致性应用

目前SequoiaDB数据分区组的数据一致性是基于集合级别进行配置的。用户在使用SequoiaDB过程当中,能够随时调整数据一致性的强度。

4.1 建立集合时指定

在一个多副本的SequoiaDB集群中,集合默认的数据一致性行级别为“最终一致性”。用户能够在建立集合时显式指定该集合的“数据一致性强度”,例如能够在SequoiaDB Shell中执行如下命令

db.CSNAME.createCL("CLNAME", {ReplSize:3})

ReplSize参数填写范围

数值

参数说明

-1

表明弹性强一致性;

例如副本数为3,当全部的副本节点都正常运行时,数据库将确保数据同时成功写入3个副本中才提交该事务日志;

若是其中一个节点宕机,可是该数据分区组中仍然存在主节点,则数据库须要确保数据同时成功写入2个副本中才提交事务日志。

0

表明强一致性;

例如副本数为3,当全部的副本节点都正常运行时,数据库将确保数据同时成功写入3个副本中才提交该事务日志;

若是其中一个节点宕机,可是该数据分区组中仍然存在主节点,则数据库仍然须要确保数据同时成功写入3个副本中才提交事务日志,因此当分区组中存在宕机节点,则该数据分区组没法写入新的记录。

1-7

1-7数值表明分区组中写入记录时,应该确保写入到多少个节点中,才能够提交该事务日志,不然认为该事务操做失败,另外,若是填写的数值大于数据分区组全部的节点数目,则以数据分区组的最大节点数目为生效RepliSize值,可是在数据库SDB_SNAP_CATALOG快照中依然显式用户填写的ReplSize数据。

4.2 修改已经存在的集合

若是集合在建立时没有设置“数据一致性”ReplSize参数,用户也能够对已经存在的集合进行修改,在SequoiaDB Shell修改命令以下

db.CSNAME.CLNAME.alter ({ReplSize:3})

ReplSize的取值范围和建立集合时一致。

4.3 如何查看集合的ReplSize参数

若是用户但愿检查当前集合的RepliSize参数值,能够经过数据库快照进行查看,在SequoiaDB Shell查看命令以下

db.snapshot(SDB_SNAP_CATALOG, {}, {"Name":null, "IsMainCL":null, "MainCLName":null, "ReplSize":null})

打印信息以下

{

  "MainCLName": "test.main2",

  "Name": "foo.bar2",

  "IsMainCL": null,

  "ReplSize": null

}

{

  "IsMainCL": true,

  "Name": "test.main2",

  "MainCLName": null,

  "ReplSize": null

}

{

  "Name": "foo.tt",

  "ReplSize": 3,

  "IsMainCL": null,

  "MainCLName": null

}

5. 总结

分布式的数据库,经过Raft算法来确保在分布式状况上数据的一致性,而且编目分区组和数据分区组对数据一致性要求又有所不一样,编目分区组始终要求的是数据在多副本请状况下数据强一致性,而数据分区组则能够由用户在建立集合时来执行数据一致性的强度,强度越高,数据安全性越好,可是执行的效率就会相对较差,反之依然。

目前SequoiaDB在数据一致性场景上,用户的调整空间较大,能够根据不一样的业务要求来调整数据一致性的强度,以知足业务或追求性能最优,或者数据最安全的技术要求。

 

SequoiaDB巨杉数据库简介:

SequoiaDB是业界领先的新一代分布式数据库产品,功能上包括了分布式OLTP,分布式对象存储以及分布式NoSQL实现全类型数据的覆盖。SequoiaDB为用户提供高性能、灵活存储、实时与可扩展等企业级数据库能力。

                    

相关文章
相关标签/搜索