Zookeeper并不保证读取的是最新数据

Zookeeper并不保证读取的是最新数据

原文地址:http://www.crazyant.net/2120.html

如果是对zk进行读取操作,读取到的数据可能是过期的旧数据,不是最新的数据。

已上图为例,如果一个zk集群有10000台节点,当进行写入的时候,如果已经有6K个节点写入成功,zk就认为本次写请求成功。但是这时候如果一个客户端读取的刚好是另外4K个节点的数据,那么读取到的就是旧的过期数据。

在zk的官方文档中对此有解释,地址在:https://zookeeper.apache.org/doc/r3.1.2/zookeeperProgrammers.html

zookeeper一致性的保证:

ZooKeeper是一种高性能,可扩展的服务,虽然读取速度比写入快,但是读取和写入操作都设计的极为快速,这样做的原因是在读取的情况下,ZooKeeper可能会提供较旧的数据,但这是为了ZooKeeper的一致性保证:

  • 顺序一致性:来自客户端的更新将按照发送的顺序被写入到zk
  • 原子性:更新操作要么成功要么失败,没有中间状态
  • 单系统快照:客户端将看到服务的相同视图,而不管它连接到的服务器。
  • 可靠性:一旦应用更新,数据将被持久化,直到数据被再次更新,对于该保证有两个推论:1、如果客户端得到了成功的返回码,说明写入成功,数据被持久化,如果出现了通信错误,超时等一些故障,客户端将不知道更新是否已应用。我们采取措施尽量减少失败,但唯一的保证是只有成功的返回码。 (这在Paxos中称为单调性条件。)2、如果客户端已经读取到了数据或者写入成功了数据,都不会因为zk的失败而导致回滚;
  • 及时性:在一段时间后,客户端将看到最新的系统更新,在此期间客户端将看到这种变更。

有时开发人员错误地假定ZooKeeper实际上没有做出另一个保证:跨客户端的强一致性

ZooKeeper并不保证在每个实例中,两个不同的客户端将具有相同的ZooKeeper数据的视图。由于诸如网络延迟的因素,一个客户端可以在另一客户端被通知该改变之前执行更新,考虑两个客户端A和B的场景。如果客户端A将znode / a的值从0设置为1,则告诉客户端B读取/ a,则客户端B可以读取旧值0,这取决于它连接到的服务器。如果客户端A和客户端B读取相同的值很重要,则客户端B应该在执行读取之前从ZooKeeper API方法调用sync()方法。

因此,ZooKeeper本身不保证所有服务器上同步发生变化,但ZooKeeper原语可用于构建更高级的函数,提供有用的客户端同步。

zk的sync方法的解释:异步的实现当前进程与leader之间的指定path的数据同步;

CAP理论

理论计算机科学中,CAP定理(CAP theorem),又被称作布鲁尔定理(Brewer’s theorem),它指出对于一个分布式计算系统来说,不可能同时满足以下三点:

  • 一致性(Consistence) (等同于所有节点访问同一份最新的数据副本)
  • 可用性(Availability)(每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据)
  • 分区容错性(Network partitioning)(以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。)

根据定理,分布式系统只能满足三项中的两项而不可能满足全部三项。理解CAP理论的最简单方式是想象两个节点分处分区两侧。允许至少一个节点更新状态会导致数据不一致,即丧失了C性质。如果为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了A性质。除非两个节点可以互相通信,才能既保证C又保证A,这又会导致丧失P性质

对于zookeeper来说,它实现了A可用性、P分区容错性、C中的写入强一致性,丧失的是C中的读取一致性。

有所丧失,才有所获得,没有十全十美。

原文地址:https://www.cnblogs.com/mkl34367803/p/10704517.html

时间: 2024-10-16 08:11:46

Zookeeper并不保证读取的是最新数据的相关文章

Java InputStream读取网络响应Response数据的方法!(重要)

原文:Java InputStream读取网络响应Response数据的方法!(重要) Java InputStream读取数据问题 ====================================================================== 原理讲解 1. 关于InputStream.read() 在从数据流里读取数据时,为图简单,经常用InputStream.read()方法.这个方法是从流里每次只读取读取一个字节,效率会非常低.     更好的方法是用Inp

分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要)

原文:分享非常有用的Java程序(关键代码)(八)---Java InputStream读取网络响应Response数据的方法!(重要) Java InputStream读取数据问题 ====================================================================== 原理讲解 1. 关于InputStream.read()      在从数据流里读取数据时,为图简单,经常用InputStream.read()方法.这个方法是从流里每次只读

NPOI读取Excel,导入数据到Excel练习01

NPOI 2.2.0.0,初级读取导入Excel 1.读取Excel,将数据绑定到dgv上 1 private void button1_Click(object sender, EventArgs e) 2 { 3 List<Book> books = new List<Book>(); 4 //1.读取Excel文件 5 using (FileStream fsReder = File.OpenRead("练习.xlsx")) 6 { 7 //2.创建工作簿

读取文件中的数据(以结构体存放)

/* *读取文件中的数据(数据以结构体存放) */ #include<iostream> #include <fstream> //#define Field 31 //field_anal number #define Field 15 //field_post number using namespace std; //the level restore certain level data //level_z show the level struct Level { int

PHP读取EXCEL时写入数据乱码解决办法

第一步排除excel读取的数据是不是乱码 EXCEL读取时经常会出现乱码,而我们常用的字符集是UTF-8 ,GB2312(GBK) ,这就需要对编码进行转换,但是又不能对纯数字和英文字符转换,否则会乱码,而只要有一个中文字符时,就必须转换编码. 个人总结了下EXCEL中经常出现的数字和英文字符,写了一个正则表达式来匹配它们,当匹配成功时,不对其做转换,反之转换成GBK或者UTF-8. /* * @param $value 从EXCEL中读取的单元格数据 * @param $toCharset 要

【记录】T-SQL 分组排序中取出最新数据

原文:[记录]T-SQL 分组排序中取出最新数据 示例 Product 表结构: 示例 Product 表数据: 想要的效果是,以 GroupName 字段分组,取出分组中通过 Sort 降序最新的数据,通过示例数据,可以推算出结果数据的 ID 应该为:7.5.3. 示例 SQL 代码: select * from Product p where ID=(select top 1 ID from Product where p.GroupName=GroupName order by Sort

读取数量不定的数据输入

//学习读取数量不定的数据输入#include<iostream>using namespace std; int main(){ int sum=0,value=0; while(cin>>value) //边读取边计算. { sum+=value; cout<<"sum is "<<sum<<endl; } return 0;} 令去掉大括弧{}:结果完全不同 while(cin>>value) //读取结束,

JAVA写个东西读取TXT中的数据 且要计算出平均值和总值 最后还要按总值排序

AVA写个东西读取TXT中的数据 且要计算出平均值和总值 最后还要按总值排序 例如:要计算a.txt文档中内容可如下: 学号 姓名    语文 数学 英语 平均值 总值 排序 1    肯德基   90   98   97 2    经典款   98   97   92 3    肯德的   93   92   97 import java.io.*; import java.io.File; import java.util.ArrayList; import java.util.Iterat

Spark读取Hbase中的数据_云帆大数据分享

Spark读取Hbase中的数据 大家可能都知道很熟悉Spark的两种常见的数据读取方式(存放到RDD中):(1).调用parallelize函数直接从集合中获取数据,并存入RDD中:Java版本如下: 1 JavaRDD<Integer> myRDD = sc.parallelize(Arrays.asList(1,2,3)); Scala版本如下: 1 val myRDD= sc.parallelize(List(1,2,3)) 这种方式很简单,很容易就可以将一个集合中的数据变成RDD的初