副本更新策略
通常情况,大规模分布式存储系统会将一份数据在系统内复制多份并保存在不同的存储。一方面可以通过数据冗余来增加系统的可用性,另一方面也可以增加读操作的并发程度。在多副本的情况下,有3种可能的更新策略:同时更新策略、主从式更新策略和任意节点更新策略。
同时更新
类型1:不通过一致性协议
不通过任何一致性协议直接同时更新多个副本数据。这种情形存在法硕的数据一致性问题:如果同一时刻两个不同的客户端对这个数据同时发出update1和update2更新请求,那么系统会无法确定其执行顺序,这样会在有的副本中,执行顺序是update1–>update2;而在有的副本中,执行顺序是update2–>update1。
类型2:一致性协议预先处理
通过某种一致性协议来预先处理,这种处理可以用来唯一确定不同更新操作的顺序。这样可以保证数据的一致性,但是由于协议本身会有处理成本,从而会增加请求延时。
主从式更新
多个副本之间存在一个主副本(Master Replica),其他副本为从副本,这种称为主从更新策略。所有对数据的更新首先提交到主副本,再由主副本通知从副本进行数据更新。如果同时产生多个数据更新操作,由主副本决定不同更新操作的顺序。
类型A:同步方式
主副本等待所有从副本更新完成之后才确认更新操作完成,这样确保数据的强一致性,但是会存在较大的请求延时,尤其是在多副本跨数据中心的情形下,因为请求延时取决于最慢的那个副本的更新速度。
类型B:异步方式
主副本在通知从副本更新之前即可确认更新操作。假设主副本还没有通知任何其他从副本就发生崩溃,那么数据一致性可能会出现问题,一般首先在另外的可靠存储位置将这次更新操作记录下来,以防这种情况发生。
- 所有读请求都通过主副本来响应,任意一个副本接收到读请求后转发为主副本,可以保证强一致,但是本来可以由距离近的副本响应的操作又得转发给距离较远的主副本,增加了请求延时,Google的Chubby采用这种方式。
- 任意一个副本都可以响应读请求,请求延时大大降低,但是可能导致读不一致,因为有些副本可能还存在旧版本的数据,Zookeeper就是采用这种方法获得低延时,但牺牲了一致性。
类型C:混合方式
同步混合异步,主副本首先同步更新部分从副本,然后确认更新操作完成,其他副本通关异步方式获得更新,Kafka就是采用这种混合方式来维护数据副本的不一致性。
- 读操作至少要从一个同步更新的节点读出,类似RWN协议的R+W>N,可保证强一致性,但是请求延时加大
- 读操作不要求一定从至少一个同步更新节点读出,那么会出现类型B的第2种不一致性情形。
任意节点更新
客户端的数据更新请求可能会发给多副本中的任意一个节点,由这个节点负责通知其他节点进行数据更新,这种方式与“主从式更新”的区别是:对于数据的更新操作请求,并不存在某个指定的首先进行响应的主副本,而是任意一个节点都可以进行响应。它的特殊性在于:在同一时刻,有两个不同的客户端对同一数据进行更新操作请求,而此时有可能有两个不同的副本各自响应。
这种方式下的请求延时和数据一致性之间的权衡也有2种情况:
类型1:同步通知其他副本
这种情况与”主从式更新”中的类型1相似。此外,为了识别出是否存在客户端同时更新不同副本的情况,还需要付出更多的请求延时。
类型2:异步通知其他副本
这种情况与”同时更新策略”及”主从式更新策略”的类型2相似。
正常情况下,”主从式更新”的类型3发挥作用,而当主副本发生故障时,”任意节点更新策略”发挥作用。