最近线上的 clickhouse(下称 CK) 集群,又被小伙伴爆出一个问题,说大屏显示的某几个指标数据量,一会大、一会小。
关键这个一「大」跟一「小」之间的差异,显得非常的诡异,比如其中一张表的实际数据量有 4kw+ 条,但是这个查询结果呢,有时候能显示 4kw+、有时候显示只有 1kw+、而有时候还显示 3kw+。
一开始他们跟我反映时,还想着以「这应该只是偶发情况」给搪塞过去的,但后来发现,同样的问题,已经蔓延到多张表身上。
问题太明显,躲不掉了。
0. 问题分析
首先要声明的是,这种稀奇古怪的情况,只会出现在对「分片表」的查询结果中,而如果查询对象是「本地表」,则不会有这种情况。
为了揪出这个内鬼,我先把所有跟这个表有关的读写都给停了,然后再尝试查,但问题依旧。
仔细观察这个查询数据量后发现,它这个不准(查少了),不准得很有规律,缺少的,都是某个,或者某几个「本地表」的「整个表」数据量。
举个栗子,我当前向这张分片表写入了 3 条数据,而这个分片表对应的后台 CK 实例有 3 个,每个实例对应一张这个分片表的本地表,3 张本地表各自写入 1 条数据。
但是你查询这张分片表总数据量的时候,有时候查的数量是 1,有时候为 2,有时候又为 3。
于是我掐指一分析,这口锅,很可能是配置不合理导致的。
1. 瞅一眼配置文件
想要实现分片表,你得先告诉 CK,这个片,它该怎么分,对于我当前的集群来说,是这么片的。
从这个集群配置可以看出来,我当前 CK 一共有 6 个实例,然后配置每 2 个实例为一组互为备份,共分为 3 组,这样一来,当数据写入到这分好的 3 组里面时,数据在实现了分片的同时,也能实现副本为 2 的冗余备份。
没毛病对不对?
好,再来瞅一眼我当前表的建表语句。
先看分片表的:
再看对应本地表的:
是不是看上去好像也没毛病?
但如果把前面的配置 + 当前这个建表方式给撺掇到一起,就会发生一开头说的事故。
2. 为嘛呢
原因在于,往分片表(*all)写数据的时候,能正常根据集群配置(配置文件上的),把数据按照建表规则(cityHash64),给分别写到对应的 3 组本地表(*local)里。
然鹅,当你去根据分片表查数据的时候,CK 也会根据配置文件里的配置,去对应的集群上找。
但是,因为当前配置文件里配置的是「2 个实例一组」,而这每组里面,它们之间的数据应该是「互为备份」的关系。
但是,又因为当前的建表语句,指定的不是「冗余表」(非 replicated 表引擎),所以当数据写入的时候,根据 CK 的规则,它只会往这一组中,其中的一个实例写数据。
所以当你对这张分片表发起查询时,CK 只会傻傻的根据配置,去选择互为备份的每组中,任意的一个实例,然后发起查询,而如果刚好不幸,它在查询时,选择了每组中,那个没有写入数据的实例,就会导致丢掉了当前分片的数据。
来,画个示意图。
你第 1 次查询,是这样的:
第 2 次查询,是这样的(蒙对了):
第 3 次查询,是这样的:
好了,看完这 3 个图,你要是再不理解,我可就生气了。
3. 咋解决
相信聪明的你看到这,应该早就想到了解决办法。
没错,既然配置文件里配置的集群方式,是互为冗余的模式,辣么我们建表的时候,就应该遵循这个配置意图,也把表也给建成「冗余表」。
而对于分片表来说,这里需要修改的,只需要是每个 CK 实例上的「本地表」,毕竟,分片表本身,只是这些本地表的一个「代理入口」而已。
所以,把之前的本代表,从「非冗余表引擎」,给改为「冗余表引擎」,比如下面这样:
完事之后,记得把之前的表数据给同步过来。
放开程序对该表的写入之后,再次查询,同样的数据体量,连着试查了几十次,数据量再也没出过问题。
两天过去了,也没有因为这个事情,再次受到小伙伴们的骚扰,说明问题确实解决了。
最后
那么问题来了,这个问题算是 CK 的 bug 吗?
像是,但又好像不全是,因为弄清楚原因之后,这个问题又确实可以避免。
那么对于这个查询数据量不准的问题,你怎么看?
- END -
IT168与ITPUB技术社区强强联手,收集数百款主流数据库产品,重磅推出“数据库全景图”,旨在打造一款集知识普及、产品对比、选型参考于一体的综合性资源平台。“数据库全景图(11月版)”可扫描上方左侧二维码回复关键词获取,识别右侧二维码直达“数据库全景图”链接(右上角浏览器打开获取更好体验)。