Clickhouse Alter操作造成zk連接丟失的問題分析

背景

業(yè)務(wù)方數(shù)據(jù)在出現(xiàn)錯(cuò)誤后需要重跑數(shù)據(jù),由于業(yè)務(wù)方?jīng)]有使用MergeTree的折疊表四啰,需要?jiǎng)h除舊的數(shù)據(jù)后,再重新跑數(shù)據(jù)寫入新的正確的數(shù)據(jù)欧瘪。

之前這種模式一直運(yùn)轉(zhuǎn)的比較好匙赞,沒有出現(xiàn)過問題,不過近期發(fā)現(xiàn)涌庭,對(duì)該表發(fā)起Alter語句時(shí),出現(xiàn)了ZK Connection Loss的錯(cuò)誤坐榆,但是對(duì)其他的表發(fā)起Alter語句沒有出現(xiàn)相同的錯(cuò)誤。

本文主要分析一下定位問題的過程以及確定問題所在席镀,也希望大家就該問題進(jìn)行討論提供更好的解決方案。

問題現(xiàn)象分析

問題描述

Clickhouse版本:20.9.3.45
表結(jié)構(gòu):

CREATE TABLE default.business_table
(
    createTime DateTime,
    appid int ,
    totalCount  bigint
)
ENGINE = ReplicatedMergeTree('/clickhouse/tables/{shard}/business_table', '{replica}');

Alter語句以及響應(yīng)的報(bào)錯(cuò)信息:

 alter table default.business_table delete where toYYYYMMDDHH(createTime) =2022012020 and appid=1;

ERROR 999 (00000): Code: 999, e.displayText() = Coordination::Exception: Connection loss (version 20.9.3.45 (official build))

問題定位

首先查看了一下clickhouse的錯(cuò)誤日志顶捷,錯(cuò)誤日志中有相關(guān)的堆棧信息

2022.02.10 11:17:51.706169 [ 34045 ] {} <Error> executeQuery: Code: 999, e.displayText() = Coordination::Exception: Connection loss (version 20.9.3.45 (official build)) (from 12
7.0.0.1:48554) (in query: alter table default.business_table delete where toYYYYMMDDHH(createTime) =2022012020 and appid=1), Stack trace (when copying this message, always include the lines below):

0. Poco::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0x18e1b360 in /usr/bin/clickhouse
1. DB::Exception::Exception(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, int) @ 0xe736dad in /usr/bin/clickhouse
2. Coordination::Exception::Exception(Coordination::Error) @ 0x16887dad in /usr/bin/clickhouse
3. ? @ 0x168991b0 in /usr/bin/clickhouse
4. DB::EphemeralLocksInAllPartitions::EphemeralLocksInAllPartitions(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic
_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&, zkut
il::ZooKeeper&) @ 0x161dca16 in /usr/bin/clickhouse
5. DB::StorageReplicatedMergeTree::EphemeralLocksInAllPartitions(DB::MutationCommands const&, DB::Context const&) @ 0x1609c636 in /usr/bin/clickhouse
6. DB::InterpreterAlterQuery::execute() @ 0x15ab5126 in /usr/bin/clickhouse

再查看了一下zk的錯(cuò)誤日志

2022-02-10 11:17:51,680 [myid:90] - WARN  [NIOWorkerThread-30:NIOServerCnxn@373] - Close of session 0x5a02260902470005
java.io.IOException: Len error 1190892
    at org.apache.zookeeper.server.NIOServerCnxn.readLength(NIOServerCnxn.java:541)
    at org.apache.zookeeper.server.NIOServerCnxn.doIO(NIOServerCnxn.java:332)
    at org.apache.zookeeper.server.NIOServerCnxnFactory$IOWorkRequest.doWork(NIOServerCnxnFactory.java:522)
    at org.apache.zookeeper.server.WorkerService$ScheduledWorkRequest.run(WorkerService.java:154)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    at java.lang.Thread.run(Thread.java:748)

然后大致對(duì)比了一下系統(tǒng)的表的大小服赎,目前出問題的表是最大的交播。

mysql> select count() from system.parts where table='business_table' and active =1 ; 
+---------+
| count() |
+---------+
|    8108 |
+---------+
1 row in set (0.04 sec)

從上面可以看出表的數(shù)據(jù)分片很多。

分析ZK的日志發(fā)現(xiàn),ZK認(rèn)為客戶端發(fā)送的消息格式不正確荔仁,從而主動(dòng)斷開了clickhouse的連接芽死。從clickhouse的異常日志有可以看出正在執(zhí)行zk操作時(shí)出現(xiàn)了連接斷開的錯(cuò)誤次洼。

現(xiàn)在我們從代碼層面去看看問題的根因,當(dāng)clickhouse執(zhí)行alter操作時(shí)卖毁,如果對(duì)應(yīng)的mutation如果涉及到分片數(shù)據(jù)的變更時(shí),就需要對(duì)分片進(jìn)行鎖定炭剪,而分片的鎖定操作是在對(duì)應(yīng)的分片對(duì)應(yīng)的zk子目錄下面創(chuàng)建一個(gè)臨時(shí)節(jié)點(diǎn)翔脱,如下面代碼所示:

EphemeralLocksInAllPartitions::EphemeralLocksInAllPartitions(
    const String & block_numbers_path, const String & path_prefix, const String & temp_path,
    zkutil::ZooKeeper & zookeeper_)
    : zookeeper(&zookeeper_)
{
    std::vector<String> holders;
    while (true)
    {
        ......

        Coordination::Requests lock_ops;
        // 這里沒有
        for (size_t i = 0; i < partitions.size(); ++i)
        {
            String partition_path_prefix = block_numbers_path + "/" + partitions[i] + "/" + path_prefix;
            lock_ops.push_back(zkutil::makeCreateRequest(
                    partition_path_prefix, holders[i], zkutil::CreateMode::EphemeralSequential));
        }
        lock_ops.push_back(zkutil::makeCheckRequest(block_numbers_path, partitions_stat.version));

        Coordination::Responses lock_responses;
        // 問題出在這里
        Coordination::Error rc = zookeeper->tryMulti(lock_ops, lock_responses);
        if (rc == Coordination::Error::ZBADVERSION)
        {
            LOG_TRACE(&Poco::Logger::get("EphemeralLocksInAllPartitions"), "Someone has inserted a block in a new partition while we were creating locks. Retry.");
            continue;
        }
        else if (rc != Coordination::Error::ZOK)
            throw Coordination::Exception(rc);

clickhouse在zk的訪問中,采用了大量批量操作错妖,在上面的分片鎖定操作中疚沐,它針對(duì)所有影響到的分片的鎖定批量一次性提交命令到zk中,而zk的傳輸使用了jute亮蛔,jute缺省最大的包大小為1M,具體細(xì)節(jié)可以參考一下關(guān)于zookeeper寫入數(shù)據(jù)超過1M大小的踩坑記尔邓。

這里clickhouse的問題在于它沒有做分包,而是對(duì)所有影響的分片合并請(qǐng)求后齿尽,批量向zk發(fā)起請(qǐng)求灯节,從而造成了超過zk最大的傳輸包大小,從而造成連接斷開炎疆。

為什么這里需要一次性的批量提交呢?具體的原因有朋友了解的可以分享一下形入,我理解可能clickhouse需要做類似事務(wù)級(jí)別的保證。

問題解決

知道了問題的根因首先考慮到增加zk的jute缺省的最大包大小浓若,zookeeper本身,我們可以在配置上實(shí)現(xiàn)挪钓。但是我們查看了一下clickhouse的zk配置相關(guān)參數(shù),能夠調(diào)整的主要是ip倚评、port和會(huì)話時(shí)長(zhǎng),沒有看到j(luò)ute大小的控制參數(shù)馏予,所以這條路基本上行不通,經(jīng)過只修改zk的參數(shù)重啟后吗蚌,測(cè)試也發(fā)現(xiàn)不能成功。

控制Alter DELETE影響的數(shù)據(jù)范圍敷燎,從原來的Alter語句來看我們已經(jīng)制定了時(shí)間的范圍箩言,但是看起來Clickhouse不會(huì)主動(dòng)根據(jù)條件來做分區(qū)裁剪。查看源碼也發(fā)現(xiàn)沒有這塊邏輯陨收,但是從最新的clickhouse的文檔中,我們可以看到Delete語句支持分區(qū)操作务漩。

ALTER TABLE [db.]table DELETE [IN PARTITION partition_id] WHERE filter_expr

但是這個(gè)語法在20.9.3.45版本中并沒有得到支持,所以最后我們對(duì)clickhouse做了升級(jí)到21.X.X.X翘悉,并讓業(yè)務(wù)方采用DELETE IN PARTITION居触,問題暫時(shí)得到解決。如果讀者有更好的解決方案轮洋,希望留言探討

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市祥楣,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌荣堰,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異斋扰,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)屎鳍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門问裕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人粮宛,你說我怎么就攤上這事∮欠梗” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵词裤,是天一觀的道長(zhǎng)鳖宾。 經(jīng)常有香客問我,道長(zhǎng)鼎文,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任赖瞒,我火速辦了婚禮蚤假,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘磷仰。我一直安慰自己,他們只是感情好伺通,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著罐监,像睡著了一般。 火紅的嫁衣襯著肌膚如雪沟堡。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天航罗,我揣著相機(jī)與錄音屁药,去河邊找鬼。 笑死酿箭,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的蜓耻。 我是一名探鬼主播械巡,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼讥耗!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起蔼卡,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤挣磨,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后茁裙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡掉蔬,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了箭启。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡傅寡,死狀恐怖婿禽,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情扭倾,我是刑警寧澤挽绩,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站模聋,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏链方。R本人自食惡果不足惜灶搜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望割卖。 院中可真熱鬧,春花似錦鹏溯、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至瞬浓,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背磅叛。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國打工弊琴, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人敲董。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像腋寨,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铃剔,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355