进阶分布式系统架构系列(十七):Zookeeper 运维实践经验总结

点击下方名片,设为星标

回复“1024”获取2TB学习资源!

前面介绍了 Zookeeper 数据与存储会话与事务管理分布式锁客户端可视化工具实战项目等相关的知识点,今天我将详细的为大家介绍 zookeeper 运维实践经验总结相关知识,希望大家能够从中收获多多!如有帮助,请点在看、转发支持一波!!!

Zookeeper是一个高可用的分布式数据管理与协调框架,该框架能很好地保证分布式环境中数据一致性。一般用来实现服务发现(类似DNS),配置管理,分布式锁,leader选举等。

生产环境中Zookeeper安装部署规范

生产环境建议zookeeper至少为三台集群,统一安装配置,版本号为近期新版本。

  • 部署路径:/opt/业务模块名/zookeeper

  • 配置文件:/opt/业务模块名/zookeeper/conf/zoo.cfg

  • 存储快照文件snapshot的目录:/opt/业务模块名/zookeeper/data

  • 事务日志输出目录:/var/log/业务模块名/zookeeper

  • 运行日志输出目录:/var/log/业务模块名/zookeeper

  • Zookeeper所有端口需要提前开通防火墙入站规则

  • 对外服务端口:默认2181,可自定义

  • 通信端口:2888,可自定义

  • 选举端口:3888,可自定义

autoperge默认关闭,建议自行编写脚本在业务低谷期清理快照和事务日志

  • 查询状态:sh /opt/业务模块名/zookeeper/zkServer.sh status

  • 启动服务:sh /opt/业务模块名/zookeeper/zkServer.sh start

  • 停止服务:sh /opt/业务模块名/zookeeper/zkServer.sh stop

配置文件conf/zoo.cfg示例如下:
# The number of milliseconds of each tick  
ickTime=2000  
# The number of ticks that the initial  
# synchronization phase can take  
nitLimit=10  
# The number of ticks that can pass between  
# sending a request and getting an acknowledgement  
yncLimit=5  
# the directory where the snapshot is stored.  
# do not use /tmp for storage, /tmp here is just  
# example sakes.  
ataDir=/opt/kevintest/zookeeper\_22181/data  
# the port at which the clients will connect  
lientPort=22181  
# the maximum number of client connections.  
# increase this if you need to handle more clients  
maxClientCnxns=60  
  
# Be sure to read the maintenance section of the  
# administrator guide before turning on autopurge.  
  
# http://zookeeper.apache.org/doc/current/zookeeperAdmin.html#sc_maintenance  
  
# The number of snapshots to retain in dataDir  
autopurge.snapRetainCount=3  
# Purge task interval in hours  
# Set to "0" to disable auto purge feature  
#autopurge.purgeInterval=1  
dataLogDir=/var/log/kevintest/zookeeper_22181  
server.1=192.168.10.91:22888:23888  
server.2=192.168.10.91:22988:23988  
server.3=192.168.10.92:22888:23888
conf/log4j.properties配置示例如下:
# Define some default values that can be overridden by system properties
zookeeper.root.logger=INFO,ROLLINGFILE
zookeeper.console.threshold=INFO
zookeeper.log.dir=.
zookeeper.log.file=zookeeper.log
zookeeper.log.threshold=DEBUG
zookeeper.tracelog.dir=.
zookeeper.tracelog.file=zookeeper_trace.log

#
# ZooKeeper Logging Configuration
#

# Format is "<default threshold> (, <appender>)+

# DEFAULT: console appender only
log4j.rootLogger=${zookeeper.root.logger}

# Example with rolling log file
#log4j.rootLogger=DEBUG, CONSOLE, ROLLINGFILE

# Example with rolling log file and tracing
#log4j.rootLogger=TRACE, CONSOLE, ROLLINGFILE, TRACEFILE

#
# Log INFO level and above messages to the console
#
log4j.appender.CONSOLE=org.apache.log4j.ConsoleAppender
log4j.appender.CONSOLE.Threshold=${zookeeper.console.threshold}
log4j.appender.CONSOLE.layout=org.apache.log4j.PatternLayout
log4j.appender.CONSOLE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n

#
# Add ROLLINGFILE to rootLogger to get log file output
#    Log DEBUG level and above messages to a log file
log4j.appender.ROLLINGFILE=org.apache.log4j.DailyRollingFileAppender
log4j.appender.ROLLINGFILE.Threshold=${zookeeper.log.threshold}
log4j.appender.ROLLINGFILE.File=${zookeeper.log.dir}/${zookeeper.log.file}

# Max log file size of 10MB
#log4j.appender.ROLLINGFILE.MaxFileSize=10MB
# uncomment the next line to limit number of backup files
log4j.appender.ROLLINGFILE.MaxBackupIndex=10

log4j.appender.ROLLINGFILE.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLINGFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L] - %m%n


#
# Add TRACEFILE to rootLogger to get log file output
#    Log DEBUG level and above messages to a log file
log4j.appender.TRACEFILE=org.apache.log4j.FileAppender
log4j.appender.TRACEFILE.Threshold=TRACE
log4j.appender.TRACEFILE.File=${zookeeper.tracelog.dir}/${zookeeper.tracelog.file}

log4j.appender.TRACEFILE.layout=org.apache.log4j.PatternLayout
### Notice we are including log4j's NDC here (%x)
log4j.appender.TRACEFILE.layout.ConversionPattern=%d{ISO8601} [myid:%X{myid}] - %-5p [%t:%C{1}@%L][%x] - %m%n
conf/zookeeper-env.sh文件配置示例如下:
ZOO_LOG_DIR="/var/log/kevintest/zookeeper_22181/"  
ZOO_LOG4J_PROP="INFO,ROLLINGFILE

Zookeeper最佳实践

必须了解以下ZK知识点,才能熟练地对ZK进行维护:

  • zookeeper集群里分三种角色: Leader, Follower和Observer。Leader和Follower参与投票,Observer只会『听』投票的结果,不参与投票。

  • 投票集群里的节点数要求是奇数

  • 一个集群容忍挂掉的节点数的等式为 N = 2F + 1,N为投票集群节点数,F为能同时容忍失败节点数。比如一个三节点集群,可以挂掉一个节点,5节点集群可以挂掉两个...

  • 一个写操作需要半数以上的节点ack,所以集群节点数越多,整个集群可以抗挂点的节点数越多(越可靠),但是吞吐量越差。

  • Zookeeper里所有节点以及节点的数据都会放在内存里,形成一棵树的数据结构。并且定时的dump snapshot到磁盘。

  • Zookeeper的Client与Zookeeper之间维持的是长连接,并且保持心跳,Client会与Zookeeper之间协商出一个Session超时时间出来(其实就是Zookeeper Server里配置了最小值,最大值,如果client的值在这两个值之间则采用client的,小于最小值就是最小值,大于最大值就用最大值),如果在Session超时时间内没有收到心跳,则该Session过期。

  • Client可以watch Zookeeper那个树形数据结构里的某个节点或数据,当有变化的时候会得到通知。

最小生产集群

要确保Zookeeper能够稳定运行,那么就需要确保投票能够正常进行,最好不要挂一个节点整个就不work了,所以我们一般要求生产环境最少3个节点部署。

网络

除了节点外,还要看不能一台物理机器,一个机柜或一个交换机挂掉然后影响了整个集群,所以节点网络结构也要考虑,这个可能就比很多应用服务器的要求更加严格。

分Group,保护核心Group

要确保Zookeeper整个集群可靠运行,就是要确保投票集群可靠。那在我们这里,将一个Zookeeper集群划分为多个小的Group,我们称Leader+Follower为核心Group,核心Group我们一般是不向外提供服务的,然后我们会根据不同的业务再加一些Observer,比如一个Zookeeper集群为服务发现,消息,定时任务三个不同的组件提供服务,那么我们为建立三个Observer Group,分别给这三个组件使用,而Client只会连接分配给它的Observer Group,不去连接核心Group。这样核心Group就不会给Client提供长连接服务,也不负责长连接的心跳,这大大的减轻了核心Group的压力,因为在实际环境中,一个Zookeeper集群要为上万台机器提供服务,维持长连接和心跳还是要消耗一定的资源的。因为Observer是不参与投票的所以加Observer并不会降低整体的吞吐量,而且Observer挂掉不会影响整个集群的健康。

但是这里要注意的是,分Observer Group只能解决部分问题,因为毕竟所有的写入还是要交给核心Group来处理的,所以对于写入量特别大的应用来说,还是需要进行集群上的隔离,比如Storm和Kafka就对Zookeeper压力比较大,你就不能将其与服务发现的集群放在一起。

内存

因为Zookeeper将所有数据都放在内存里,所以对JVM以及机器的内存也要预先计划,如果出现Swap那将严重的影响Zookeeper集群的性能,所以我一般不怎么推荐将Zookeeper用作通用的配置管理服务。因为一般配置数据还是挺大的,这些全部放在内存里不太可控。

日志清理

因为Zookeeper要频繁的写txlog (Zookeeper写的一种顺序日志) 以及定期dump内存snapshot到磁盘,这样磁盘占用就越来越大,所以Zookeeper提供了清理这些文件的机制,但是这种机制并不太合理,它只能设置间隔多久清理,而不能设置具体的时间段。那么就有可能碰到高峰期间清理,所以建议将其关闭:autopurge.purgeInterval=0。然后使用crontab等机制,在业务低谷的时候清理。

日志,jvm配置

从官网直接下载的包如果直接启动运行是很糟糕的,这个包默认的配置日志是不会轮转的,而且是直接输出到终端。我们最开始并不了解这点,然后运行一段时间后发现生成一个庞大的zookeeper.out的日志文件。除此之外,这个默认配置还没有设置任何jvm相关的参数(所以堆大小是个默认值),这也是不可取的。那么有的同学说那我去修改Zookeeper的启动脚本吧。最好不要这样做,Zookeeper会加载conf文件夹下一个名为zookeeper-env.sh的脚本,所以你可以将一些定制化的配置写在这里,而不是直接去修改Zookeeper自带的脚本。

#!/usr/bin/env bash
ZOO_LOG_DIR=/var/log/kevintest/zookeeper_22181/       #日志文件放置的路径
ZOO_LOG4J_PROP="INFO,ROLLINGFILE"                     #设置日志轮转

新版本的zk中是用java.env这个参数文件来配置的

if [ -f "$ZOOCFGDIR/java.env" ]
then
    . "$ZOOCFGDIR/java.env"
fi

其中$ZOOCFGDIR/java.env就是设置jvm内存大小的文件,这个文件默认情况下是没有的,需要手动创建.

vim /usr/local/services/zookeeper-3.4.8/conf/java.env

#!/bin/sh  
export JAVA_HOME=/usr/java/jdk  
# heap size MUST be modified according to cluster environment  
export JVMFLAGS="-Xms4096m -Xmx4096m $JVMFLAGS"
地址

在实际环境中,我们可能因为各种原因比如机器过保,硬件故障等需要迁移Zookeeper集群,所以Zookeeper的地址是一个很头痛的事情。这个地址有两方面,第一个是提供给Client的地址,建议这个地址通过配置的方式下发,不要让使用方直接使用,这一点我们前期做的不好。另外一个是集群配置里,集群之间需要通讯,也需要地址。我们的处理方式是设置hosts:

192.168.1.20 zk1  
192.168.1.21 zk2  
192.168.1.22 zk3

在zoo.cfg配置里:

server.1=zk1:2081:3801  
server.2=zk2:2801:3801  
server.3=zk3:2801:3801

这样在需要迁移的时候,我们停老的节点,起新的节点只需要修改hosts映射就可以了。比如现在server.3需要迁移,那我们在hosts里将zk3映射到新的ip地址。但是对于java有一个问题是,java默认会永久缓存DNS cache,即使你将zk3映射到别的ip,如果并不重启server.1, server.2,它是不会解析到新的ip的,这个需要修改$JAVA_HOME/jre/lib/security/java.security文件里的networkaddress.cache.ttl=60,将其修改为一个比较小的数。对于这个迁移的问题,我们还遇到一个比较尴尬的情况,在最后的坑里会有提及。

日志位置

Zookeeper主要产生三种IO: txlog(每个写操作,包括新Session都会记录一条log),Snapshot以及运行的应用日志。一般建议将这三个IO分散到三个不同的盘上。不过我们倒是一直没有这么实验过,我们的Zookeeper也是运行在虚拟机(一般认为虚拟机IO较差)上。

监控

我们对Zookeeper做了这样一些监控:

a)是否可写。就是一个定时任务定时的去创建节点,删节点等操作。这里要注意的是Zookeeper是一个集群,我们监控的时候我还是希望对单个节点做监控,所以这些操作的时候不要连接整个集群,而是直接去连接单个节点。

b)监控watcher数和连接数 特别是这两个数据有较大波动的时候,可以发现使用方是否有误用的情况

c)网络流量以及client ip 这个会记录到监控系统里,这样很快能发现『害群之马』

一些使用建议

a)不要强依赖Zookeeper,也就是Zookeeper出现问题业务已然可以正常运行。Zookeeper是一个分布式的协调框架,主要做的事情就是分布式环境的一致性。这是一个非常苛刻的事情,所以它的稳定性受很多方面的影响。比如我们常常使用Zookeeper做服务发现,那么服务发现其实是不需要严格的一致性的,我们可以缓存server list,当Zookeeper出现问题的时候已然可以正常工作,在这方面etcd要做的更好一些,Zookeeper如果出现分区,少数派是不能提供任何服务的,读都不可以,而etcd的少数派仍然可以提供读服务,这在服务发现的时候还是不错的。

b)不要将很多东西塞到Zookeeper里,这个上面已经提到过。

c)不要使用Zookeeper做细粒度锁,比如很多业务在订单这个粒度上使用Zookeeper做分布式锁,这会频繁的和Zookeeper交互,对Zookeeper压力较大,而且一旦出现问题影响面广。但是可以使用粗粒度的锁(其实leader选举也是一种锁)。

d)不建议做通用配置的第二个理由是,通用配置要提供给特别多特别多系统使用,而且一些公共配置甚至所有系统都会使用,一旦这样的配置发生变更,Zookeeper会广播给所有的watcher,然后所有Client都来拉取,瞬间造成非常大的网络流量,引起所谓的『惊群』。而自己实现通用配置系统的时候,一般会对这种配置采取排队或分批通知的方式。

Zookeeper 运维管理

对于长期运行的ZooKeeper ensemble来说, 运维工作是必须做的, 运维人员需要注意以下几点:

清理磁盘文件

ZooKeeper中有两处使用到了磁盘:事务日志与内存数据库快照.。ZooKeeper名称空间里的节点发生变更的时候, 就会有内容写入事务日志. 通常情况下, 当单个事务日志文件变的越来越大的时候, 事务日志就需要创建一个新的文件. 但在创建新的事务日志文件之前, ZooKeeper会先把当前的内存数据库的状态写入磁盘先做快照, 然后再生成一个新的事务日志文件. 这样就保证了快照文件和事务日志文件是一一对应的. 但快照落地需要时间, 在快照落地期间如果还有事务来临, 那么这部分事务的日志依然会写向旧的事务日志文件里. 这就导致, 快照文件对应的那个事务日志文件里, 存储的事务日志可能要比当前快照文件要新.

ZooKeeper server进程在默认启动的情况下, 是不会自动删除事务日志文件和快照文件的,当然这是可配置的, 配置项分别是 autopurge.snapRetainCount 和 autopurge.purgeInterval. 这两个配置项的具体含义在有详细描述. 但需要注意:如果你要这样做, 那么最好为每台部署的机器提供不同的配置值, 除非这些机器的规格是完全一摸一样的!

除过在配置文件中设定, 还有一种方法就是调用一个ZooKeeper提供的小工具, 大致如下:

java -cp zookeeper.jar:lib/log4j-1.2.15.jar:conf org.apache.zookeeper.server.PurgeTxnLog <dataDir> <snapDir> -n <count>

其中<dataDir>是事务日志的保存目录,<snapDir>是快照文件的保存目录,<count>是要保留的个数. 建议大于3.。运行该命令后, 除了最近的<count>对事务日志文件与快照文件, 其它文件都将被删除. 这是一个一次性命令. 如果你想定期清理, 那么只能自己写个脚本咯。

注意以下几点

-  永远不建议手动删除事务日志文件与快照文件;-  通过配置项使ZooKeeper server自动删除, 只有在ZooKeeper版本大于3.4后才可用;-  PrugeTxnLog工具是一个一次性工具, 如果需要定期清理, 你需要自己写一个脚本;-  当机器规格不同的时候, 建议按照不同规格定制不同的清楚阈值;

清理运行日志

ZooKeeper 用 log4j 来输出运行日志。如果要更改运行日志的相关配置,你需要独立为log4j提供配置文件。建议使用log4j提供的滚动日志特性,这样就免去了清理运行日志的问题。

监控ZooKeeper server进程的死活

ZooKeeper的server进程在错误发生的时候会立即自杀,ZooKeeper的设计哲学是这样的:-  单个实例挂掉, 或少量实例挂掉不影响整体服务 -  当单个实例遇到错误的时候, 实例会立即挂掉 -  实例被重启后会自动加入ensemble -  但实例不会自动重启

所以搞一个监控进程, 在实例进程挂掉之后将其立即拉起是一个很好的做法. 比如daemontools或SMF.

监控ZooKeeper server服务的状态

要监控ZooKeeper服务的状态, 有两个选择:-  用4字命令去检查。这个在上面的 ZooKeeper4字命令中有详情 -  JMX。

运行日志

ZooKeeper使用log4j 1.2来输出运行日志,默认的配置文件在zookeeper/conf/log4j.properties中。log4j的配置文件要求要么放在工作目录里, 要么放在类路径里。

问题定位
由于文件损坏导致实例不能启动

ZooKeeper的server进程在事务日志文件被损坏的情况下是起不来的。这时运行日志会说在载入ZooKeeper database时出现IOException。这种情况下,你需要做的是:-  通过四字命令stat检查ensemble中的其它实例是否正常工作 -  如果其它实例正常, 那么把当前实例dataDir目录下的version-2子目录中的所有文件删除, 再把dataLogDir下的version-2子目录下的所有文件删除, 然后重启就可以了。

这种情况是当前实例的事务文件损坏, 不能重建内存数据库, 删除掉事务日志和数据库快照后, 当前的实例在重启后会通过其它实例拉取内在数据库, 重建事务日志和快照文件.

配置参数

ZooKeeper的行为受配置文件影响. 所有同一个ensemble中的实例建议使用完全相同的配置文件. 但使用完全相同的配置文件有一个前提条件: 就是所有实例所属的机器上的磁盘布局是相同的. 磁盘布局不同意味着不同的机器下的实例在配置dataDir和dataLogDir的时候配置值可能有差异, 但除此之外, 一个ensemble中的所有实例的配置文件必须保证server.x=xxxx这些配置值是完全一致的。

最小配置

下面列出来的是要让ensemble正常工作, 每个实例都需要配置的配置项。配置项含义:48f59fd0954c90a599b70fe87757025f.png

高级可选配置

下面列出来的是一此可选配置, 属于高级选项. 你可以用这些配置项进一步个性化ZooKeeper server的行为. 其中一些配置项的值可以通过在启动server进程的时候写入Java 系统属性来设置。配置项对应的Java系统属性名含义:3117979d9d629c1650eedfca7da99f9e.png

多实例模式下的配置项

下面列出来的配置项是多实例模式下的一些配置项. 有一些配置项可以通过在启动server进程的时候写入Java系统属性来设置。配置项对应的Java系统属性名含义。c3fa7092373313d4c746d8d747d77b69.png

身份认证与授权相关的配置项

为了避免看不懂下面的配置项都在干嘛,先大致说一下Zookeeper里的认证与授权。在ZooKeeper server端, 每个znode存储两部分内容: 数据和状态. 状态中包含ACL信息. 创建一个znode会产生一个ACL表, 每个ACL记录有以下内容:

**验证模式(scheme)

-  具体内容(id). 比如当scheme=="digest"的时候, id为是用户名和密码, 比如"root:J0sTy9BCUKubtK1y8pkbL7qoxSw=" -  这个ACL拥有的权限

ZooKeeper提供了如下几种验证模式(scheme)

digest #就是用户名+密码.
auth   #不使用任何id, 表示任何已确认用户
ip.    #用client连接至server时使用的IP地址进行验证
world  #固定ID为"anyone", 为所有client端开放权限
super  #在这种scheme下, 对应的id拥有超级权限.

需要注意:exists操作的getAcl操作不受ACL控制, 任何client都可以执行这两个操作.

znode的权限主要有以下几种: -  create -  read -  write -  delete -  admin     允许对本节点执行setAcl操作

实验性的配置项

配置项对应的Java系统属性名含义ed5f383641b7dbe9d4ecf7fcdb844421.png

不安全的配置项

配置项对应的Java系统属性名含义bf38b5003db2015571029ebe82a75422.png

使用Netty框架进行通信

这是3.4版本后的一个特性。Netty是一个基于NIO的客户端-服务器通信框架, 这个框架简化了Java在网络通信层上的很多繁操作, 并且内置支持SSL和认证授权, 当然SSL和认证授权是额外的可选功能.

3.4版本之前,ZooKeeper是直接用NIO的,在3.4之后,NIO只是一个可选项,但依然是默认选项,如果要使用Netty的话,需要把zookeeper.serverCnxnFactory替换为org.apache.zookeeper.server.NettyServerCnxnFactory。可以只在client上用Netty,也可在server上用Netty,但通常情况下,建议要改一起改。蛋疼的是相关的文档官方还没有写!

四字命令

ZooKeeper支持一系列的四字命令, 你可以在client上通过telnte或nc直接向server发送这些四字命令.使用一个四字命令如下所示, 下面使用echo和nc将四字命令ruok发送给本机的server:

echo ruok | nc 127.0.0.1 2182

下表是所有支持的四字命令, 注意有些命令仅在特定版本之后才受支持。命令含义:16fcafaead06ca974986039e4fe75ba1.png

这里需要注意:

mntr命令的输出大致长下面这样. 输出格式符合java属性格式, 如果你要写个脚本定时发送这个命令以监控ensemble的运行状态, 注意输出的字段的数量可能会有变化, 写脚本的时候注意这一点。另外有一些字段是与操作系统平台相关的,  输出每一行的格式是key \t value, 下面是一个示例:

# echo mntr | nc localhost 2185

zk_version  3.4.0
zk_avg_latency  0
zk_max_latency  0
zk_min_latency  0
zk_packets_received 70
zk_packets_sent 69
zk_outstanding_requests 0
zk_server_state leader
zk_znode_count   4
zk_watch_count  0
zk_ephemerals_count 0
zk_approximate_data_size    27
zk_followers    4                   - only exposed by the Leader
zk_synced_followers 4               - only exposed by the Leader
zk_pending_syncs    0               - only exposed by the Leader
zk_open_file_descriptor_count 23    - only available on Unix platforms
zk_max_file_descriptor_count 1024   - only available on Unix platforms
数据文件管理

将事务日志文件和快照文件存储在不同的物理磁盘上, 可以提升系统性能。

快照存储目录

配置项dataDir指向的目录路径中主要存储两种文件: -  myid: 这个文件里写着当前server实例的编号 -  snapshot.<zxid>: 这里存储着内存数据库的快照

server实例的编号用在两个场合:myid文件里, 以及配置文件里的server.X配置项中。当前server实例在启动的时候, 先去配置文件里看dataDir的值, 然后去找dataDir/myid这个文件, 查看文件内容, 得知自己的编号, 然后在配置文件里再找对应的server.x查看要开的端口号。

快照文件的后缀, <zxid>, 是一个事务ID. 这是在落地内存数据库这个过程开始时, 成功执行的最后一个事务的ID号, 但蛋疼的是, 在落地快照的过程中, server还在接受请求, 执行事务, 也就是在落地的过程中, 内存数据库中的数据还处于一个变动的过程中, 这就导致落地后的快照文件像是一个扭曲的文件. 像是你在用手机拍摄全景照片的过程中, 有一只猫随着你的镜头走, 然后最终拍摄出来的照片里有一只长度为17米的猫. 最终落地生成的快照文件里的数据状态可能和任何一个时刻内存数据库的状态都对不上, 就是因为这个原因. 但ZooKeeper依然可以用这种扭曲的快照文件重建内存数据库, 这是因为ZooKeeper中的update操作是幂等的, 这就保证了在扭曲的快照文件之上重放事务日志里的日志, 就可以将进程的内存状态恢复到日志结束时的那个时刻。

事务日志目录

在有update请求的时候, server的默认行为是先写事务日志, 再执行update操作. 单个事务日志里存储的事务个数超过一个阈值的时候, 就会导致事务日志新开一个文件, 同时会导致内在数据库落地快照, 这个阈值在上面的配置项中有提. 日志文件的后缀是日志文件里第一个日志的ID

文件管理

快照文件的格式和事务日志文件的格式是死的,这就允许你从现网的server机器上将事务日志和内存快照拷贝至你的开发机,在你的开发环境重现现网的情景, 从而进行一些调试或问题定位操作。

使用旧的事务日志文件和快照文件还能重建过去某个指定时刻server的状态, LogFormatter类可以用来访问事务日志文件, 以获取可读的信息. 当然使用的时候需要有管理员权限, 因为数据是加密的。

server进程本来是没有删除事务日志和快照文件的能力的, 但这在3.4版本中也随着新的配置项autopurge.snapRetainCount和autopurge.purgeInterval添加上了。

要避免的事情

下面是几个你应当在部署运维的时候极力避免的事情:

  • ensemble中各个server使用的配置文件中,server.X配置表不一致. 所有的配置文件中, 都要以server.X配置项的形式列出当前ensemble中的所有server, 包括自己. 如果这个东西不一致, 会炸。- 事务日志目录设置不合理。将事务日志目录指向一个IO繁忙的磁盘, 会导致server始终处于一个半死不活的状态;- 不正确的java heap size。频繁的swap操作会严重拖慢性能. 保守起见, 如果你的机器有4G内存, 把java heap size设置为3G就好了;- 部署的时候不考虑安全性。建议在生产环境中合理配置防火墙;

Zookeeper常见问题汇总

1)zookeeper client 3.4.5 ping时间间隔算法有问题,在遇到网络抖动等原因导致一次ping失败后会断开连接。3.4.6解决了这个问题 Bug1751。

2)zookeeper client如果因为网络抖动断开了连接,如果后来又重连上了,zookeeper client会自动的将之前订阅的watcher等又全部订阅一遍,而Zookeeper默认对单个数据包的大小有个1M的限制,这往往就会超限,最后导致一直不断地的重试。这个问题在较新的版本得到了修复。Bug706。

3)抛出UnresolvedAddressException异常导致Zookeeper选举线程退出,整个集群无法再选举,处于崩溃的边缘。这个问题是,某次OPS迁移机器,将老的机器回收了,所以老的机器的IP和机器名不复存在,最后抛出UnresolvedAddressException这个异常,而Zookeeper的选举线程(QuorumCnxManager类里的Listener)只捕获了IOException,导致该线程退出,该线程一旦退出只要现在的leader出现问题,需要重新选举,则不会选出新的leader来,整个集群就会崩溃。Bug2319。

4)由于文件损坏导致实例不能启动。

ZooKeeper的server进程在事务日志文件被损坏的情况下是起不来的. 这时运行日志会说在载入ZooKeeper database时出现IOException. 这种情况下, 你需要做的是:

  • 通过四字命令stat检查ensemble中的其它实例是否正常工作 - 如果其它实例正常, 那么把当前实例dataDir目录下的version-2子目录中的所有文件删除, 再把dataLogDir下的version-2子目录下的所有文件删除, 然后重启就可以了.

这种情况是当前实例的事务文件损坏, 不能重建内存数据库, 删除掉事务日志和数据库快照后, 当前的实例在重启后会通过其它实例拉取内在数据库, 重建事务日志和快照文件。

来源:https://blog.51cto.com/u_6215974/4938598

读者专属技术群

构建高质量的技术交流社群,欢迎从事后端开发、运维技术进群(备注岗位,已在技术交流群的请勿重复添加)。主要以技术交流、内推、行业探讨为主,请文明发言。广告人士勿入,切勿轻信私聊,防止被骗。

扫码加我好友,拉你进群

101c1d6054329f3c5ecf0f2a5f4b977d.jpeg

推荐阅读 点击标题可跳转

号称 “真正自主研发”!中国首款自研 IDE 正式亮相

不会用这个工具,你的 Linux 服务器就是个摆设!

互联网大事件!宇宙第一 IDE 放弃了 Mac

打脸了!微软竟然发布了自己的 Linux

IPv4 开始收费!或将是一场新的 IT 灾难

第一大服务器厂商:收入骤降 100 亿

发现一款吊炸天的远程控制与监控工具,有点牛逼

06563b4dcdac6ac56d1db1e8df3eb1ab.png

PS:因为公众号平台更改了推送规则,如果不想错过内容,记得读完点一下在看,加个星标,这样每次新文章推送才会第一时间出现在你的订阅列表里。点在看支持我们吧!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值