zookeeper07-ZooKeeper的文件系统

  • 我们已经讨论了快照、事务日志和存储设备,本节中,我们将会讨论如何在文件系统上实现这些功能。
  • 数据存储有两类:事务日志文件和快照文件。这两类文件均以普通文件的形式保存到本地文件系统中。事务日志是在进行事务处理的时候写入的,因此我们强烈建议将其存储在专用设备上(因为这对于保持良好的吞吐能力和延迟非常重要),不使用专用存储设备保存事务日志文件并不会导致任何正确性问题,但会影响性能。在虚拟化环境中,也许无法获得专用存储设备。对于快照文件并不要求存储于专用存储设备上,因为该文件由后台线程慢慢写入。
  • 快照文件将会被写入DataDir指定的目录中,而事务日志文件将会被写入到DataLogDir指定的目录中。首先,我们看一下事务日志目录中的文件,如果列出该目录的内容,您将看到一个名为version-2的子目录。我们对日志和快照的格式做了一个重大的更改,当我们做了这个更改后,我们会发现按文件版本分离数据会很有用,这样可以更容易地处理版本之间的数据迁移。

1、事务日志

  • 在执行"create /hh"后,让我们看看事务日志的目录,其中只有一个日志文件。
--zkCli.sh
[zk: localhost:2181(CONNECTED) 0] create /hh
Created /hh

--linux文件系统
]# ll /tmp/zookeeper/log/version-2/
-rw-r--r-- 1 root root 67108880 1月  18 10:52 log.100000001
  • 我们可以仔细观察这些文件信息。首先,虽然我们仅仅只创建了一个znode,但事务日志文件却非常大(每个都超过6MB);其次事务日志文件名有一个很大的数字作为后缀。
  • ZooKeeper为事务日志文件预分配大的数据块,来避免每次写入时对元数据管理的开销。如果你对这些文件进行十六进制转储打印,你会看到这些文件中全部以null字符(\0)填充,只有在开头的部分有少量的二进制数据位。服务器运行一段时间后,其中的null字符逐渐被日志数据替换。
  • 日志文件中包含事务标签zxid,但是为了便于恢复和允许快速查找,每个日志文件的后缀是日志文件的第一个zxid,以十六进制表示。通过十六进制表示zxid的一个好处就是可以快速区分zxid中时间戳部分和计数器部分,所以在之前例子中的第一个文件的时间戳为1,而第二个文件的时间戳为2。
  • 不过,我们还想继续看一看文件中保存了什么内容,对于问题诊断也非常有帮助。有时,开发人员宣称ZooKeeper丢失了某些znode,此时只有通过查找事务日志文件才可以知道客户端具体删除过哪些znode。我们可以用下面的命令来查看第事务日志文件:
--在/etc/profile中添加如下内容,并source
export zkDir=/usr/local/apache-zookeeper-3.5.9-bin/
JAVA_OPTS="$JAVA_OPTS -Djava.ext.dirs=$zkDir:$zkDir/lib"

--查看事务日志的命令
]# java $JAVA_OPTS org.apache.zookeeper.server.LogFormatter /tmp/zookeeper/log/version-2/log.100000001

--查看事务日志的输出
ZooKeeper Transactional Log File with dbid 0 txnlog format version 2
1/18/22 10:52:12 AM CST session 0x2000019637d0000 cxid 0x0 zxid 0x100000001 createSession 30000
1/18/22 10:52:23 AM CST session 0x2000019637d0000 cxid 0x1 zxid 0x100000002 create '/hh,,v{s{31,s{'world,'anyone}}},F,1
EOF reached after 2 txns.
  • 事务日志文件中每一行都是一个的事务。因为只有变更操作才会被记录到事务日志中,所以在事务日志中不会看到任何读操作。

2、快照

  • 快照文件的命名规则与事务日志文件的命名规则相似,以下为之前例子中的服务器的快照列表信息:
]# ll /tmp/zookeeper/data/version-2/
-rw-r--r-- 1 root root   1 1月  18 22:16 acceptedEpoch
-rw-r--r-- 1 root root   1 1月  18 22:16 currentEpoch
-rw-r--r-- 1 root root 556 1月  18 22:16 snapshot.0
-rw-r--r-- 1 root root 556 1月  18 22:16 snapshot.100000000
  • 快照文件不是预先分配的,因此大小更准确地反映了它们包含的数据量。所使用的后缀反映快照开始时的zxid。正如我们前面讨论的,快照文件实际上是一个模糊快照;在事务日志重放之前,它本身不是一个有效的快照。具体来说,要还原系统,必须从快照后缀的zxid或更早的地方开始重放事务日志。
  • 快照文件本身也以二进制形式存储模糊快照数据。因此,有另一种工具查看快照文件的内容:
--在/etc/profile中添加如下内容,并source
export zkDir=/usr/local/apache-zookeeper-3.5.9-bin/
JAVA_OPTS="$JAVA_OPTS -Djava.ext.dirs=$zkDir:$zkDir/lib"
 
--查看快照内容的命令
]# java $JAVA_OPTS org.apache.zookeeper.server.SnapshotFormatter /tmp/zookeeper/data/version-2/snapshot.100000000
 
--查看快照内容命令的输出
ZNode Details (count=5):
----
/
  cZxid = 0x00000000000000
  ctime = Thu Jan 01 08:00:00 CST 1970
  mZxid = 0x00000000000000
  mtime = Thu Jan 01 08:00:00 CST 1970
  pZxid = 0x00000000000000
  cversion = 0
  dataVersion = 0
  aclVersion = 0
  ephemeralOwner = 0x00000000000000
  dataLength = 0
----
/zookeeper
  cZxid = 0x00000000000000
  ctime = Thu Jan 01 08:00:00 CST 1970
  mZxid = 0x00000000000000
  mtime = Thu Jan 01 08:00:00 CST 1970
  pZxid = 0x00000000000000
  cversion = 0
  dataVersion = 0
  aclVersion = 0
  ephemeralOwner = 0x00000000000000
  dataLength = 0
----
/zookeeper/config
  cZxid = 0x00000000000000
  ctime = Thu Jan 01 08:00:00 CST 1970
  mZxid = 0x00000000000000
  mtime = Tue Jan 18 22:16:17 CST 2022
  pZxid = 0x00000000000000
  cversion = 0
  dataVersion = -1
  aclVersion = -1
  ephemeralOwner = 0x00000000000000
  dataLength = 132
----
/zookeeper/quota
  cZxid = 0x00000000000000
  ctime = Thu Jan 01 08:00:00 CST 1970
  mZxid = 0x00000000000000
  mtime = Thu Jan 01 08:00:00 CST 1970
  pZxid = 0x00000000000000
  cversion = 0
  dataVersion = 0
  aclVersion = 0
  ephemeralOwner = 0x00000000000000
  dataLength = 0
----
Session Details (sid, timeout, ephemeralCount):
  • 快照只存储了每个znode的元数据。这样,运维人员就可以知道一个znode何时发生了变化,以及哪个znode节点占用了大量内存。不幸的是,快照并没有存储数据和acl。因此,在进行问题诊断时,必须将快照的信息与事务日志文件的信息结合起来分析问题所在。

3、时间戳文件

  • ZooKeeper的持久状态由两个小文件构成,它们是两个时间戳文件,其文件名为acceptedEpoch和currentEpoch。我们之前已经讨论过时间戳的概念,而这两个文件则反映了某个服务器进程已接受的和正在处理的信息。虽然这两个文件并不包含任何应用数据信息,但对于数据一致性却至关重要,所以如果你在备份一个Zookeeper服务器的原始数据文件时,不要忘了这两个文件。

4、使用存储在ZooKeeper中的数据

  • ZooKeeper存储数据有一个优点:不管独立模式还是集群模式的服务器存储数据的方式都一样。我们刚刚提到,为了获得准确的数据视图,需要合并事务日志和快照。你可以将事务日志文件和快照文件拷贝到一个独立服务器下空白的data目录中,然后启动服务,该服务就会真实反映出你所拷贝的那个服务器上的状态信息。这项技术可以使你从生产环境拷贝服务器的状态信息,用于稍后的复查等用途。
  • 同时也意味着,你只需要简单地将这些数据文件进行备份,就可以轻易地完成ZooKeeper服务器的备份,如果你采用这种方式进行备份,还需要注意一些问题。首先,Zookeeper为复制服务,所以系统中存在冗余信息,如进行备份,只需要备份其中一台服务器的数据信息。
  • 当ZooKeeper服务器认可了一个事务,从这时起它就会承诺记录下该事务的状态,你一定要记住这一点,这一点非常重要。因此如果你使用旧的备份文件恢复一个服务器,就会导致服务器违反其承诺。如果你刚刚遭遇了所有服务器的数据丢失的情况,这可能不是什么大问题,但如果你的集群在正常工作中,而你将某个服务器还原为旧的状态,你的行为可能会导致其他服务器也丢失了某些信息。
  • 如果你要对全部或大多数服务器进行数据丢失的恢复操作,最好的办法是使用最新抓取的状态信息(从最新的存活服务器中获取的备份文件),并在启动服务器之前将状态信息拷贝到其他所有服务器上。
上一篇:谈谈Zookeeper的ZAB协议


下一篇:neo4jGuide简单测试