1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        ClickHouse 實踐 | ClickHouse 使用實踐與規(guī)范

        共 12385字,需瀏覽 25分鐘

         ·

        2022-02-25 15:56


        導(dǎo)讀:

        ClickHouse作為一款開源列式數(shù)據(jù)庫管理系統(tǒng)(DBMS)近年來備受關(guān)注,主要用于數(shù)據(jù)分析(OLAP)領(lǐng)域。作者根據(jù)以往經(jīng)驗和遇到的問題,總結(jié)出一些基本的開發(fā)和使用規(guī)范,以供使用者參考。


        隨著公司業(yè)務(wù)數(shù)據(jù)量日益增長,數(shù)據(jù)處理場景日趨復(fù)雜,急需一種具有高可用性和高性能的數(shù)據(jù)庫來支持業(yè)務(wù)發(fā)展,ClickHouse是俄羅斯的搜索公司Yandex開源的MPP架構(gòu)的分析引擎,號稱比事務(wù)數(shù)據(jù)庫快100-1000倍,最大的特色是高性能的向量化執(zhí)行引擎,而且功能豐富、可靠性高。


        在過去的一年中,杭研DBA團隊已經(jīng)支撐網(wǎng)易集團內(nèi)部多個事業(yè)部上線使用,集群規(guī)模共計十幾套,CPU近3000核,每日近千億數(shù)據(jù)入庫,千億級別表查詢可在秒級完成,大大提升了業(yè)務(wù)原有OLAP架構(gòu)的效能,覆蓋的業(yè)務(wù)場景包括:用戶行為日志分析,進行PV、UV、留存、轉(zhuǎn)化漏斗和操作,包括游戲反外掛數(shù)據(jù)統(tǒng)計分析;用戶畫像,人群圈定和問卷投放;AB實驗數(shù)據(jù)的實時計算與分析;機器和業(yè)務(wù)日志的分析、監(jiān)控、查詢等。


        1

        ClickHouse應(yīng)用場景


        1. 寫在前面

        (1)如果你的業(yè)務(wù)預(yù)算或機器資源有限,強烈不推薦使用clickhouse,因為這套架構(gòu)成本比較高。

        (2)最小集群部署所需機器:ck節(jié)點需要2臺256G內(nèi)存/40c cpu物理機,磁盤使用SSD,加上3臺zookeeper和2臺chproxy應(yīng)用主機或者云主機。

        (3)Clickhouse自帶了豐富的功能來應(yīng)對復(fù)雜的業(yè)務(wù)場景和大數(shù)據(jù)量,所以在使用期間需要運維和開發(fā)側(cè)都投入人力對這些功能(表引擎類型)學(xué)習(xí)和掌握。


        2. 業(yè)務(wù)在數(shù)據(jù)層的表現(xiàn)

        (1)業(yè)務(wù)大多數(shù)是讀請求,存儲寬表,無大字段,較少的并發(fā)(單臺100-200qps左右)。

        (2)數(shù)據(jù)批寫入(1000條以上,線上業(yè)務(wù)建議5w-10w),不修改或少修改已添加的數(shù)據(jù)。

        (3)無事務(wù)要求,對數(shù)據(jù)一致性要求低。

        (4)對于簡單查詢,允許延遲大約50毫秒,每一個查詢除了一個大表外都很小。

        (5)處理單個查詢時需要高吞吐量(每個服務(wù)器每秒高達數(shù)十億行)。


        3.具體業(yè)務(wù)場景

        (1)用戶行為分析,精細化運營分析:日活,留存率分析,路徑分析,有序漏斗轉(zhuǎn)化率分析,Session分析等;

        (2)實時日志分析,監(jiān)控分析;

        (3)實時數(shù)倉。


        2

        表引擎選擇


        ClickHouse表引擎一共分為四個系列,分別是Log、MergeTree、Integration、Special。其中包含了兩種特殊的表引擎Replicated、Distributed,功能上與其他表引擎正交,目前業(yè)務(wù)上主要使用MergeTree系列,配合使用Mview和Distributed引擎。


        ClickHouse 包含以下幾種常用的引擎類型:

        • MergeTree 引擎:該系列引擎是執(zhí)行高負載任務(wù)的最通用和最強大的表引擎,它們的特點是可以快速插入數(shù)據(jù)以及進行后續(xù)的數(shù)據(jù)處理。該系列引擎還同時支持數(shù)據(jù)復(fù)制(使用Replicated的引擎版本),分區(qū) (partition) 以及一些其它引擎不支持的額外功能。

        • Log 引擎:該系列引擎是具有最小功能的輕量級引擎。當(dāng)你需要快速寫入許多小表(最多約有100萬行)并在后續(xù)任務(wù)中整體讀取它們時使用該系列引擎是最有效的。

        • 集成引擎:該系列引擎是與其它數(shù)據(jù)存儲以及處理系統(tǒng)集成的引擎,如 Kafka,MySQL 以及 HDFS 等,使用該系列引擎可以直接與其它系統(tǒng)進行交互,但也會有一定的限制,如確有需要,可以嘗試一下。

        • 特殊引擎:該系列引擎主要用于一些特定的功能,如 Distributed 用于分布式查詢,MaterializedView 用來聚合數(shù)據(jù),以及 Dictionary 用來查詢字典數(shù)據(jù)等。


        在所有的表引擎中,最為核心的當(dāng)屬MergeTree系列表引擎,這些表引擎擁有最為強大的性能和最廣泛的使用場合。對于非MergeTree系列的其他引擎而言,主要用于特殊用途,場景相對有限。而MergeTree系列表引擎是官方主推的存儲引擎,支持幾乎所有ClickHouse核心功能,下面主要介紹MergeTree系列表引擎:


        1. MergeTree表引擎

        MergeTree在寫入一批數(shù)據(jù)時,數(shù)據(jù)總會以數(shù)據(jù)片段的形式寫入磁盤,且數(shù)據(jù)片段不可修改。為了避免片段過多,ClickHouse會通過后臺線程,定期合并這些數(shù)據(jù)片段,屬于相同分區(qū)的數(shù)據(jù)片段會被合成一個新的片段。這種數(shù)據(jù)片段往復(fù)合并的特點,也正是合并樹名稱的由來。


        ?MergeTree作為家族系列最基礎(chǔ)的表引擎,主要有以下特點:

        • 存儲的數(shù)據(jù)按照主鍵排序:允許創(chuàng)建稀疏索引,從而加快數(shù)據(jù)查詢速度

        • 支持分區(qū),可以通過PRIMARY KEY語句指定分區(qū)字段。

        • 支持數(shù)據(jù)副本

        • 支持數(shù)據(jù)采樣


        ?建表語法:

        CREATE?TABLE?[IF?NOT?EXISTS]?[db.]table_name?[ON?CLUSTER?cluster](???name1?[type1]?[DEFAULT|MATERIALIZED|ALIAS?expr1]?[TTL?expr1],????name2?[type2]?[DEFAULT|MATERIALIZED|ALIAS?expr2]?[TTL?expr2],????...????INDEX?index_name1?expr1?TYPE?type1(...)?GRANULARITY?value1,????INDEX?index_name2?expr2?TYPE?type2(...)?GRANULARITY?value2)?ENGINE?=?MergeTree()ORDER?BY?expr[PARTITION?BY?expr][PRIMARY?KEY?expr][SAMPLE?BY?expr][TTL?expr?[DELETE|TO?DISK?'xxx'|TO?VOLUME?'xxx'],?...][SETTINGS name=value, ...]


        • ENGINE:ENGINE = MergeTree(),MergeTree引擎沒有參數(shù)

        • ORDER BY:排序字段。比如ORDER BY (Col1, Col2),值得注意的是,如果沒有指定主鍵,默認情況下 sorting key(排序字段)即為主鍵。如果不需要排序,則可以使用ORDER BY tuple()語法,這樣的話,創(chuàng)建的表也就不包含主鍵。這種情況下,ClickHouse會按照插入的順序存儲數(shù)據(jù)。必選。

        • PARTITION BY:分區(qū)字段,強烈建議指定。

        • PRIMARY KEY:指定主鍵,如果排序字段與主鍵不一致,可以單獨指定主鍵字段。否則默認主鍵是排序字段??蛇x。

        • SAMPLE BY:采樣字段,如果指定了該字段,那么主鍵中也必須包含該字段。比如SAMPLE BY intHash32(UserID) ORDER BY (CounterID, EventDate, intHash32(UserID))??蛇x。

        • TTL:數(shù)據(jù)的存活時間。在MergeTree中,可以為某個列字段或整張表設(shè)置TTL。當(dāng)時間到達時,如果是列字段級別的TTL,則會刪除這一列的數(shù)據(jù);如果是表級別的TTL,則會刪除整張表的數(shù)據(jù)。大表強烈建議指定。

        • SETTINGS:額外的參數(shù)配置。一般設(shè)置index_granularity=8192 ,可選。


        2. ReplicatedMergeTree表引

        ReplicatedMergeTree使得以上 MergeTree 家族擁有副本機制,保證高可用,用于生產(chǎn)環(huán)境,對于大數(shù)據(jù)量的表來說不推薦使用,因為副本是基于zk做數(shù)據(jù)同步的,大數(shù)據(jù)量會對zk造成巨大壓力,成為整個ck整個集群瓶頸。業(yè)務(wù)可以根據(jù)數(shù)據(jù)重要程度在性能和數(shù)據(jù)副本之間做選擇。


        建表示例:

        CREATE?TABLE?[IF?NOT?EXISTS]?[db.]table_name?[ON?CLUSTER?cluster](`id`?Int64,?`ymd`?Int64)ENGINE?=?ReplicatedMergeTree('/clickhouse/tables/replicated/{shard}/test',?'{replica}')PARTITION?BY?ymdORDER BY id


        • /clickhouse/tables/ 這一部分指定的是在ZK上創(chuàng)建的路徑地址,可隨意變換只要記得即可

        • {shard} 指的是分片的標(biāo)志,同一個分片內(nèi)的所有機器應(yīng)該保持相同。建議使用使用的是集群名+分片名的配置也就是{layer}-{shard},這里的數(shù)據(jù)就是在macros中配置的屬性

        • test 建議使用表名稱

        • {replica} 參數(shù)建議在macros配置成機器的hostname,因為每臺機器的hostname都是不一樣的,因此就能確保每個表的識別符都是唯一的了


        3. ReplacingMergeTree表引

        上文提到MergeTree表引擎無法對相同主鍵的數(shù)據(jù)進行去重,ClickHouse提供了ReplacingMergeTree引擎,可以針對相同主鍵的數(shù)據(jù)進行去重,它能夠在合并分區(qū)時刪除重復(fù)的數(shù)據(jù)。值得注意的是,ReplacingMergeTree只是在一定程度上解決了數(shù)據(jù)重復(fù)問題,但是并不能完全保障數(shù)據(jù)不重復(fù)。


        建表語法:

        CREATE?TABLE?[IF?NOT?EXISTS]?[db.]table_name?[ON?CLUSTER?cluster](???name1?[type1]?[DEFAULT|MATERIALIZED|ALIAS?expr1],????name2?[type2]?[DEFAULT|MATERIALIZED|ALIAS?expr2],????...)?ENGINE?=?ReplacingMergeTree([ver])[PARTITION?BY?expr][ORDER?BY?expr][PRIMARY?KEY?expr][SAMPLE?BY?expr][SETTINGS name=value, ...]


        [ver]:可選參數(shù),列的版本,可以是UInt、Date或者DateTime類型的字段作為版本號。該參數(shù)決定了數(shù)據(jù)去重的方式。

        當(dāng)沒有指定[ver]參數(shù)時,保留最新的數(shù)據(jù);如果指定了具體的值,保留最大的版本數(shù)據(jù)。


        注意點:

        (1)去重規(guī)則

        ReplacingMergeTree是支持對數(shù)據(jù)去重的,去除重復(fù)數(shù)據(jù)時,是以O(shè)RDERBY排序鍵為基準(zhǔn)的,而不是PRIMARY KEY。

        (2)何時刪除重復(fù)數(shù)據(jù)

        在執(zhí)行分區(qū)合并時,會觸發(fā)刪除重復(fù)數(shù)據(jù)。optimize的合并操作是在后臺執(zhí)行的,無法預(yù)測具體執(zhí)行時間點,除非是手動執(zhí)行。

        (3)不同分區(qū)的重復(fù)數(shù)據(jù)不會被去重

        ReplacingMergeTree是以分區(qū)為單位刪除重復(fù)數(shù)據(jù)的。只有在相同的數(shù)據(jù)分區(qū)內(nèi)重復(fù)的數(shù)據(jù)才可以被刪除,而不同數(shù)據(jù)分區(qū)之間的重復(fù)數(shù)據(jù)依然不能被剔除。


        4. SummingMergeTree表引

        該引擎繼承了MergeTree引擎,當(dāng)合并 SummingMergeTree 表的數(shù)據(jù)片段時,ClickHouse 會把所有具有相同主鍵的行合并為一行,該行包含了被合并的行中具有數(shù)值數(shù)據(jù)類型的列的匯總值,即如果存在重復(fù)的數(shù)據(jù),會對對這些重復(fù)的數(shù)據(jù)進行合并成一條數(shù)據(jù),類似于group by的效果。


        推薦將該引擎和 MergeTree 一起使用。例如,將完整的數(shù)據(jù)存儲在 MergeTree 表中,并且使用 SummingMergeTree 來存儲聚合數(shù)據(jù)。這種方法可以避免因為使用不正確的主鍵組合方式而丟失數(shù)據(jù)。


        如果用戶只需要查詢數(shù)據(jù)的匯總結(jié)果,不關(guān)心明細數(shù)據(jù),并且數(shù)據(jù)的匯總條件是預(yù)先明確的,即GROUP BY的分組字段是確定的,可以使用該表引擎。


        建表語法:

        CREATE?TABLE?[IF?NOT?EXISTS]?[db.]table_name?[ON?CLUSTER?cluster](???name1?[type1]?[DEFAULT|MATERIALIZED|ALIAS?expr1],????name2?[type2]?[DEFAULT|MATERIALIZED|ALIAS?expr2],????????...)?ENGINE?=?SummingMergeTree([columns])?--?指定合并匯總字段[PARTITION?BY?expr][ORDER?BY?expr][SAMPLE?BY?expr][SETTINGS name=value, ...]


        ?注意點:

        ?要保證PRIMARY KEY expr指定的主鍵是ORDER BY expr 指定字段的前綴,比如

        ?-- 如下情況是允許的:

        ORDER?BY?(A,B,C)PRIMARY KEY A

        -- 如下情況會報錯:

        DB::Exception:?Primary?key?must?be?a?prefix?of?the?sorting?keyORDER?BY?(A,B,C)PRIMARY?KEY?B


        這種強制約束保障了即便在兩者定義不同的情況下,主鍵仍然是排序鍵的前綴,不會出現(xiàn)索引與數(shù)據(jù)順序混亂的問題。


        總結(jié):

        • SummingMergeTree是根據(jù)什么對兩條數(shù)據(jù)進行合并的用ORBER BY排序鍵作為聚合數(shù)據(jù)的條件Key。即如果排序key是相同的,則會合并成一條數(shù)據(jù),并對指定的合并字段進行聚合。

        • 僅對分區(qū)內(nèi)的相同排序key的數(shù)據(jù)行進行合并以數(shù)據(jù)分區(qū)為單位來聚合數(shù)據(jù)。當(dāng)分區(qū)合并時,同一數(shù)據(jù)分區(qū)內(nèi)聚合Key相同的數(shù)據(jù)會被合并匯總,而不同分區(qū)之間的數(shù)據(jù)則不會被匯總。

        • 如果沒有指定聚合字段,會怎么聚合如果沒有指定聚合字段,則會按照非主鍵的數(shù)值類型字段進行聚合

        • 對于非匯總字段的數(shù)據(jù),該保留哪一條如果兩行數(shù)據(jù)除了排序字段相同,其他的非聚合字段不相同,那么在聚合發(fā)生時,會保留最初的那條數(shù)據(jù),新插入的數(shù)據(jù)對應(yīng)的那個字段值會被舍棄。


        5. Aggregatingmergetree表引

        該表引擎繼承自MergeTree,可以使用 AggregatingMergeTree 表來做增量數(shù)據(jù)統(tǒng)計聚合。如果要按一組規(guī)則來合并減少行數(shù),則使用 AggregatingMergeTree 是合適的。


        AggregatingMergeTree是通過預(yù)先定義的聚合函數(shù)計算數(shù)據(jù)并通過二進制的格式存入表內(nèi)。與SummingMergeTree的區(qū)別在于:SummingMergeTree對非主鍵列進行sum聚合,而AggregatingMergeTree則可以指定各種聚合函數(shù)。


        建表語法:

        CREATE?TABLE?[IF?NOT?EXISTS]?[db.]table_name?[ON?CLUSTER?cluster](????name1?[type1]?[DEFAULT|MATERIALIZED|ALIAS?expr1],?????????name2?[type2]?[DEFAULT|MATERIALIZED|ALIAS?expr2],?????????...)?ENGINE?=?AggregatingMergeTree()[PARTITION?BY?expr][ORDER?BY?expr][SAMPLE?BY?expr][SETTINGS name=value, ...]


        ?6. 其他特殊的表引

        Distributed表引擎

        Distributed表引擎是分布式表的代名詞,它自身不存儲任何數(shù)據(jù),數(shù)據(jù)都分散存儲在某一個分片上,能夠自動路由數(shù)據(jù)至集群中的各個節(jié)點,所以Distributed表引擎需要和其他數(shù)據(jù)表引擎一起協(xié)同工作。


        所以,一張分布式表底層會對應(yīng)多個本地分片數(shù)據(jù)表,由具體的分片表存儲數(shù)據(jù),分布式表與本地分片數(shù)據(jù)表是一對多的關(guān)系。


        Distributed表引擎的定義形式如下所示:

        Distributed(cluster_name, database_name, table_name[, sharding_key])


        各個參數(shù)的含義分別如下:

        • cluster_name:集群名稱,與集群配置中的自定義名稱相對應(yīng)。

        • database_name:數(shù)據(jù)庫名稱

        • table_name:表名稱

        • sharding_key:可選的,用于分片的key值,在數(shù)據(jù)寫入的過程中,分布式表會依據(jù)分片key的規(guī)則,將數(shù)據(jù)分布到各個節(jié)點的本地表。


        創(chuàng)建分布式表是讀時檢查的機制,也就是說對創(chuàng)建分布式表和本地表的順序并沒有強制要求。


        同樣值得注意的是,在上面的語句中使用了ON CLUSTER分布式DDL,這意味著在集群的每個分片節(jié)點上,都會創(chuàng)建一張Distributed表,這樣便可以從其中任意一端發(fā)起對所有分片的讀、寫請求。


        3

        開發(fā)規(guī)范


        ?1. 查詢sql編寫規(guī)范

        (1)當(dāng)多表聯(lián)查時,查詢的數(shù)據(jù)僅從其中一張表出時,可考慮使用IN操作而不是JOIN。

        (2)多表查詢性能較差,多表Join時要滿足小表在右的原則,右表關(guān)聯(lián)時被加載到內(nèi)存中與左表進行比較,ClickHouse中無論是Left Join 、Right Join還是Inner Join永遠都是拿著右表中的每一條記錄到左表中查找該記錄是否存在,所以右表必須是小表。

        (3)將一些需要關(guān)聯(lián)分析的業(yè)務(wù)創(chuàng)建成字典表進行join操作,前提是字典表不宜太大,因為字典表會常駐內(nèi)存。

        (4)禁?業(yè)務(wù)select *?,列存數(shù)據(jù),每減少一個字段會減少大量的數(shù)據(jù)掃描,提升查詢效率。

        (5)建議使用 limit 限制返回數(shù)據(jù)條數(shù)使用limit返回指定的結(jié)果集數(shù)量,不會進行向下掃描,大大提升了查詢效率。

        6)查詢時如果可以建議帶上分區(qū)鍵查詢,可以有效減少數(shù)據(jù)掃描量,提升查詢效率。

        (7)CK的稀疏索引使得點查詢(即kv類型的查詢)性能不佳,千萬不要把它簡單當(dāng)做關(guān)系型數(shù)據(jù)庫進行查詢。

        (8)使用Global優(yōu)化分布式子查詢,避免出現(xiàn)查詢指數(shù)級放大。

        (9)使用 uniqCombined 替代 distinctuniqCombined 對去重進行了優(yōu)化,通過近似去重提升十倍查詢性能。

        (10)盡量不去使用字符串類型,時間類型最終會轉(zhuǎn)換成數(shù)值類型進行處理,數(shù)值類型在執(zhí)行效率和存儲上遠好過字符串。

        (11)ClickHouse的分布式表性能性價比不如物理表高,建表分區(qū)字段值不宜過多,防止數(shù)據(jù)導(dǎo)入過程磁盤可能會被打滿。

        (12)不要在唯一列或大基數(shù)列上進行分組或去重操作,基數(shù)太大會消耗過多的io和內(nèi)存。

        (13)CPU一般在50%左右會出現(xiàn)查詢波動,達到70%會出現(xiàn)大范圍的查詢超時,CPU是最關(guān)鍵的指標(biāo),要非常關(guān)注。


        ?2. 數(shù)據(jù)寫入注意事項

        (1)不適合高并發(fā)寫入,最好還是從異步化隊列寫入,batch insert 5w-10w 起步,盡量不要執(zhí)行單條或插入操作,會產(chǎn)生大量小分區(qū)文件,給后臺merge任務(wù)帶來巨大壓力。

        (2)幾乎完全不支持update/delete,也不支持事務(wù)。

        (3)建議表要指定分區(qū)鍵,尤其是數(shù)據(jù)量大的表,插入/查詢/合并都是以分區(qū)為單位,合理的分區(qū)可以提升整體性能。

        (4)分區(qū)不建議太多,如果分區(qū)太多,會因需要打開的文件描述符過多導(dǎo)致查詢效率不佳。

        (5)數(shù)據(jù)在寫入ClickHouse前預(yù)先的對數(shù)據(jù)進行分組,避免一次插入的數(shù)據(jù)屬于多個分區(qū)。

        (6)注意MerTree 主鍵允許存在重復(fù)數(shù)據(jù)(ReplacingMergeTree可以在分區(qū)內(nèi)去重)。


        ?3. 建表規(guī)范

        (1)本地表命名格式:{tab_name}_local,分布式表命名格式:{tab_name}_shard 。

        (2)物化視圖命名規(guī)范:{tabl_name_xxx}_mv 。

        (3)盡量不要使用Nullable類型,該類型對性能有一定影響,且不能包含在索引中。

        (4)合理設(shè)置分區(qū),所有本地表使用order by關(guān)鍵字指定分區(qū)字段,建議采用日期作為一級分區(qū)。默認 order by 字段作為主鍵。

        5)如果表中不是必須保留全量歷史數(shù)據(jù),建議指定TTL,可以免去手動過期歷史數(shù)據(jù)的麻煩。?

        (6)所有復(fù)制引擎表建表指定 use_minimalistic_part_header_in_zookeeper=1。

        ??

        ?本地ReplicatedMergeTree表建表模板如下所示:

        CREATE TABLE IF NOT EXISTS ads. ads_af_city_complaint_1d _local ON cluster ycdata_3shards_3replicas(`id`?UInt64?COMMENT?'序號',`order_id`?UInt64?COMMENT?'訂單號',`gross_weight`?UInt64??COMMENT?'權(quán)重',`create_time`?Date?COMMENT?'創(chuàng)建時間',`event`?String?COMMENT?'事件')ENGINE = ReplicatedMergeTree('/clickhouse/table/{shared}/ads_af_city_complaint_1d _local', '{replica}')PARTITION?BY?create_timeORDER?BY?idTTL create_time + toIntervalDay(90)SETTINGS?index_granularity?=?8192,?use_minimalistic_part_header_in_zookeeper?=?1;


        解釋:

        • TTL 定義了數(shù)據(jù)保留策略為90天。

        • {shared},{replica}無需替換為一個具體值。

        • ycdata_3shards_3replicas為clickhouse是集群名稱。


        4

        集群架構(gòu)


        ?1. 常用架構(gòu)

        為簡化業(yè)務(wù)使用方式,降低業(yè)務(wù)使用成本。對clickhouse集群的使用做一些約束,能夠提升交付速度,提高標(biāo)準(zhǔn)化程度,降低使用成本。


        以4臺機器為例,集群模式固定為2分片2副本模式,若數(shù)據(jù)量較大4臺機器不夠時,可以增加2臺機器,集群模式未3分片每個分片2副本形式,另外需要3臺zookeeper和2臺chproxy應(yīng)用主機或者云主機,兩臺chproxy使用NLB管理,程序直連NLB IP。


        對于單表數(shù)據(jù)量超過100億數(shù)據(jù)的表不建議使用副本表,建議采用4分片0副本架構(gòu)。(具體架構(gòu)可以和DBA溝通后確定)


        總體上講,一句話總結(jié):業(yè)務(wù)訪問統(tǒng)一入口,讀分布式表,寫本地表。


        ?優(yōu)勢:

        • ?解決clickhouse集群高可用性,保證單機器宕機情況不影響集群可用性。

        • ?解決寫入分布式表寫入效率低以及讀分布式表時熱點問題

        • ?解決寫入本地表數(shù)據(jù)需要業(yè)務(wù)層路由的問題

        • ?降低業(yè)務(wù)使用門檻,提升交付效率


        限制:

        (1)業(yè)務(wù)寫入本地表(以_local結(jié)尾),讀分布式表(以_shard結(jié)尾表)

        • 業(yè)務(wù)表名為musci_bi_t1,則寫入musci_bi_t1_local 通過proxy代理輪詢寫入底層節(jié)點保證數(shù)據(jù)分布均衡;

        • 讀musci_bi_t1_shard表,同樣可以通過proxy將shard表路由壓力分散到底層節(jié)點。

        (2)業(yè)務(wù)寫入時需要批量寫入,需要業(yè)務(wù)去保證每批次數(shù)據(jù)量大小盡量一致,以保證數(shù)據(jù)盡量均勻分布。

        (3)業(yè)務(wù)每批次寫入時都要重新獲取連接,禁止使用長連接否則無法使用負載均衡能力,會導(dǎo)致數(shù)據(jù)分布不均衡。

        (4)不支持跨集群訪問

        • 不同集群內(nèi)的分片以及副本數(shù)量不固定,可能會導(dǎo)致某些節(jié)點沒有l(wèi)ocal表,會使得寫入失??;

        • 統(tǒng)一集群名與database名,防止跨集群訪問。


        問題:

        因業(yè)務(wù)每批次寫入數(shù)據(jù)量的不同,會導(dǎo)致數(shù)據(jù)分布的不均勻。


        運維注意點:

        • 對業(yè)務(wù)不透明,insert需要指定local結(jié)尾表,查詢需要查sharded表,需要與業(yè)務(wù)確認;

        • 副本同步使用底層ReplicatedMergeTree引擎,提升副本同步性能以及數(shù)據(jù)一致性(需要手動創(chuàng)建底層表,保證主備關(guān)系正確);

        • 使用on cluster 語法在每個節(jié)點中創(chuàng)建分布式表,提升建表效率。


        2. zookeeper的關(guān)鍵作用

        ClickHouse中依賴Zookeeper解決的問題可以分為兩大類:分布式DDL執(zhí)行、ReplicatedMergeTree表主備節(jié)點之間的狀態(tài)同步。zk的性能會影響整個集群的性能表現(xiàn)。使用復(fù)制表之后,隨著數(shù)據(jù)量的增加,zookeeper可能成為集群瓶頸,zk集群建議機器配置如下:3臺32G/4c機器,萬兆網(wǎng)卡,磁盤80G-200G。


        可以看作ck把zookeeper用成了目錄服務(wù),日志服務(wù)和協(xié)調(diào)服務(wù),當(dāng)znode達到幾百萬后,zk出現(xiàn)異常,常見是連接失敗,此時有些表會出現(xiàn)readonly模式。頭條對這個問題的處理方式是改寫源碼調(diào)整ck對zk的使用方式,為zk減重。


        如果業(yè)務(wù)上單表數(shù)據(jù)量較大并且希望使用復(fù)制表,務(wù)必在建表時指定use_minimalistic_part_header_in_zookeeper參數(shù)為1,達到壓縮zk數(shù)據(jù)的目的。


        3. chproxy

        chproxy官方推薦的是專用于ClickHouse數(shù)據(jù)庫的HTTP代理和負載均衡器,使用go語言實現(xiàn),目前僅支持http協(xié)議。在Clickhouse集群中,每一臺機器都是單獨的實例,我們可以使用其中的一臺作為查詢機器。此時如何更好的完成負載均衡是我們所關(guān)注的,chproxy即是這么一個工具。


        特性:

        • 用戶路由和響應(yīng)緩存。

        • 靈活的限制。

        • 自動SSL證書續(xù)訂。


        chroxy連接測試:

        echo 'show databases;' | curl 'http://10.200.161.49:9009/?user=writeuser&password=xxxx' --data-binary @-


        關(guān)于chroxy參數(shù)配置可參照如下文檔:

        https://github.com/ContentSquare/chproxy

        ?

        5

        客戶端工具選擇


        1. DBeave

        DBeaver是免費和開源(GPL)為開發(fā)人員和數(shù)據(jù)庫管理員通用數(shù)據(jù)庫工具。易用性是該項目的主要目標(biāo),是經(jīng)過精心設(shè)計和開發(fā)的數(shù)據(jù)庫管理工具。免費、跨平臺、基于開源框架和允許各種擴展寫作(插件)。


        2. Superse

        Superset 是一款由 Airbnb 開源的“現(xiàn)代化的企業(yè)級 BI(商業(yè)智能) Web 應(yīng)用程序”,其通過創(chuàng)建和分享 dashboard,為數(shù)據(jù)分析提供了輕量級的數(shù)據(jù)查詢和可視化方案。


        3. Tabi

        功能和部署方式與Superset相似,可參考如下文檔:

        https://github.com/smi2/tabix.ui/releases


        6

        可用性說明


        根據(jù)選擇的集群架構(gòu)不同, clickhouse集群表現(xiàn)出的可用性也不同。

        (1)數(shù)據(jù)的讀寫高可用就是依賴復(fù)制表引擎創(chuàng)建多副本機制保證。如果Clickhouse集群使用是多分片多副本架構(gòu),當(dāng)一個副本所在的機器宕機后,chproxy層會自動路由到可用的副本讀寫數(shù)據(jù);

        (2)如果Clickhouse集群只用了sharding分片,沒有用到復(fù)制表作為數(shù)據(jù)副本,那么單臺機器宕機只會影響到單個數(shù)據(jù)分片的讀寫;

        (3)當(dāng)zk集群不可用時,整個集群的寫入會都會受影響,不管有沒有使用復(fù)制表。


        總結(jié):

        數(shù)據(jù)可用性要求越高,意味著投入更多的資源,單臺機器的資源利用率越低,業(yè)務(wù)可根據(jù)數(shù)據(jù)重要程度靈活選擇,不過Clickhouse的定位是在線分析olap系統(tǒng),建議業(yè)務(wù)方將ck里的數(shù)據(jù)也定義為二級數(shù)據(jù),數(shù)據(jù)丟失后是可以再生成的,從而控制整體架構(gòu)的成本,提高單臺機器的資源利用率。同時強烈建議業(yè)務(wù)不要強依賴Clickhouse,要有一定的兜底和熔斷機制。


        7

        集群配置參數(shù)調(diào)優(yōu)


        1. max_concurrent_querie

        最大并發(fā)處理的請求數(shù)(包含select,insert等),默認值100,推薦150(不夠再加),在我們的集群中出現(xiàn)過”max concurrent queries”的問題。


        2. max_bytes_before_external_sor

        當(dāng)order by已使用max_bytes_before_external_sort內(nèi)存就進行溢寫磁盤(基于磁盤排序),如果不設(shè)置該值,那么當(dāng)內(nèi)存不夠時直接拋錯,設(shè)置了該值order by可以正常完成,但是速度相對內(nèi)存來說肯定要慢點(實測慢的非常多,無法接受)。


        3. background_pool_size

        后臺線程池的大小,merge線程就是在該線程池中執(zhí)行,當(dāng)然該線程池不僅僅是給merge線程用的,默認值16,推薦32提升merge的速度(CPU允許的前提下)。


        4. max_memory_usag

        單個SQL在單臺機器最大內(nèi)存使用量,該值可以設(shè)置的比較大,這樣可以提升集群查詢的上限。


        5. max_memory_usage_for_all_querie

        單機最大的內(nèi)存使用量可以設(shè)置略小于機器的物理內(nèi)存(留一點內(nèi)操作系統(tǒng))。

        ?

        6. max_bytes_before_external_group_b

        在進行g(shù)roup by的時候,內(nèi)存使用量已經(jīng)達到了max_bytes_before_external_group_by的時候就進行寫磁盤(基于磁盤的group by相對于基于磁盤的order by性能損耗要好很多的),一般max_bytes_before_external_group_by設(shè)置為max_memory_usage / 2,原因是在clickhouse中聚合分兩個階段:

        • 查詢并且建立中間數(shù)據(jù);

        • 合并中間數(shù)據(jù) 寫磁盤在第一個階段,如果無須寫磁盤,clickhouse在第一個和第二個階段需要使用相同的內(nèi)存。


        這些內(nèi)存參數(shù)強烈推薦配置上,增強集群的穩(wěn)定性避免在使用過程中出現(xiàn)莫名其妙的異常。


        學(xué)習(xí)資料:

        • 官網(wǎng)??

          https://clickhouse.com/docs/en/engines/table-engines/integrations/

        • 中文社區(qū)??

          http://clickhouse.com.cn/



        作者簡介

        劉彥鵬,網(wǎng)易杭州研究院數(shù)據(jù)庫工程師。



        獲取最新動態(tài)

        最新的推文無法在第一時間看到?

        以前的推文還需要復(fù)雜漫長的翻閱?


        進入“網(wǎng)易有數(shù)”公眾號介紹頁,點擊右上角

        “設(shè)為星標(biāo)”!

        置頂公眾號,從此消息不迷路


        設(shè)為星標(biāo),最新推文不迷路


        分享,點贊,在看,安排一下?
        瀏覽 82
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        評論
        圖片
        表情
        推薦
        點贊
        評論
        收藏
        分享

        手機掃一掃分享

        分享
        舉報
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            男插女青青 | 一级欧美大片 | 成人性爱视频一区二区 | 嗯啊憋涨揉尿按顶端男男总裁h | 夜店三级在线播放hd | 翔田千里电影1234区 | 囚禁调教分腿器扩张 | 亚洲AV乱码成人精品国5 | 亚洲国产永久精品成人麻豆 | 在线A∨|