失眠网,内容丰富有趣,生活中的好帮手!
失眠网 > vc6 往mdb写入信息_HBase运维 | 一张表写入异常引起的HBase Replication 队列堆积

vc6 往mdb写入信息_HBase运维 | 一张表写入异常引起的HBase Replication 队列堆积

时间:2019-07-06 03:07:30

相关推荐

vc6 往mdb写入信息_HBase运维 | 一张表写入异常引起的HBase Replication 队列堆积

线上的接口依赖于HBase主备集群来提供数据读写服务,HBase主备集群之间则通过replication机制来进行数据同步,正常情况下,数据的读写流量都集中于主集群,只有在主集群读写超时或服务不可用时,才会触发熔断机制,读写流量自动切换至备集群。所以,主备集群的replication模式是互为主备。

1.replication不可用

业务方通过phoenix视图查询,反馈备集群的一张表没有数据,这边通过hbase-shell查询后,也发现表是空的,而主集群则是有数据的。检查replication peer以及该表的REPLICATION_SCOPE,都是正常的,手动在主集群的表里put一条数据,等待许久,备集群依然没有数据正常同步过来。同时,我也在备集群的表里同样put了一条数据,稍候片刻,主集群依然没有数据正常同步过去。按照以往的经验,一方集群写入的数据,在很小的延时下就会被同步至关联的集群中。在主集群的hbase-shell下使用命令status 'replicaion'来查看当前集群复制队列的进度状态,果然,复制队列存在延迟,复制队列中堆积了大量未被发送的数据。按照以往的经验,正常情况下复制队列中的SizeOfLogQueue一般为1。查看备集群的复制状态,同样也有延迟。此时,CDH中主备集群的各项指标如:IO、CPU、内存等均是正常的,用arthas分析ReplicationSource的相关线程,也看不出有什么异常。

thread

监控页面中未见异常,唯一有异常的地方是:hbase的WALs目录非常大,数据总量不到20T,WALs目录空间占用就有20T,这个已经是我们这边老生常谈的问题了。

2. 一张表的写入异常导致replication持续报错

标题的结论,是分析了RegionServer的日志后才得出。日志中持续输出如下报错信息:

log-error

根据日志中的异常信息,ReplicationSink端,对表COMPANY_INFO:INDUSTRY_FINANCIAL_ANALYSIS写入数据的时候,遇到了类似Region too busy。Store或StoreFile too busy之类的异常,然后导致ReplicationSource端不停地重试发送数据包。RegionServer一般出现这种异常,十有八九是因为写入的数据量过大,而表的预分区做的不够好。但是,这张表创建的时候已经做了预分区,依然导致了这样的异常。回顾这张表的数据写入方式,导入历史数据的时候,先走的离线导入方式,由spark生成hfile,最后用bulkload。只是这张表的数据量太大,spark任务出现了数据倾斜,就改为nifi来推,数据由主集群写入,再通过replication机制同步到备集群,只是在推数据的过程中,nifi报错了,但前一部分的数据已经堆积在了复制队列中,等待着后续被发送至备集群。然后,所有这些未发送的复制队列中的数据,就成了此次异常的导火索。之后,队列中的数据继续发送至备集群,而备集群的表无法承受这样的写入,导致了region too busy的异常,主集群捕获到RemoteException,依旧会不停地尝试,不停地尝试,直至要写入成功。这样的僵局就造成了主备集群之间的复制队列越积越多。但是主集群的WALs数据目录异常膨胀,不确定是否和复制队列堆积有关。按理说,复制队列堆积只会跟OldWals目录有关,WALs目录中的数据落盘后会被回收线程定时移动到OldWAls目录中,隔一定时间后会被彻底删除。但是,如果集群开启了replication,过期的预写日志只有在主集群确定发送至备集群后,才会被标记为弃用,否则,就会堆积在OldWals目录中。

3. 破局

主备集群数据复制队列堆积,replication不可用,如果直接清空zookeeper上的replication相关的znode path,势必会造成备集群数据丢失,主备数据不一致。解决问题的过程中,也曾尝试删除或禁用写入异常的表,但是没有用,RegionServer的报错依旧持续发生,复制队列依旧越积越多。我认为最理想的解决方案是,针对该张表堆积在复制通道的待发送数据包,第一,删除zookeeper中replication的状态(类似于标记为偏移量等),让主备同步机制主动跳过这部分异常的待发送数据。这样,数据丢失也仅是针对这张表。但是,并没有找到这样的解决方案,或者是目前的HBase不支持这样的功能?HBase数据写入时,正常流程是先写预写日志,对于所有表的数据写入或删除操作,都可以视为一个行为,这些只是不停追加至WALs的文件中,所有表的写入行为都是往一个或多个WALs中追加,而不是我理解的每张表独占一个WALs文件。所以,zookeeper中维护的replication的进度状态,无法区分某张表数据写入的复制状态,所以,就无法针对性地选择跳过哪些表的复制。在没有找到很完美的解决方案之前,我们只能尝试先重启主集群,虽然主集群的WALs目录很大,但主集群重启的过程还算顺利,主集群重启后,WALs目录慢慢减小,直至为0,可以理解,集群重启的过程中,缓存中的数据会全部刷新至磁盘中,所有的预写日志都会被移动至OLdWAls目录之下,事实也的确如此,OLdWAls变为20多T,等待一段时间之后,该目录持续变小,直至减为3T后便不再减少。RegionServer中上述那张表replication相关的报错依旧在持续,主备集群之间的复制队列依旧在堆积,replication依旧不可用。现在可以确定,OLdWAls目录之中那3T的数据,就是复制队列中堆积的未发送至备集群的数据。如果贸然清空复制队列,至少有3T的数据是无法被同步至备集群的。此时,我们陷入了进退维谷的境地,没有别的办法,只能通过重建replication的peer,来消除zookeeper中的复制状态,直接跳过这些堆积的预写日志,然后把主集群的表重新克隆至备集群中,把丢数据的风险降到最低。选择重建peer后,OLdWAls的目录大小减至为0,查看复制队列状态,延迟消失,replication恢复正常,RegionServer日志中的报错消失,剩下的工作就是手动进行数据同步了。

4. 总结

我们集群参与replication的表有一百多张,所有表的复制,走的是同一个复制链路(peer),一旦某张表的数据同步发生异常,将会导致整个复制链路拥堵,造成replication不可用。那么,如果我为每张表都单独创建一个复制链路,就算一个链路存在问题,其余链路依旧会正常运转。之前尝试过这种方式,但又会引起别的问题,比如,短连接过多,zookeeper连接占用过多等问题。replication在zookeeper中的复制状态,或者说偏移量之类的,是否可以更改?是否可以针对性地跳过一个或若干个待同步的数据包?或者在zookeeper维护复制队列状态的znode path中,手动删除正在卡住的znode path?此外,在Replication没有延迟,一切正常的情况下,WALs目录的空间占用依旧会持续膨胀,这个异常点貌似与Replication的关系也不大。学海无涯,在此以作记录,后续继续探索。

5. 参考链接

/2.1/book.html

据说,关注我的人都找到了对象?

如果觉得《vc6 往mdb写入信息_HBase运维 | 一张表写入异常引起的HBase Replication 队列堆积》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。