能够容忍节点的failure只是想要拷贝的理由之一,其他的理由还包括扩展性(比单个机器处理更过的请求)以及延迟(从地理上,把复制品放在离用户更近的地方)。
Leader-based复制品要求所有的写请求都经由某单一节点,但读请求可以查询任意复制品。这对于负载是大量读请求而写请求只占很小百分比的情况(网页的一般情形),是很有吸引力的:创建很多的follower,并且把读请求分散在这些follower间。这可以去除leader的负载,并且允许用就近的复制品为读请求服务。
在这种读请求扩展read-scaling的架构下,你可以简单的通过增加更多的follower来提升只读请求的能力。然而,这种方法只对于异步的复制品是实际可行的,如果你想对follower采用同步机制的话,一个节点的failure或者是网络瘫痪就会使得整个系统不能再写数据。并且,你有的节点越多,那么单个节点的宕机可能性就越大,因此,一个完全同步的配置是不现实的。
不幸的是,如果一个应用的读来自一个已不的follower,如果这个follower的更新有所落后,那么应用看到的将是过时的信息。这会导致明显的数据库的不一致:
如果你在leader和follower那同时运行同样的查询,你会得到不一样的结果,因为并不是所有的写请求都已经反应到follower那。
这种不一致性就是一个临时的状态 - 如果你停下对数据的写请求并且等一会,最终eventually follower会赶上并且和leader保持一致的。因为这个原因,这一影响被称为evetual consistency。
术语“eventually最终”有一点故意的模糊性质:一般来说,对于复制品落后多少更新是没有限制的。在正常操作下,一个发生在leader和反应到follower之间的写请求的延迟,也叫拷贝延迟replication lag,可能不到一秒,在实际中不会被注意到。然而,如果系统的运行接近系统的最大容量或者网络上有问题,那么这个lag就会很容易增加到几秒或是几分钟。
当lag很大时,那么刚才被提及的不一致性就不是理论上的问题了,对于应用程序来说也是一个实际的问题。下面我们将讨论,