免費(fèi)做網(wǎng)站的網(wǎng)址有哪些網(wǎng)絡(luò)整合營(yíng)銷(xiāo)4i原則
作為企業(yè)數(shù)字化建設(shè)的必備要素,易用的數(shù)據(jù)引擎能幫助企業(yè)提升數(shù)據(jù)使用效率,更好提升數(shù)據(jù)應(yīng)用價(jià)值,夯實(shí)數(shù)字化建設(shè)基礎(chǔ)。
數(shù)據(jù)導(dǎo)入是衡量OLAP引擎性能及易用性的重要標(biāo)準(zhǔn)之一,高效的數(shù)據(jù)導(dǎo)入能力能夠加速數(shù)據(jù)實(shí)時(shí)處理和分析的效率。作為一款OLAP引擎,火山引擎云原生數(shù)據(jù)倉(cāng)庫(kù)ByteHouse源于開(kāi)源ClickHouse,在字節(jié)跳動(dòng)多年打磨下,提供更豐富的能力和更強(qiáng)性能,能為用戶帶來(lái)極速分析體驗(yàn),支撐實(shí)時(shí)數(shù)據(jù)分析和海量離線數(shù)據(jù)分析,具備便捷的彈性擴(kuò)縮容能力,極致的分析性能和豐富的企業(yè)級(jí)特性。
隨著B(niǎo)yteHouse內(nèi)外部用戶規(guī)模不斷擴(kuò)大, 越來(lái)越多用戶對(duì)數(shù)據(jù)導(dǎo)入提出更高的要求,這也為ByteHouse的數(shù)據(jù)導(dǎo)入能力帶來(lái)了更大的挑戰(zhàn)。
本篇文章來(lái)源于ByteHouse產(chǎn)品專家在火山引擎數(shù)智平臺(tái)(VeDI)主辦的“數(shù)智化轉(zhuǎn)型背景下的火山引擎大數(shù)據(jù)技術(shù)揭秘”線下Meeup的演講,將從ByteHouse數(shù)據(jù)庫(kù)架構(gòu)演進(jìn)、增強(qiáng)HaKafka引擎實(shí)現(xiàn)方案、增強(qiáng)Materialzed MySQL實(shí)現(xiàn)方案、案例實(shí)踐和未來(lái)展望四個(gè)部分展開(kāi)分享。
ByteHouse數(shù)據(jù)庫(kù)的架構(gòu)演進(jìn)
作為一款分析型數(shù)據(jù)庫(kù),ByteHouse已經(jīng)應(yīng)用在互聯(lián)網(wǎng)、金融、汽車(chē)領(lǐng)域,幫助企業(yè)實(shí)現(xiàn)人群洞察、行為分析、 IOT 風(fēng)控等場(chǎng)景的實(shí)時(shí)分析。
ByteHouse的演進(jìn)
從2017年開(kāi)始,字節(jié)內(nèi)部的整體數(shù)據(jù)量不斷上漲,為了支撐實(shí)時(shí)分析的業(yè)務(wù),字節(jié)內(nèi)部開(kāi)始了對(duì)各種數(shù)據(jù)庫(kù)的選型。經(jīng)過(guò)多次實(shí)驗(yàn),在實(shí)時(shí)分析版塊,字節(jié)內(nèi)部決定開(kāi)始試水ClickHouse。
2018年到2019年,字節(jié)內(nèi)部的ClickHouse業(yè)務(wù)從單一業(yè)務(wù),逐步發(fā)展到了多個(gè)不同業(yè)務(wù),適用到更多的場(chǎng)景,包括BI 分析、A/B測(cè)試、模型預(yù)估等。
在上述這些業(yè)務(wù)場(chǎng)景的不斷實(shí)踐之下,研發(fā)團(tuán)隊(duì)基于原生ClickHouse做了大量的優(yōu)化,同時(shí)又開(kāi)發(fā)了非常多的特性。
2020年, ByteHouse正式在字節(jié)跳動(dòng)內(nèi)部立項(xiàng),2021年通過(guò)火山引擎對(duì)外服務(wù)。
截止2022年3月,ByteHouse在字節(jié)內(nèi)部總節(jié)點(diǎn)數(shù)達(dá)到18000個(gè),而單一集群的最大規(guī)模是2400個(gè)節(jié)點(diǎn)。
ByteHouse的架構(gòu)
ByteHouse架構(gòu)分為分布式架構(gòu)和云原生架構(gòu)兩種。分布式架構(gòu)的主要特點(diǎn)就是單集群可以支持 2000 多個(gè)節(jié)點(diǎn)的“大兵團(tuán)”;通過(guò)分布式的并行計(jì)算體現(xiàn)的高性能,能夠充分利用每個(gè)節(jié)點(diǎn)的計(jì)算和存儲(chǔ)資源;云原生實(shí)現(xiàn)了存算分離,計(jì)算資源通過(guò)容器化進(jìn)行彈性和秒級(jí)的擴(kuò)容,這對(duì)業(yè)務(wù)是無(wú)感知的。
從分布式架構(gòu)來(lái)看,ByteHouse具備MPP 1.0特點(diǎn):
存算一體:通過(guò)本地存儲(chǔ)能夠保證它極致的這種查詢性能。
自研的表引擎:包含 HaMergeTree和 HaUniqueMergeTree。
在社區(qū) RBO 優(yōu)化器的基礎(chǔ)上增強(qiáng) RBO 加 CBO 的結(jié)合的查詢優(yōu)化,并基于 CBO 的分布式計(jì)劃能夠在集群模式下計(jì)算全局最優(yōu)的查詢計(jì)劃。
支持?jǐn)?shù)據(jù)的冷熱分存,同時(shí)兼顧性能和成本。
增強(qiáng)關(guān)鍵的數(shù)據(jù)類(lèi)型,從而優(yōu)化查詢性能。
通過(guò)統(tǒng)一的管控面提供可視化的管理查詢和運(yùn)維,從內(nèi)到外給用戶提供優(yōu)質(zhì)的使用體驗(yàn)。

但MPP 1.0存在資源隔離、擴(kuò)容等痛點(diǎn),由此演進(jìn)到云原生架構(gòu),即MPP 2.0:其中存算分離通過(guò)結(jié)合 shared-everything 存儲(chǔ)和 shared-nothing 計(jì)算層,避免了傳統(tǒng) MPP 架構(gòu)中數(shù)據(jù)重新分配 (re-sharding) 的問(wèn)題。
好處在于:
更好地實(shí)現(xiàn)資源隔離。每個(gè)用戶不同的計(jì)算都提交到不同的計(jì)算組,并進(jìn)行計(jì)算資源和存儲(chǔ)資源的擴(kuò)容,再結(jié)合按量計(jì)費(fèi)的計(jì)費(fèi)策略可以降低用戶使用成本。
底層存儲(chǔ)既支持HDFS,也支持 S3 對(duì)象存儲(chǔ),能夠讓 ByteHouse實(shí)現(xiàn)真正的云原生。

ByteHouse技術(shù)優(yōu)勢(shì)
在增強(qiáng)型數(shù)據(jù)導(dǎo)入場(chǎng)景中,ByteHouse核心優(yōu)勢(shì)體現(xiàn)在自研表引擎:
在社區(qū)版的基礎(chǔ)上,ByteHouse對(duì)表引擎做了進(jìn)一步增強(qiáng),使其能夠?qū)崿F(xiàn)開(kāi)源的ClickHouse所做不到的場(chǎng)景。
高可用引擎,相比社區(qū)高可用引擎,可以支持表的數(shù)量更多,集群的規(guī)模更大,穩(wěn)定性會(huì)更高。
實(shí)時(shí)數(shù)據(jù)引擎,相比社區(qū)實(shí)時(shí)數(shù)據(jù)引擎,消費(fèi)能力更強(qiáng),支持 at least once 的語(yǔ)義,排除單點(diǎn)寫(xiě)入的性能故障。
Unique引擎,相比社區(qū)Unique引擎,ByteHouse沒(méi)有更新延遲問(wèn)題,能夠?qū)崿F(xiàn)真正實(shí)時(shí)的 upsert。
Bitmap 引擎,在特定的場(chǎng)景比如用戶圈選圈群的場(chǎng)景中支持大量的交并補(bǔ)操作,能夠使整體的性能提升 10 - 50 倍以上。

這里具體再介紹一下ByteHouse自研引擎的優(yōu)勢(shì)——與導(dǎo)入密切相關(guān)的表引擎。
首先,ByteHouse 提供的HaMergeTree方案能夠降低 ZK 負(fù)載,提升可承載的數(shù)據(jù)量級(jí)。
ClickHouse 社區(qū)版本: 社區(qū)提供的ReplicatedMergeTree表引擎讓 ClickHouse 實(shí)現(xiàn)了從單機(jī)到集群的演進(jìn),通過(guò)ZK節(jié)點(diǎn)來(lái)同步并維護(hù)兩個(gè)MergeTree之間的元數(shù)據(jù)和數(shù)據(jù)。痛點(diǎn)在于,在 TB 級(jí)的數(shù)據(jù)量級(jí)之下, ZK 重復(fù)地進(jìn)行分發(fā)日志和數(shù)據(jù)交換等操作,極大地增加了ZK的壓力,使ZK 成為整個(gè)集群的故障點(diǎn)。
ByteHouse 自研HaMergeTree: 將元數(shù)據(jù)的同步和數(shù)據(jù)的同步解耦,ZK只負(fù)責(zé)元數(shù)據(jù)的同步,而數(shù)據(jù)的同步是通過(guò) LogExchange 來(lái)實(shí)現(xiàn),在兩個(gè)MergeTree之間進(jìn)行對(duì)等拷貝。優(yōu)勢(shì)在于,降低了 ZK 的負(fù)載,即使是承載 PB 級(jí)的數(shù)據(jù)量,集群也能夠平穩(wěn)地運(yùn)行。
其次, ByteHouse 提供的HaMergeTree方案能平衡讀寫(xiě)性能。
ClickHouse 社區(qū)版本: 提供ReplacingMerge Tree實(shí)現(xiàn)了對(duì)唯一鍵的支持;使用Merge-on-read的實(shí)現(xiàn)邏輯,在不同批次的數(shù)據(jù)中包含著相同的 key ,需要在讀時(shí)做合并,讓相同的 key 返回最新的版本。痛點(diǎn)在于,數(shù)據(jù)存在延遲、滯后,降低讀的性能。
ByteHouse 自研的HaUniqueMergeTree: 引入了 delete bitmap 的組件在數(shù)據(jù)插入時(shí)即標(biāo)記刪除,然后在數(shù)據(jù)查詢時(shí)過(guò)濾掉標(biāo)記刪除的數(shù)據(jù)。優(yōu)勢(shì)在于,整體上平衡了讀和寫(xiě)的性能,保障了讀取時(shí)性能一致性。
增強(qiáng)HaKafka引擎實(shí)現(xiàn)方案
HaKafka 引擎架構(gòu)介紹
社區(qū)版Kafka 優(yōu)勢(shì) : 由于社區(qū)版ClickHouse是一個(gè)分布式結(jié)構(gòu),其數(shù)據(jù)分布在多個(gè)Shard上,Kafka引擎可以在多個(gè)Shard上去做并發(fā)的寫(xiě)入,而在同一個(gè)Shard內(nèi)可以啟動(dòng)多線程做并發(fā)寫(xiě)入,并具備本地盤(pán)的極致的性能讀寫(xiě)。
社區(qū)版 Kafka 不足 :
在內(nèi)外部業(yè)務(wù)的場(chǎng)景中,會(huì)經(jīng)常遇到唯一鍵場(chǎng)景,由于社區(qū)版本的 Kafka的 high level 的消費(fèi)模式(這種模式就決定無(wú)法預(yù)知數(shù)據(jù)被寫(xiě)入到哪一個(gè)Shard上),所以很難滿足這一類(lèi)場(chǎng)景。
社區(qū)版的 Kafka 引擎沒(méi)有高可用,即使ClickHouse是多副本的,在當(dāng)一個(gè)節(jié)點(diǎn)發(fā)生宕機(jī)時(shí),無(wú)法保證另一個(gè)節(jié)點(diǎn)繼續(xù)消費(fèi)。
HaKafka引擎架構(gòu)(分布式架構(gòu))
保持社區(qū)版本兩級(jí)并發(fā)兩大的優(yōu)化點(diǎn):
引入高可用,讓備節(jié)點(diǎn)處于 stand-by 的狀態(tài),一旦主節(jié)點(diǎn)發(fā)生宕機(jī),備節(jié)點(diǎn)立刻繼續(xù)進(jìn)行消費(fèi)。
升級(jí)為low-level的消費(fèi)模式,當(dāng)數(shù)據(jù)寫(xiě)入的時(shí)候,相同的 key 會(huì)寫(xiě)到相同的 partition 里面,保證在同一個(gè)Shard下支持的唯一鍵場(chǎng)景。
ByteHouse增強(qiáng)HaKafka引擎核心功能實(shí)現(xiàn)
高可用(主備切換)
在備節(jié)點(diǎn)上起一個(gè) stand by的consumer ,通過(guò) ZK 來(lái)進(jìn)行選組,選到的主節(jié)點(diǎn)進(jìn)行消費(fèi),當(dāng)主節(jié)點(diǎn)發(fā)生宕機(jī)或者無(wú)法進(jìn)行服務(wù)時(shí),在秒級(jí)之內(nèi)切換到備節(jié)點(diǎn)上,讓備節(jié)點(diǎn)繼續(xù)消費(fèi)。
假設(shè)現(xiàn)在 replica 1因?yàn)楣收襄礄C(jī)了,無(wú)法繼續(xù)進(jìn)行消費(fèi),那么Z K能在秒級(jí)內(nèi)把 replica 2 選為leader。replica 2 隨即會(huì)立即啟動(dòng)相同數(shù)量的消費(fèi)者,啟動(dòng)之后會(huì)繼續(xù)從 replica 1 的消費(fèi)位置開(kāi)始繼續(xù)進(jìn)行消費(fèi)。

替換節(jié)點(diǎn)
隨著集群規(guī)模的增大,節(jié)點(diǎn)數(shù)越來(lái)越多的情況下,不可避免地遇到節(jié)點(diǎn)故障,這個(gè)時(shí)候就需要替換節(jié)點(diǎn)。
對(duì)于分布式架構(gòu),替換節(jié)點(diǎn)一個(gè)重要的操作就是拷貝數(shù)據(jù),在拷貝數(shù)據(jù)的時(shí)候意味著新的節(jié)點(diǎn)的數(shù)據(jù)是不全的,如圖示,示意圖 replica 1為新替換的節(jié)點(diǎn),還處于數(shù)據(jù)拷貝的狀態(tài),即數(shù)據(jù)是不全,如果此時(shí)實(shí)施消費(fèi)的 leader 起在了 replica 1,就意味著 最新的消費(fèi)數(shù)據(jù)會(huì)寫(xiě)進(jìn) replica 1,但是它缺失一部分舊的數(shù)據(jù)。
而replica 2有舊的數(shù)據(jù),它的最新數(shù)據(jù)還需要從replica 1進(jìn)行拷貝,那這個(gè)時(shí)候下載之內(nèi)沒(méi)有一個(gè)副本上面的數(shù)據(jù)是完整的,所有的節(jié)點(diǎn)就不可能對(duì)外提供服務(wù)。
這時(shí)HaKafka會(huì)做強(qiáng)制限制,如果 replica 1是一個(gè)新節(jié)點(diǎn),且還在拷貝數(shù)據(jù)的狀態(tài),那么就會(huì)強(qiáng)制把 leader 切換成 replica 2,由 replica 2 繼續(xù)去消費(fèi)最新的數(shù)據(jù),replica 1保持繼續(xù)拷貝數(shù)據(jù),這樣可以保證在節(jié)點(diǎn)替換的過(guò)程中至少有一個(gè)副本是能夠正常提供服務(wù)。

Memory table
不同于社區(qū)的Memory Table和底層存儲(chǔ)綁定,ByteHouse的Memory Table是和Hakafka綁定的,主要使用在有百列或者千列的大寬表的場(chǎng)景。
對(duì)于ClickHouse來(lái)說(shuō),每一次導(dǎo)入的寫(xiě)的文件的數(shù)量和列數(shù)是成正比的。如果列很多,但是每批次寫(xiě)入的數(shù)據(jù)量不大,這時(shí)每一次寫(xiě)入就會(huì)造成很多的碎片,這對(duì)于 IO的消耗會(huì)比較高,寫(xiě)入的性能其實(shí)也會(huì)比較差。
針對(duì)這種情況,考慮使用Memory Table,讓寫(xiě)不直接落盤(pán),每一次寫(xiě)先寫(xiě)到Memory Table中,攢到一定的批次或者到達(dá)一定的時(shí)間之后再一次性刷盤(pán)。
當(dāng)數(shù)據(jù)寫(xiě)入Memory Table之后,就可以對(duì)外提供查詢服務(wù)了,因?yàn)?memory table 是跟 Kafka 綁定的,在同一個(gè)下的內(nèi)是唯一的。當(dāng)查詢來(lái)了之后,只需要路由到對(duì)應(yīng)的消費(fèi)節(jié)點(diǎn)下 the Memory Table,就能保證了數(shù)據(jù)查詢的一致性。

云原生架構(gòu)增強(qiáng)
分布式架構(gòu)的痛點(diǎn)在于:
1.節(jié)點(diǎn)故障: 字節(jié)的集群規(guī)模較大,每周/每天會(huì)遇到節(jié)點(diǎn)故障的問(wèn)題,需要進(jìn)行節(jié)點(diǎn)替換,是一個(gè)比較大的負(fù)擔(dān)。
2.讀寫(xiě)沖突問(wèn)題: 隨著集群的接入的業(yè)務(wù)越來(lái)越多,數(shù)據(jù)量越來(lái)越大的情況下,每一個(gè)節(jié)點(diǎn)同時(shí)承擔(dān)著查詢和寫(xiě)入的操作,之間會(huì)有沖突。
3.擴(kuò)容成本: 唯一鍵的場(chǎng)景對(duì)數(shù)據(jù)分布要求非常嚴(yán)格,擴(kuò)容在這種場(chǎng)景下很難支持,因?yàn)閿U(kuò)容之后partition的映射關(guān)系發(fā)生了變化。
云原生架構(gòu)優(yōu)點(diǎn)在于,存算分離、自動(dòng)擴(kuò)容、自動(dòng)容錯(cuò)輕量級(jí)的擴(kuò)縮容等,因?yàn)樵圃С质挛?#xff0c;讓我們可以將消費(fèi)語(yǔ)義增強(qiáng)到exactly once。

在云原生架構(gòu)下的 Kafka 引擎是如何通過(guò)事務(wù)來(lái)實(shí)現(xiàn) exactly once:
事務(wù)保證: 因?yàn)樵圃軜?gòu)有事務(wù)的支持,所以每一輪的消費(fèi)都需要有事物來(lái)保證。因?yàn)?Catalog 的元信息和 Catalog 元信息的交互是在 Server 端進(jìn)行的,所以第一步會(huì)通過(guò) RPC 的請(qǐng)求向 Server 端請(qǐng)求創(chuàng)建消費(fèi)事務(wù),然后客戶端創(chuàng)建正常,創(chuàng)建消費(fèi)事務(wù)之后會(huì)把 transaction ID 給consumer, consumer 拿到這種全聲音 ID 之后就可以開(kāi)始正常地消費(fèi)了。之后它就會(huì)從分配到的 partition 里面不停地消費(fèi)數(shù)據(jù),當(dāng)消費(fèi)到足夠的數(shù)據(jù)量或者消費(fèi)滿足一定的時(shí)間時(shí),它就會(huì)把消費(fèi)的這數(shù)據(jù)轉(zhuǎn)換為對(duì)應(yīng)的 part 文件并dump到存儲(chǔ)層。在 dump 之后,數(shù)據(jù)是不可見(jiàn)的,因?yàn)檫@個(gè)時(shí)候的 transaction 還沒(méi)有提交,所以在第五步的時(shí)候,還是會(huì)通過(guò)一個(gè) RPC 的 call 把剛才 dump 的元信息消費(fèi)的 offseed 提交到 catalog 中。這一步是一個(gè)原子性的提交,也是我們的消費(fèi)語(yǔ)義升級(jí)從 at least once 到 exactly once 的一個(gè)核心關(guān)鍵點(diǎn)
容錯(cuò)保證: 因?yàn)閙anager 和它具體之間的任務(wù)是在不同的節(jié)點(diǎn)上的,所以需要有一定的這種容錯(cuò)機(jī)制。當(dāng)前是讓 manager 和 task 之間保持一種一個(gè)雙向的心跳機(jī)制來(lái)保證,比如說(shuō)manager每隔 10 秒鐘會(huì)去探活一次,看看當(dāng)前任務(wù)是否正常運(yùn)行,如果沒(méi)有在正常運(yùn)行,它就會(huì)重新拉起一個(gè)新的task。而對(duì)于 task 來(lái)說(shuō),它每一次的消費(fèi)都會(huì)有兩次的 RPC call 和 Server 端做交互,這兩次的 RPC 交互都會(huì)向 manager 去校驗(yàn)自身的有效性,如果校驗(yàn)到自己當(dāng)前是一個(gè)失效的狀態(tài),它就會(huì)把自己 kill 掉,從而保證整個(gè)全局的唯一任務(wù)的運(yùn)行。
Memory Buffer : 與社區(qū)相似,Memory Buffer和底層的存儲(chǔ)表綁定。因?yàn)槎际菍?xiě)入底表的,不僅Kafka的導(dǎo)入可以用,Flink的導(dǎo)入也可以用。memory buffer 的使用場(chǎng)景是高頻的小批量的導(dǎo)入場(chǎng)景,因?yàn)槊恳淮螌?dǎo)入都會(huì)寫(xiě)一個(gè)part,不停地寫(xiě) part 會(huì)對(duì)集群產(chǎn)生壓力。而 ClickHouse 的話,對(duì) ClickHouse 來(lái)說(shuō) part 越多性能越差,所以使用 memory buffer 來(lái)緩存小批量的數(shù)據(jù),到達(dá)一定批次之后再進(jìn)行導(dǎo)入。首先需要有一個(gè)事務(wù)的保證,才能保證導(dǎo)入的完整性和一致性。另外它需要有WAL,因?yàn)槭紫劝褦?shù)據(jù)要先寫(xiě)到 WAL 中,數(shù)據(jù)寫(xiě)入到 WAL 中之后,就認(rèn)為導(dǎo)入成功了,因?yàn)?WAL 本身也是一個(gè)持久化的存儲(chǔ),數(shù)據(jù)寫(xiě)入 WAL 之后,再將數(shù)據(jù)寫(xiě)入到 memory buffer。當(dāng)數(shù)據(jù)寫(xiě)入了 memory buffer 之后就可以對(duì)外提供查詢服務(wù)。

增強(qiáng) Materialzed MySQL 實(shí)現(xiàn)方案
社區(qū)版 Materialzed MySQL 介紹
物化 MySQL 將MySQL的表映射到 ClickHouse 中, ClickHouse 服務(wù)會(huì)讀取binlog,并執(zhí)行 DDL 和 DML 的請(qǐng)求,實(shí)現(xiàn)了這種基于實(shí)現(xiàn)了基于 MySQL binlog 的實(shí)時(shí) CDC 同步。它的架構(gòu)很簡(jiǎn)單,不依賴于數(shù)據(jù)同步工具,使用自身的資源就能將整個(gè) MySQL 的數(shù)據(jù)庫(kù)同步到 ClickHouse中,并且時(shí)效性很好,因?yàn)閷?shí)時(shí)同步的延時(shí)一般在秒級(jí)、毫秒級(jí)到秒級(jí)之間。
社區(qū)版本的這種物化MySQL 在很大程度上去解決了 MySQL 數(shù)據(jù)庫(kù)到 ClickHouse 之間的這種實(shí)時(shí)同步。在實(shí)際業(yè)務(wù)、實(shí)際場(chǎng)景中,遇到不少問(wèn)題:
1.社區(qū)版本的物化MySQL,它是不支持同步到分布式表,也不支持跳過(guò)DDL,缺乏這些功能就很難將數(shù)據(jù)庫(kù)的引擎應(yīng)用到實(shí)際生產(chǎn)中。
2.社區(qū)版本的物化 MySQL 不支持在數(shù)據(jù)同步發(fā)生異常時(shí)進(jìn)行輔助,發(fā)生異常的時(shí)候發(fā)起重新同步的命令,它沒(méi)有同步的日志信息和沒(méi)有同步的狀態(tài)信息,缺少了這些信息會(huì)導(dǎo)致同步發(fā)生異常的時(shí)候,很難在短期內(nèi)把這些任務(wù)重新啟動(dòng)。
基于這些問(wèn)題和痛點(diǎn), ByteHouse在社區(qū)版本的物化 MySQL 的基礎(chǔ)之上做了一些功能增強(qiáng)易用性,降低了運(yùn)維成本,讓數(shù)據(jù)的同步更加穩(wěn)定。

ByteHouse的物化 MySQL 結(jié)合了HaUniqueMergeTree表引擎:結(jié)合這樣的表引擎之后,它就能夠?qū)崿F(xiàn)數(shù)據(jù)的實(shí)時(shí)去重能力,同時(shí)它能夠支持分布式的能力,我們通過(guò)底層的中間的參數(shù)優(yōu)化,比如 include tables、 exclude tables、 SKIP DDL 等等能夠允許用戶自定義同步的表的同步范圍。
通過(guò)下 model 這樣的一個(gè)參數(shù),能夠支持分布式表的同步,然后通過(guò) Rethink 參數(shù)的設(shè)置支持將額外增加的表啟動(dòng)獨(dú)立的數(shù)據(jù)同步任務(wù)去進(jìn)行 CDC 同步,在出現(xiàn)異常的時(shí)候,我們也支持跳過(guò)這種不支持的 DDL 語(yǔ)句。另外,可以通過(guò)系統(tǒng)日志的抓取和展示進(jìn)行可視化的運(yùn)維。

ByteHouse增強(qiáng)Materialzed MySQL核心功能實(shí)現(xiàn)
實(shí)時(shí)去重 / 分布式
社區(qū)版的物化 MySQL 使用的是ReplacingMergeTree,每一個(gè)同步任務(wù)都會(huì)將源端的 MySQL 數(shù)據(jù)庫(kù)同步到 ClickHouse 的某一個(gè)節(jié)點(diǎn)上面,它不支持按照分片邏輯將數(shù)據(jù)分布到所有的節(jié)點(diǎn),也無(wú)法利用 ClickHouse 整個(gè)集群的分布式計(jì)算和存儲(chǔ)能力,所ByteHouse的物化MySQL 支持分布式地同步利用。我們利用HaUniqueMergeTree表引擎,將每張表同步到對(duì)應(yīng)的分布式節(jié)點(diǎn)上,充分利用集群的這種分布式計(jì)算能力,同時(shí)通過(guò)表引擎的實(shí)時(shí) upsert 能力來(lái)實(shí)現(xiàn)快速地去重。

異步 Resync
這里有三個(gè)對(duì)象, SYNC manager是用來(lái)管理主 SYNC 線程和 Resync 線程,然后 SYNC task 和 resync task 各自管理各自的任務(wù)。比如說(shuō)一個(gè) MySQL 的庫(kù)有 100 張表,我們選了 50 張表進(jìn)行同步,所以在同步進(jìn)行過(guò)程中,當(dāng) think task 同步到 binlog 的 position 位置,比如到 1000 的時(shí)候,用戶修改了配置之后,它增加了 30 張表。增加 30 張表的時(shí)候, SYNC manager 就會(huì)啟動(dòng) Resync task 去同步另外 30 張表,那這個(gè)時(shí)候 SYNC task 是繼續(xù)執(zhí)行的;RESYNC task 會(huì)從 position 0 開(kāi)始,它先做全量的同步,然后再做增量的同步。所以當(dāng)?shù)竭_(dá)某一個(gè)階段,比如說(shuō) sync task 跑到了 position 1500 的時(shí)候, resync task 跑到了 position 1490 的時(shí)候,這時(shí) SYNC manager 就會(huì)去判斷兩者的誤差,這個(gè) position 的誤差在一定的閾值之內(nèi),在一定閾值之內(nèi)之后,它會(huì)將 SYNC task 停止1秒鐘,將 RESYNC task 合并到 SYNC task 中。合并成功之后,這 80 張表就都會(huì)通過(guò)SYNC task 繼續(xù)同步,而 RESYNC task 這個(gè)任務(wù)就會(huì)被停止掉。這就是現(xiàn)在 RESYNC task 做了一個(gè)能力實(shí)現(xiàn)。

可視化運(yùn)維
通過(guò)可視化的任務(wù)監(jiān)控和任務(wù)啟停異常的重啟任務(wù)告警這些方式實(shí)現(xiàn)了物化 MySQL 的可視化易用性的極大提升。

案例實(shí)踐與未來(lái)展望
案例一:短視頻直播
該場(chǎng)景下的數(shù)據(jù)是批流一體寫(xiě)入,為了維護(hù)和管理抖音創(chuàng)作者的數(shù)據(jù),并且面向這種業(yè)務(wù)運(yùn)營(yíng)和達(dá)人經(jīng)營(yíng)提供數(shù)據(jù)查詢服務(wù),需要將短視頻和直播的實(shí)時(shí)數(shù)據(jù)和離線數(shù)據(jù)做融合,來(lái)構(gòu)建 B端的數(shù)據(jù)分析。
問(wèn)題: 首先,創(chuàng)作者是唯一的,需要我們進(jìn)行數(shù)據(jù)去重。第二,數(shù)據(jù)源是比較多樣化的,所以它整個(gè)字段超過(guò) 4000 +,是典型的大寬表場(chǎng)景。第三,T+1的數(shù)據(jù),T+1數(shù)據(jù)離線同步后,T+0數(shù)據(jù)要對(duì)它進(jìn)行更新。第四,是對(duì)任何指標(biāo)的實(shí)時(shí)查詢需要秒級(jí)出結(jié)果,這是業(yè)務(wù)面臨的問(wèn)題。
解決方案: 第一,我們采用了自研的 Unique表引擎來(lái)做實(shí)時(shí)的去重,并且能夠讓數(shù)據(jù)在寫(xiě)入時(shí)就可以實(shí)時(shí)去重、實(shí)時(shí)查詢。第二,通過(guò) Kafka 引擎的 memory table 來(lái)實(shí)現(xiàn)大寬表數(shù)據(jù)先緩存,到達(dá)了一定的批次之后再集中刷盤(pán)。通過(guò)對(duì) Byte house 的優(yōu)化方案有效地解決了碎片化、IO負(fù)載高的問(wèn)題,能夠支持 10 億+創(chuàng)作數(shù)據(jù)實(shí)時(shí)寫(xiě)入和實(shí)時(shí)查詢。

案例二:營(yíng)銷(xiāo)實(shí)時(shí)數(shù)據(jù)的監(jiān)控
營(yíng)銷(xiāo)實(shí)時(shí)監(jiān)控是對(duì)業(yè)務(wù)營(yíng)銷(xiāo)活動(dòng)效果的實(shí)時(shí)查詢和實(shí)時(shí)回收,希望通過(guò)這種實(shí)時(shí)回收來(lái)動(dòng)態(tài)調(diào)整獎(jiǎng)品的實(shí)時(shí)發(fā)放策略來(lái)做到最終的 IOR、ROI 的提升。這就要求數(shù)據(jù)實(shí)時(shí)寫(xiě)入、落盤(pán)延時(shí)要非常低,對(duì)數(shù)據(jù)處理的性能也有很高的要求。在數(shù)據(jù)傳送上面需要保證數(shù)據(jù)傳輸?shù)奈ㄒ恍?#xff0c;以保證獎(jiǎng)品不會(huì)重復(fù)發(fā)放,也不會(huì)丟失。
解決方案: 我們?cè)诜桨干鲜紫炔捎米匝械腒afka 引擎來(lái)支持流式數(shù)據(jù)的實(shí)時(shí)寫(xiě)入,實(shí)時(shí)寫(xiě)入便實(shí)時(shí)入庫(kù)。通過(guò) low-level 的這種消費(fèi)來(lái)保證數(shù)據(jù)的有序分片,再通過(guò)增強(qiáng)的消費(fèi)語(yǔ)義 exactly once 保證數(shù)據(jù)的精準(zhǔn)一次傳輸。最后我們通過(guò)自研的Unique引擎來(lái)實(shí)現(xiàn)實(shí)時(shí)的這種 upsert 的語(yǔ)義,讓數(shù)據(jù)實(shí)時(shí)寫(xiě)入、實(shí)時(shí)去重。通過(guò) ByteHouse 方案的優(yōu)化,營(yíng)銷(xiāo)業(yè)務(wù)的每一個(gè)節(jié)點(diǎn)的實(shí)時(shí)性能達(dá)到了 30 MB/s/node,分析性能也是在秒級(jí)的延時(shí),讓運(yùn)營(yíng)人員能根據(jù)不同用戶群,實(shí)時(shí)發(fā)放獎(jiǎng)勵(lì),并秒級(jí)地監(jiān)控獎(jiǎng)品發(fā)放的進(jìn)展,從而調(diào)整獎(jiǎng)品的發(fā)放策略。

案例三:游戲廣告的數(shù)據(jù)分析
游戲廣告數(shù)據(jù)分析是在廣告業(yè)務(wù)中會(huì)做一些人群圈選、廣告投放、效果反饋等投放策略,用戶行為預(yù)測(cè)這些全流程的統(tǒng)計(jì)和監(jiān)控來(lái)實(shí)現(xiàn)廣告營(yíng)銷(xiāo)過(guò)程的數(shù)字化,提升整個(gè)廣告游戲投放的 ROI 。
問(wèn)題: 業(yè)務(wù)數(shù)據(jù)和日志數(shù)據(jù)要求實(shí)時(shí)寫(xiě)入、實(shí)時(shí)去重,由于體量比較大,所以寫(xiě)入壓力和查詢壓力都比較大。
解決方案: 首先使用 Kafka 引擎來(lái)支持流式數(shù)據(jù)寫(xiě)入,通過(guò) low level 消費(fèi)模式保障數(shù)據(jù)的有序分片,再通過(guò) Unique引擎來(lái)實(shí)現(xiàn)數(shù)據(jù)的唯一性,并且實(shí)時(shí)地去重。在業(yè)務(wù)數(shù)據(jù)方面,我們使用物化MySQL來(lái)保障業(yè)務(wù)數(shù)據(jù)從 MySQL 到 ByteHouse 之間能夠?qū)崟r(shí)同步。最后使用自研的查詢優(yōu)化器來(lái)優(yōu)化查詢性能,通過(guò)ByteHouse 的優(yōu)化之后,廣告效果分析從原來(lái)的小時(shí)級(jí)提升到了現(xiàn)在的秒級(jí)延時(shí)數(shù)據(jù)查詢的性能,單線程同步 20+MB/s ,并且整個(gè)查詢性能提升了 3 倍,用戶的收益和體驗(yàn)得到了明顯的改善。

未來(lái)戰(zhàn)略:全鏈路和一體化
端到端。從語(yǔ)法轉(zhuǎn)換、數(shù)據(jù)遷移,到數(shù)據(jù)校驗(yàn),形成完整的全鏈路方案。
一體化。通過(guò)DES的邏輯復(fù)制能力實(shí)現(xiàn) TP / AP 的一體化,同時(shí)實(shí)現(xiàn)數(shù)據(jù)倉(cāng)庫(kù)和數(shù)據(jù)集市的一體化。
資源隔離。支持用戶使用共享資源池或者數(shù)據(jù)庫(kù)引擎來(lái)進(jìn)行數(shù)據(jù)的同步,也支持用戶通過(guò)獨(dú)享的資源池來(lái)進(jìn)行高效數(shù)據(jù)同步。
多引擎方案。除了基于 ClickHouse 引擎的基礎(chǔ)能力,我們也會(huì)去探索更多的底層引擎能力來(lái)增強(qiáng)ByteHouse的數(shù)據(jù)同步。