前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >关于zookeeper写入数据超过1M大小的踩坑记

关于zookeeper写入数据超过1M大小的踩坑记

作者头像
我是攻城师
发布2019-09-30 14:06:40
13K1
发布2019-09-30 14:06:40
举报
文章被收录于专栏:我是攻城师我是攻城师

背景

某天晚上集群的一个任务提交一直失败,经过排查日志,发现是zk客户端写入的数据包过大,导致报错。我们来看下,这中间发生了什么。

首先zk的单个znode写入数据大小是受jute.maxbuffer参数影响的,默认是1MB,如果超过了这个数值,就会如下抛出如下的两个异常:

客户端:

代码语言:javascript
复制
java.io.IOException: Unreasonable length = 2054758
        at org.apache.jute.BinaryInputArchive.readBuffer(BinaryInputArchive.java:100)
        at org.apache.zookeeper.server.quorum.QuorumPacket.deserialize(QuorumPacket.java:85)
        at org.apache.jute.BinaryInputArchive.readRecord(BinaryInputArchive.java:108)
        at org.apache.zookeeper.server.quorum.Learner.readPacket(Learner.java:152)
        at org.apache.zookeeper.server.quorum.Follower.followLeader(Follower.java:85)
        at org.apache.zookeeper.server.quorum.QuorumPeer.run(QuorumPeer.java:740)

服务端:

代码语言:javascript
复制
java.io.Exception: Len error  2054758

注:2054758 byte= 2MB

ok,问题很明显,不就改一个参数的事吗?如果你只是简单的这样的认为,那可就大错特错了,这个参数弄不好就会导致整个zookeeper集群挂掉,我们先来看下官网对这个参数的解释:

链接:https://zookeeper.apache.org/doc/r3.3.3/zookeeperAdmin.html

注意这个选项是在高风险参数的类目下:

Unsafe Options (有一定风险的选项) The following options can be useful, but be careful when you use them. (下面的选项可能非常有用,但一定需要谨慎使用他们)

..........省略无关选项..........

jute.maxbuffer:(Java system property: jute.maxbuffer) (需要通过Java的环境变量来设置)

This option can only be set as a Java system property. There is no zookeeper prefix on it. It specifies the maximum size of the data that can be stored in a znode. The default is 0xfffff, or just under 1M. If this option is changed, the system property must be set on all servers and clients otherwise problems will arise. This is really a sanity check. ZooKeeper is designed to store data on the order of kilobytes in size.

简单的翻译一下:

jute.maxbuffer这个选项是需要通过Java系统变量来设置,它指定了在zk里面一个znode节点存储数据大小的限制,默认值是1MB,如果这个参数的值被改变,必须需要在所有的服务端和客户端进行同步设置,否则就会出现问题(注:这是个大问题,有可能会导致zookeeper整个集群挂掉,后面再细说)。此外官网还强调了zk是用来存储kb级别相关的数据,言外之意就是告诉警告用户非特殊情况别乱这个值,如果操作不当,出了问题,会被老板fuck的,切记一般不要用zk来存储大数据包。

ok,到这里基本弄明白了这个参数的意思,也确实与线上发生的问题有着千丝万缕的关系,后面又经过查询,从zk的官网jira列表里面,找到了两个相关的issue,如下:

https://issues.apache.org/jira/browse/ZOOKEEPER-3496

https://issues.apache.org/jira/browse/ZOOKEEPER-2101

基本证实了问题,那么接下来,又需要思考的是,为什么客户端会提交这么大一个包?后经排查确实也是客户端代码存在一定的问题。

问题原因总结:

(1)客户端代码,读取了大量的不同znode的数据,然后使用了事务,将多个znode的数据打包一起发送,体积超过了1MB。

(2)因为没有及时清理,客户端读取的部分数据中充斥着zk历史上残余的垃圾数据

(3)服务端和客户端相关的jute.maxbuffer参数用的都是默认值

解决办法

如何解决,无非就是对症下药:

(1)首先清理zk历史上存在的垃圾数据

(2)优化代码,只同步有效数据和拆分事务

(3)如果1和2都暂时没法完成,那么只能调大jute.maxbuffer参数,来确保一定时间内安全,但非根治之法。

这里我想重点说明下如何修改jute.maxbuffer参数,因为操作方法不当直接会引发集群宕机风险。

首先这个参数的修改,有两种方式:

方式一:在zk的部署机器上,进入zk的conf目录下,新建一个java.env文件,然后写入如下内容:

代码语言:javascript
复制
export JVMFLAGS="-Xms512m -Xmx2048m -Djute.maxbuffer=10485760 " (10MB)

注意jvm堆大小,可以根据情况来控制。

方式二:

修改bin目录下的zkServer.sh文件,在vi中搜索start单词,然后修改如下参数:

代码语言:javascript
复制
nohup "$JAVA" "-Djute.maxbuffer=10485760  -Dzookeeper.log.dir=${ZOO_LOG_DIR}" "-Dzookeeper.root.logger=${ZOO_LOG4J_PROP}"

重启服务

这里要说明的是,为了避免造成大范围影响,我们操作的方式是先滚动重启服务端zk集群,即单台修改完成之后,即可重启,然后使用jps -lvm命令,可以在进程列表中找到我们启动的进程,如果观察环境参数中附带了我们设置的值,即代表修改生效。

然后依次再滚动重启其他的zk机器。这里我再强调一下,启动的顺序一定是按照myid的值,从小到大依次启动,否则有可能导致启动失败。

在所有服务端启动成功后,我们可以根据需要决定是否需要启动客户端,如果你真的决定客户端会写入大于1MB的数据包,那么就要在客户端任务启动的时候,同样加上x相同的环境变量:

代码语言:javascript
复制
java -Djute.maxbuffer=10485760 -jar  com.xxxx.Main

这里面需要注意,是改服务端之后,在改客户端的,这个顺序也一定不要弄反,否则先改了客户端重启之后,会直接导致客户端发送大包到服务端,这里面又由于zk客户端的代码,对写入请求对大小,并不做校验,仅仅对读取请求的校验,所以直接可以写成功,这样如果客户端写了2MB的数据成功的到了zk的leader上,这个follower节点就会去leader上同步读取数据,而这个时候服务端的配置还是默认的1MB,所以做读取校验会失败,最终导致所有的follower同步失败,从而造成状态不一致后引发follwer服务挂掉,此时leader认为follwer丢失之后,本身状态可能也是不正常的,会再次发生选举,但仅仅只能自身没法选举,最终导致整个zk集群挂掉,所有依赖zk做分布式协调的业务都会受到影响。所以这步一定要谨慎操作。

总结

本文主要了记录了一次关于写入zk数据包超过默认大小的问题,由此又详细的分析了这里面非常重要的一些知识和操作步骤,这告诉我们在日常开发或者运维在操作正式环境之前,一定要在测试环境多做测试,然后列出操作步骤,在正式操作时,一定严格按照列好的清单执行,当然这步最好做成流程化的web工具,以最大限度的降低出现问题的可能性。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-09-27,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 我是攻城师 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • 解决办法
  • 重启服务
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档