`
邢邢色色
  • 浏览: 226063 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

ZooKeeper学习之本地存储(事务日志与快照)

阅读更多

在上一篇的server代码骨架中已提到,当处理proposal时,是由SyncRequestProcessor来处理的,下面就来对这其中的操作做更详细的分析。


日志和磁盘使用情况

server是使用事务日志来持久化事务的。在accept一个proposal请求之前,server(follower或者leader)把这个proposal以事务的形式持久化到事务日志,按照顺序进行append。server每隔一段时间,时不时的roll over,就是关掉当前的日志文件,并创建一些新的文件继续append。

 

因为写事务日志是写请求的一个关键步骤,所以ZK需要保证这个操作的高效。在硬件上append一个文件是很高效的,但是ZK玩了一些花招可以更快的操作,这就是group commit和padding。group commit在一次写磁盘操作中包括了多个append,这样可以只用一次磁盘寻道的代价持久化多个事务。

 

关于持久化事务日志还有一个重要的事情。现代的操作系统通常会缓存脏页并异步的写入磁盘。

然而我们需要在继续处理之前确保事务已被持久化,所以我们需要把事务刷新到磁盘上。刷新只是意味我们告诉操作系统把脏页写到磁盘上,当操作系统完成时则返回。因为我们在SyncRequestProcessor进行持久化,它的一个职责就是刷新。当需要刷新一个事务到磁盘时,我们实际上做了个优化,把所有进入队列的事务来进行group commit。如果只有一个事务进入队列,它仍然会执行刷新,并不会等待更多事务进入队列,这样可以优化延迟时间。可以参考SyncRequestProcessor.run()来了解细节。

 

磁盘写缓存

只有强制事务日志刷到磁盘后,server才能对proposal进行ack操作。说得更明白一点,server会调用ZKDatabase的commit方法,这最终会调用FileChannel.force方法。这样,server会在ack之前保证事务已被持久化到磁盘。关于此事还有一点要注意,现代磁盘有一个写缓存,可以保存要写到磁盘的数据。如果启用了写缓存,强行刷新不能保证返回的时候数据已落到磁盘,数据会落到写缓存中。为了保证在FileChannel.force()返回后数据落到磁盘,要禁用写磁盘缓存。操作系统有许多方式可以禁用。

 

Padding就是预分配(preallocate)的一个文件的磁盘块(disk block)。这样做是为了更新一个文件对应的文件系统块分配相关的元数据时不会显著的影响这个文件顺序写操作。如果事务以很快的速度append的时候,若这个文件的块没有预分配的话,每当写完一个块的时候,文件系统需要分配一个新的块。这会带来至少两次额外的磁盘寻道:一次是为了更新元数据,另一次是文件的末尾。

 

为了避免受到系统其他写操作的干扰,强烈建议在一个独立的设备写事务日志,使用另一个设备存放快照文件和系统其他文件。

 

快照

快照是ZK的data tree的一份拷贝。每一个server每隔一段时间会序列化data tree的所有数据并写入一个文件。server进行快照时不需要进行协调,也不用暂停处理请求。因为server在进行快照时还会处理请求,所以当快照完成时,data tree 可能会变化。我们称这样的快照是模糊的(fuzzy),因为它们不需要反映出(reflect)在任意给点的时间点data tree确切的状态。

 

举一个例子来说明一下。一颗data tree只有2个znode:/z和/z'。一开始,两个znode的数据都是1。现在有以下操作步骤:


1. 开始一个快照
2. 序列化并写入/z=1到快照
3. 设置/z的数据为2(事务T)
4. 设置/z'的数据为2(事务T')
5. 序列化并写入/z'=2到快照

 

这个快照包含了/z=1和/z'=2。然而在任意的时间点上,data tree的数据都不会跟快照一样。这不是问题,因为server会重放(replay)事务。每一个快照文件会被打上一个标记(tag),这个标记是快照开始的时候最后一个被commit的事务的时间戳,称之为TS。如果server最后加载快照,它会重放在TS之后的所有事务日志中的事务。在这个例子中,它们就是T和T'。在快照的基础上重放T和T'后,server包含/z=2和/z'=2,这是一个合理的状态。

 

还有一个重要的问题,就是说重放事务是否会带来问题,因为在开始快照之后这些事务已经被执行过一次了。其实不会有问题,因为事务是幂等的(idempotent),所以只要我们按照相同的顺序执行相同的事务,就会得到相同的结果,就算它们在生成快照前被执行过。

 

为了理解这个过程,假设执行一个事务,有一些要被重新执行的操作。有两种操作,一个操作设置某个znode的数据为一个特定的值,这个值跟其他东西不相关。另一种操作,无条件(unconditionly)的设置/z'的值(setData请求中的version number为-1),重新执行操作均成功,但最后我们得到了错误的version number,因为我们增加了它2次。下面这种方式会导致问题。假设有如下3个操作并成功执行:


setData /z', 2, -1
setData /z', 3, 2
setData /a, 0, -1

 

第一个setData操作跟我们描述的一样,但是我们加上了2个setData操作来展示在重放中第二个操作没有执行,因为一个不正确的version number。假设这3个操作在提交时被正确执行。又假设server加载最新的快照,快照已包含第一个setData操作。

 

server仍然会重放第一个setData操作,因为快照被一个更早的zxid标记。因为它重新执行了第一个setData操作。version并不匹配第二个setData操作期望的version,那么这个操作无法完成。第三个setData操作可以正常完成,因为它也是无条件的。

 

在加载完快照并重放日志后,server的状态是不正确的,因为它没有包括第二个setData请求。这个操作违反了持久性和正确性,请求的序列应该是没有缺口的(no gap)。

通过让leader来把事务转换成状态的delta来解决这个问题。当leader为一个请求产生事务时,作为事务生成的一部分,包括了一些在这个请求中znode或它的数据的变化的值(delta值),并指定一个特定的version number。最后重新执行一个事务就不会导致不一致的version number。

0
0
分享到:
评论

相关推荐

    zookeeper日志查看工具

    #Zookeeper的日志可以用LogFormatter查看 ##命令方式如下 java -classpath .:slf4j-api-1.7.2.jar:zookeeper-3.4.6.jar org.apache.zookeeper.server.LogFormatter /var/lib/zookeeper/version-2/log.1 ##window...

    Zookeeper学习笔记

    自己整理的ZooKeeper学习笔记,适合刚刚接触ZooKeeper的人学习

    java zookeeper kafka 日志处理

    java zookeeper kafka 日志处理,存储mysql数据库

    有关zookeeper本地伪集群搭建的配置

    有关zookeeper本地伪集群搭建的配置有关zookeeper本地伪集群搭建的配置有关zookeeper本地伪集群搭建的配置

    zookeeper学习笔记

    zookeeper学习笔记

    Zookeeper学习总结

    在Zookeeper中,znode是一个跟Unix文件系统路径相似的节点,可以往这个节点存储或获取数据。如果在创建znode时Flag设置为EPHEMERAL,那么当创建这个znode的节点和Zookeeper失去连接后,这个znode将不再存在在...

    3天全面深入学习zookeeper视频教程

    3天精通zookeeper视频详细讲解,需要的小伙伴自行百度网盘下载,链接见附件,永久有效。 课程内容: zookeeper简介 zookeeper数据模型 zookeeper单机安装 zookeeper常用shell命令 zookeeper的Acl权限控制 zookeeper...

    基于ZooKeeper的配置信息存储方案的设计与实现

    本文提出了一种基于ZooKeeper 的配置信息存储方案。首先介绍了ZooKeeper 的架构和ZooKeeper 的相关概念,然后分析了当前配置信息存储方案的不足;最后重点介绍 基于ZooKeeper 的配置信息存储方案,包括架构和实现...

    ZooKeeper学习笔记

    java ZooKeeper学习笔记\ZooKeeper原理、运用

    zookeeper+dubbo本地工程demo

    快速搭建的一个本地Dubbo demo,方便学习Dubbo。 注:该资源的使用可以参考文章:http://blog.csdn.net/accp_fangjian/article/details/51658292

    zookeeper 学习资料 中篇

    zookeeper 学习资料 中篇

    zookeeper学习Demo

    zookeeper学习用Demo,包含zookeeper的各种使用案例 zookeeper学习用Demo,包含zookeeper的各种使用案例

    zookeeper学习图谱

    zookeeper学习知识点, 脑图

    Zookeeper中日志文件种类

    日志种类 Zookeeper在运行期间主要输出三类文件:快照(snapshot)、事务日志(transaction log...当事务日志文件变得较大时,Zookeeper会将当前所有znode节点的最新状态生成快照snapshot存储到dataDir中,同时生成新的

    Zookeeper学习笔记.pdf

    ZooKeeper是一种为分布式应用所设计的高可用、高性能且一致的开源协调服务,它提供了一项基本服务:**分布式锁服务**。由于ZooKeeper的开源特性,后来我们的开发者在分布式锁的基础上,摸索了出了其他的使用方法:**...

    zookeeper 自己学习资料

    自己学习zookeeper时的用过学习资料,很不全,但都是这么过来的。

    ELK+Filebeat+Kafka+ZooKeeper构建日志分析平台

    ELK+Filebeat+Kafka+ZooKeeper构建日志分析平台,架构图解

    Zookeeper学习笔记.docx

    Zookeeper学习笔记

    zookeeper学习视频.rar

    zookeeper学习视频

    zookeeper一站式学习资料

    zookeeper一站式学习资料包含国内首部Zookeeper从入门到精通+搜索引擎等一条龙学习资料以及视频讲解包含笔记代码资源

Global site tag (gtag.js) - Google Analytics