深入浅出cassandra 4 数据一致性问题概述

/**
*author:ahuaxuan(张荣华)
*date: 2010-2-28
*/

在上一篇文章,ahuaxuan和大家简单的熟悉了cassandra的集群环境的部署,接下来要做的就是搞清除这种部署模型的的理论依据.

理论依据一,数据一致性和W R N

首先简单解释一下数据一致性(这个问题是老生常谈的问题,任何一本应用开发的书上都有它的描述)
所谓的一致性其实就是事物ACID中的C:

事务在完成时,必须使所有的数据都保持一致状态。在相关数据库中,所有规则都必须应用于事务的修改,以保持所有数据的完整性。事务结束时,所有的内部数据结构(如 B 树索引或双向链表)都必须是正确的。

(但是一致性并非只存在于事务环境中,这也就是说我们会有一些系统不能实现A, 或者I,但是能够实现C和D,这里面有一个哲学问题,是不是我们所有的应用都需要事务,如果所有的应用都需要事务,那么几年前mysql的
isam索引为什么会这么流行?所以说事务有事务的用处,非事务由非事务的用途。cassandra0.5中目前还没有实现完整的事务功能,但是已经有不少公司在使用。)

那么举两个非一致性的场景,比如说某个数据存放着两份备份,某一份数据被修改之后,必须保证这份修改被用户看到之前,另一份数据修改也已经完成。
或者说有相互依赖的两条数据,等用户能看到前条数据的时候,他一定能看到第二条数据。否则在修改的过程中,用户拿到了第一条刚修改完的数据,但是在拿第二条数据的时候却拿到了老的数据,
这两种场景都有可能在mysql的master-slaver模型中出现
在master中插入数据,然后去slaver中查找该数据,你有可能查找不到,具体的原因后面会讲到。


但是在这之前我们还得再来看看标题中的3个字母:

N: cassandra网络中复制数据的节点数
R: cassandra网络中读节点数
W:cassandra网络中阻塞写节点数(为什么是阻塞写?后面的文章中会讲到)

为什么要提出这三个概念呢,其实这三个概念和cassandra中的数据一致性和读写性能息息相关.

我们先来看第一个问题,数据一致性.

在一般的数据库集群(或者m-s之流的策略)中,读写操作的一致性问题向来会困扰一部分人,举个例子,在mysql的master和slaver模式中,
写操作总是由master负责,读操作有slaver负责,当然必要时master也可以负责读操作,但是我相信用过mysql的m-s模式的人一般都会碰到一个问题,
就是数据延迟的问题,一条写语句发往master,然后master会把数据复制到slaver上,但是这里有一个问题,复制和插入过程是没有全局锁来保证顺序的,也就是master写往自己,其实客户端就可以
从Master上读取这条数据,但是如果客户端操作的是slaver,那它就要碰运气了,因为复制的时间可长可短,而且和网络环境相关,有的时候数据延迟会高达12分钟.ahuaxuan曾经就碰到复制过程2分钟的场景.

但是如果这里有全局锁来控制复制过程,比如在cluster模型下,那么写操作必须等待所有的机器都写完,那么写操作才能返回,虽然这样容错性得到了保证,但是写操作的性能大大下降,而且集群环境中的节点越多写操作越忙.

在ahuaxuan看来,mysql的cluster模式和m-s模式其实也是W/R/N之间关系的一种表现.
举例来说,在cluster模式中(假设一共3台机器),由于要考虑到读操作和写操作的容错,所以写操作需要有全居锁的保证,而且所有的集群都要响应写操作,而读操作只需要操作一台机器,为啥了,因为所有的数据在用户能读之前都会在所有的mysql机器上.
所以我们可以把这种行为看成: N=mysql的集群数量(3), W=mysql的集群数量(3), R=1

而在m-s模式中,由于写只需要涉及m,所以这里W=1,而读操作也只是涉及到一台机器,所以R=1,而N还是为3,但是正如ahuaxuan论述的那样,m-s是不能保证一致性的,而且不能保证写操作的容错性.

我们再仔细看以下这两个例子的关系
cluster模型中, N=3, W=3(全局锁同步控制), R=1, 可以容错,可以保证一致性. W+R=4 > N=3
M-S模型中, N=3, W=1(slaver是异步复制写,注意,这里不是同步读写,同步的话,这里的W就应该是3), R=1, 读操作可以容错,不能保证数据一致性, W+R=2 < N=3

而amazon论文中对W/R/N的论述大意如下:
如果W+R>N, 那么写读写操作都会有多份,这种模式下可以保证数据的强一致性. 在实现了同步(注意,这里不是异步)数据复制类m-s的场景中,N=2, W=2, R=1,这种模型可以保证数据一致性. 但是如果是异步数据复制的类m-s场景,那么如同ahuaxuan之前举的Mysql例子一样,是不能保证数据一致性的.

那么我们在想远一点,举一个比较极端的例子,如果N=3, W=3, R=1,这种是数据库集群常用的模型,所以在这种场景下读性能会远高于写性能.而如果N=3, R=3, W=1,这种场景下,写一次,但是读取的时候需要读多次,然后比较版本
所以在这种场景下写性能远高于读性能,如果要写性能很高的场景我们一般也不会采取这种模型.

那么我们再回头来看看使用数据库系统的时候我们需要些什么,我们要综合考虑我们的数据特征,然后来判断是水平切分,垂直切分等等,然后还要考虑各种部署模型,m-s, cluster等等.
当然这些技术目前都是比较成熟的,在一些大型的互联网系统,水平和垂直切分已经成了标准做法,而且往往他们和m-s或者cluster模型结合起来使用。
比如说在统计系统中,通常会通过日期来进行水平切分统计数据。在其他和id相关的系统中,可能将id进行hash做水平切分,等等类似的方案有很多。当然也有可能根据常用和非常用来对数据进行垂直切分。
与此同时对数据库进行m-s或者cluster部署(根据业务特征决定),但是由于m-s和cluster的扩展有限,所以通常还会将app和一组数据库(m-s或者cluster部署)绑定,进行整体failover.


但是
即使这样做在容错和水平扩展上还是会有局限性,随着数据量的增大,原来可行的方法会渐渐变得不可行,于是我们不得不寻找新的理论,新的方案,cassandra背后的理论也是在这种需求的促发下产生的.

回到正题,
通过ahuaxuan举了例子,我想同学们应该都基本上对W/R/N之间的关系有了一个比较直观的理解.既然这个话题放在这里说明,那么证明我们的cassandra中也存在这样的问题,
在后面的文章我们会讲到cassandra在网络上其实是dynamo理论的一个实现,这意味着存在如下事实.

每条数据并不是保存在cassandra中所有的节点上,部分数据会保存在部分节点上(而如何确定什么数据保存在什么节点上这是通过一致性hash算法来决定的.)
比如说我们一共有n个节点在网络中,那么如果根据key算出对应的value应该保存在n-m号节点上,那么我们可以认为这个value对象还会有备份在n-m-1,和n-m-2的节点上(假设N=3)
而在读取的时候,我们也可以通过consistency_level来控制R的值,这样对应的在cassandra中, N, W, R的关系也成为我们必须要了解的内容。


在后续的文章中,我们将通过代码来详细的分析cassandra中的数据备份策略,以及读策略, 但是在那之前,我们还需要知道cassandra中的网络模型,
以及W, R, N在cassandra模型中究竟处于什么样的位置。to be continued

上一篇:《Android游戏开发详解》——第2章,第2.13节调用对象的行为


下一篇:使用webgl(three.js)搭建一个3D建筑,3D消防模拟——第三课