一、OLAP在唯品會(huì)演進(jìn)迭代
1.1 Presto/Kylin在唯品會(huì)的使用
Presto作為當(dāng)前唯品會(huì)OLAP主力軍,經(jīng)歷了數(shù)次架構(gòu)和使用方式演進(jìn)。當(dāng)前階段,我們Presto共有物理機(jī)500多臺(tái),服務(wù)于20多個(gè)線(xiàn)上業(yè)務(wù),日均查詢(xún)高峰可達(dá)500萬(wàn)次,每天讀取和處理接近3PB數(shù)據(jù)。
在業(yè)務(wù)應(yīng)用上Presto從最初只有魔方、自助分析兩個(gè)業(yè)務(wù)使用,發(fā)展到現(xiàn)在接入20個(gè)業(yè)務(wù),基于業(yè)務(wù)使用實(shí)踐,每個(gè)階段我們對(duì)Presto都有相應(yīng)改進(jìn)。
1.1.1集群統(tǒng)一接入管控
定制化Presto管理工具Spider/Nebula(新版),做到多集群路由,集群HA,負(fù)載均衡,查詢(xún)回溯,全鏈路監(jiān)控等。
我們定制了Presto Server和Client。用自研管理工具Spider/Nebula從Presto暴露的API和系統(tǒng)表里獲取到節(jié)點(diǎn)和查詢(xún)信息,一方面將查詢(xún)落入mysql,通過(guò)etl-job落入hive便于存儲(chǔ)和分析;一方面根據(jù)集群查詢(xún)數(shù)和節(jié)點(diǎn)信息來(lái)給該集群打分。用戶(hù)可以事先在Spider里給Presto集群劃分group,同一個(gè)group的集群coordinator信息被我們統(tǒng)一保存到zk中。這樣用戶(hù)查詢(xún)presto時(shí),在本地調(diào)用定制presto-client或者presto-jdbc來(lái)連接presto集群之際,就會(huì)通過(guò)zk獲取當(dāng)前業(yè)務(wù)所屬group中打分最低的集群(負(fù)載最低)進(jìn)行連接查詢(xún)。當(dāng)有集群處于維護(hù)狀態(tài)或者連不通時(shí),路由會(huì)自動(dòng)感知摘除這個(gè)節(jié)點(diǎn)的coordinator信息,這樣查詢(xún)將不會(huì)打到這個(gè)集群上,同步保障了Presto的HA。
1.1.2 Presto容器化
Presto上云接入K8S,可以智能擴(kuò)縮容Presto集群,做到資源合理調(diào)度、智能部署等功能。標(biāo)準(zhǔn)配置每個(gè)Presto的Worker 40vCPU/110G內(nèi)存,每個(gè)集群100個(gè)Worker節(jié)點(diǎn)。
500多臺(tái)物理機(jī)分批改造,讓用戶(hù)業(yè)務(wù)無(wú)感,隨之帶來(lái)的提升也很明顯。
★后臺(tái)presto-k8s集群是配置完全相同、算力相同的集群。用戶(hù)的業(yè)務(wù)只需要在client里配置一個(gè)虛擬IP,我們就會(huì)使用路由功能為他分配一到N個(gè)集群。不同業(yè)務(wù)允許交叉和隔離。這種操作完全是動(dòng)態(tài)的,不需要重啟集群,算力也是均衡的。
★在查詢(xún)比較集中,大促、流量比較大時(shí),我們可以快速合并集群,動(dòng)態(tài)刪除部分集群,讓其他集群快速擴(kuò)容worker。用戶(hù)在使用過(guò)程中是無(wú)感知的。
★部署Presto on k8s變得十分便捷。我們只需要在k8s管理平臺(tái)上點(diǎn)擊頁(yè)面,填入集群名稱(chēng),幾分鐘內(nèi)就可以拉起一個(gè)標(biāo)準(zhǔn)化的Presto集群,域名跟集群名有規(guī)則對(duì)應(yīng)。這樣刪除集群、新增集群代價(jià)非常小。
★由于網(wǎng)絡(luò)、內(nèi)存、反親和性部署使得整個(gè)Presto-k8s集群處于相對(duì)均衡穩(wěn)定狀態(tài),集群穩(wěn)定性得到了大大的提升。我們觀(guān)察了物理機(jī)的CPU、內(nèi)存等指標(biāo),機(jī)器變得飽和且穩(wěn)定。
★安裝包和配置分離、k8s自動(dòng)部署模式,使得所有集群的升級(jí)變得簡(jiǎn)單、快速、易操作。
自此,唯品會(huì)Presto走上了集群全面容器化的階段。
1.2 Clickhouse的引入
隨著業(yè)務(wù)對(duì)于OLAP要求越來(lái)越高,部分業(yè)務(wù)場(chǎng)景Presto和Kylin無(wú)法滿(mǎn)足其需求。比如百億JOIN百億(Local Join)的低延遲實(shí)時(shí)數(shù)據(jù)場(chǎng)景和對(duì)中等qps的查詢(xún)平均響應(yīng)時(shí)間要求低于1秒的OLAP使用場(chǎng)景等,我們把目光轉(zhuǎn)向”大家都說(shuō)快“的Clickhouse。
Presto | Kylin | Clickhouse | |
---|---|---|---|
數(shù)據(jù)存儲(chǔ) | 本身不存儲(chǔ),依賴(lài)catalog的存儲(chǔ) | 中間文件存儲(chǔ)在HDFS,結(jié)果文件存儲(chǔ)在HBASE | Zookeeper保存元數(shù)據(jù),數(shù)據(jù)存儲(chǔ)在本地,且會(huì)壓縮 |
查詢(xún) | 比較均衡,適配各種ADHOC場(chǎng)景 | 查詢(xún)結(jié)果數(shù)據(jù)比Presto往往要快,得益于預(yù)計(jì)算 | 比Presto快的ADHOC能力,但是join多分布式表能力較弱 |
數(shù)據(jù)讀寫(xiě) | 借助connector來(lái)完成讀寫(xiě),不支持更新 | 讀寫(xiě)Hbase。中間數(shù)據(jù)會(huì)讀寫(xiě)Hdfs | 支持讀寫(xiě),不能更新,有偽更新 |
維護(hù) | 我們自己開(kāi)發(fā)了Presto運(yùn)維工具,且額外依賴(lài)了redis和Zookeeper | 維護(hù)Kylin本身和一套Hbase | 額外維護(hù)Zookeeper |
應(yīng)用場(chǎng)景 | 應(yīng)對(duì)各種Adhoc和自助取數(shù),ETL場(chǎng)景,應(yīng)用最廣 | 自助分析里,Presto解決不了的超大查詢(xún) | 百億級(jí)數(shù)量級(jí)下 大寬表聚合、復(fù)雜查詢(xún)等 |
1.3 ClickHouse在業(yè)務(wù)的部署架構(gòu)和模式
我們?cè)谑褂弥邪l(fā)現(xiàn) Clickhouse有如下優(yōu)勢(shì):
★大寬表查詢(xún)性能優(yōu)異,其主要分析都是大寬表的sql聚合。ClickHouse整個(gè)聚合耗時(shí)都非常小,性能好,并且具有量級(jí)提升。
★單表性能分析以及分區(qū)對(duì)其的join計(jì)算都能取得很好的性能優(yōu)勢(shì)。比如百億數(shù)量級(jí)join幾十億數(shù)量級(jí)的大表關(guān)聯(lián)大表的場(chǎng)景,在24C 128G * 10 shard (2副本) 通過(guò)優(yōu)化取得了10s左右的查詢(xún)性能。
目前我們支持的業(yè)務(wù)主要是實(shí)驗(yàn)平臺(tái)、agamotto監(jiān)控、OLAP 查詢(xún)?nèi)罩尽?/p>
二、實(shí)時(shí)數(shù)據(jù)入ClickHouse
2.1 Flink寫(xiě)ClickHouse
2.1.1 Flink寫(xiě)入分布式表
最初我們使用分布式表寫(xiě)入是為了快速驗(yàn)證一些功能和性能,比如分布式表在建表時(shí)支持sharding_key和數(shù)據(jù)寫(xiě)入支持各種策略,分布式表的建表示例:
Distributed(logs, default, hits[, sharding_key[, policy_name]])
為了實(shí)現(xiàn)join時(shí)完全local join,我們?cè)趯?xiě)入分布式表時(shí),sharding_key就是join的column,policy_name設(shè)定為murmurHash3_64(sharding_key),實(shí)現(xiàn)起來(lái)相對(duì)比較簡(jiǎn)單。為了支持寫(xiě)入HA ,我們配置連接的URL有多個(gè),如果某個(gè)host出現(xiàn)連接,會(huì)重連另外一個(gè)host。下面附上一些實(shí)踐小經(jīng)驗(yàn):
★ck 適合小并發(fā) 大批次寫(xiě)入,否則會(huì)報(bào)錯(cuò):典型的merge速度跟不上寫(xiě)入;
★本地表url填寫(xiě)的地址只需要一個(gè)(實(shí)際會(huì)根據(jù)這個(gè)地址查詢(xún)集群分片信息,根據(jù)hash策略做哈希),分布式表可以一個(gè)或多個(gè);
★如果是本地表寫(xiě)入推薦基于字段的一致性哈希,可以相對(duì)做到數(shù)據(jù)均衡,如果是分布式表寫(xiě)入推薦至少2個(gè)節(jié)點(diǎn)的分布式表寫(xiě)入 。
整體寫(xiě)入架構(gòu)如下圖所示:
2.1.2 Flink寫(xiě)入本地表
Flink寫(xiě)入分布式表能完成功能邏輯,但在性能和可靠性上還是略微有差異:
★由于數(shù)據(jù)是由ClickHouse節(jié)點(diǎn)做二次分發(fā),會(huì)占用寫(xiě)入分布式表節(jié)點(diǎn)比較多的內(nèi)存;
★集群節(jié)點(diǎn)異常后,導(dǎo)致分布式表無(wú)法準(zhǔn)確把數(shù)據(jù)分發(fā)到新節(jié)點(diǎn)。
基于以上問(wèn)題,我們?cè)贔link的ClickHouse Connector端做了相應(yīng)改造,支持寫(xiě)入本地表的相關(guān)功能。主要流程如下:
★根據(jù)庫(kù)名和表名查system.tables獲取表的engine信息(SELECT engine_full FROM system.tables WHERE database = ? AND name = ? )
★解析engine信息,獲取集群名、本地表名;
★根據(jù)集群名,查system.clusters獲取集群分片節(jié)點(diǎn)信息 (SELECT shard_num, host_address FROM system.clusters WHERE cluster = ?),得到TreeMap<shard_num, shard host list>這樣的配置信息
★根據(jù)shard配置信息,初始化List<ClickHouseShardExecutor>, ClickHouseShardExecutor 內(nèi)部初始化時(shí)會(huì)隨機(jī)shard group里的url來(lái)連接;負(fù)責(zé)將flink內(nèi)部的數(shù)據(jù)結(jié)構(gòu)RowData 添加到batch buffer里,并根據(jù)sink.buffer-flush.max-rows buffer大小和sink.buffer-flush.interval flush間隔來(lái)觸發(fā)flush,將一批數(shù)據(jù)真正的sink 到 ClickHouse Server端。
★當(dāng)shard內(nèi),個(gè)別節(jié)點(diǎn)負(fù)載比較高或查詢(xún)有熱點(diǎn)時(shí),會(huì)導(dǎo)致batch flush失敗,這個(gè)時(shí)候需要做異常時(shí)重連操作。
究竟某條數(shù)據(jù)過(guò)來(lái)sink 到哪個(gè)shard,我們定義了RowData 到ClickHouseShardExecutor 的分區(qū)接口,并實(shí)現(xiàn)了3種分區(qū)策略round-robin輪訓(xùn) 、random隨機(jī)分區(qū)、field-hash基于字段的一致性哈希等策略,通過(guò) sink.partition-column 參數(shù)指定分區(qū)字段,保證相同分區(qū)字段哈希到同shard內(nèi)。整體架構(gòu)如下圖所示:
Flink數(shù)據(jù)寫(xiě)入的時(shí)序圖可以參考如下所示:
三、實(shí)驗(yàn)平臺(tái)數(shù)據(jù)自助分析
3.1 實(shí)驗(yàn)平臺(tái)簡(jiǎn)要介紹
唯品會(huì)實(shí)驗(yàn)平臺(tái)是通過(guò)配置多維度分析和下鉆分析,提供海量數(shù)據(jù)的A/B-test實(shí)驗(yàn)效果分析的一體化平臺(tái)。一個(gè)實(shí)驗(yàn)是由一股流量(比如用戶(hù)請(qǐng)求)和在這股流量上進(jìn)行的相對(duì)對(duì)比實(shí)驗(yàn)的修改組成。實(shí)驗(yàn)平臺(tái)對(duì)于海量數(shù)據(jù)查詢(xún)有著低延遲、低響應(yīng)、超大規(guī)模數(shù)據(jù)(百億級(jí))的需求。
3.2 Flink+ClickHouse整體架構(gòu)
3.2.1 FLINK SQL + CK 在實(shí)驗(yàn)平臺(tái)業(yè)務(wù)場(chǎng)景
我們實(shí)現(xiàn)了flink sql redis connector,支持redis的sink 、source維表關(guān)聯(lián)等操作,可以很方便的讀寫(xiě)redis,實(shí)現(xiàn)維表關(guān)聯(lián),維表關(guān)聯(lián)內(nèi)可配置cache ,極大提高應(yīng)用的TPS。通過(guò)FLINK SQL 實(shí)現(xiàn)實(shí)時(shí)數(shù)據(jù)流的pipeline,最終將大寬表sink到CK 里,并按照某個(gè)字段粒度做murmurHash3_64 存儲(chǔ),保證相同用戶(hù)的數(shù)據(jù)都存在同一shard 節(jié)點(diǎn)組內(nèi)。
3.2.2 ClickHouse百億級(jí)數(shù)據(jù)join的解決方案
在實(shí)際應(yīng)用場(chǎng)景中,我們發(fā)現(xiàn)一些流量的特定場(chǎng)景。我們需要拿一天的用戶(hù)流量點(diǎn)擊情況,來(lái)join A/B TEST的日志,用以匹配實(shí)驗(yàn)和人群的關(guān)系。這就給我們帶來(lái)了很大挑戰(zhàn),兩張大分布式表join出來(lái)的性能也非常不理想。
分桶join字段
在這種情況下,我們用了類(lèi)似于分桶概念。首先把左表和右表join的字段,建表時(shí)用hash來(lái)落到不同的機(jī)器節(jié)點(diǎn),murmurHash3_64(mid)。
如果寫(xiě)入分布式表,在建表時(shí)指定murmurHash3_64字段,如果是寫(xiě)本地表,在flink寫(xiě)入段路由策略里加入murmurHash3_64策略即可。
在查詢(xún)時(shí),使用分布式表join本地表,來(lái)達(dá)到想要的效果。
這樣分桶后JOIN的結(jié)果,是等于分布式表JOIN分布式表,且處理的數(shù)據(jù)量,只有總數(shù)據(jù)量/(集群機(jī)器數(shù)/副本數(shù))。
在寫(xiě)SQL的時(shí)候,我們還遇到一個(gè)坑,即在左表JOIN右表的過(guò)程中,如果左表是子查詢(xún),則分布式規(guī)則不生效,查詢(xún)出的結(jié)果也遠(yuǎn)遠(yuǎn)小于預(yù)期值,等于本地表JOIN本地表。右表是子查詢(xún)則沒(méi)有關(guān)系,因?yàn)橛冶肀緛?lái)就是本地表,對(duì)分布式?jīng)]有要求。
如圖所示:
3.3. 增量數(shù)據(jù)更新場(chǎng)景
數(shù)據(jù)去重方案比較
訂單類(lèi)數(shù)據(jù)需要像寫(xiě)入kudu一樣,做去重,由于流量數(shù)據(jù)都實(shí)時(shí)寫(xiě)入數(shù)據(jù),為了訂單數(shù)據(jù)和流量數(shù)據(jù)做join,就需要對(duì)訂單數(shù)據(jù)做去重,由于訂單數(shù)據(jù)是有生命周期的,從產(chǎn)生之后,會(huì)不停的update ,下面討論基于CK各種MergeTree engine的去重方案優(yōu)缺點(diǎn)。對(duì)于實(shí)驗(yàn)平臺(tái)的場(chǎng)景,需要選用一種方案,既能夠?qū)崟r(shí)去重,又要保證查詢(xún)歷史數(shù)據(jù)的結(jié)果要固定下來(lái),又不能影響歸因準(zhǔn)確率,不能忽大忽小,避免對(duì)用戶(hù)產(chǎn)生困惑。
方案 | 優(yōu)點(diǎn) | 缺點(diǎn) | 歸因準(zhǔn)確率 | 查詢(xún)結(jié)果穩(wěn)定性(是否存在忽大忽小的情況) | 查詢(xún)性能 |
---|---|---|---|---|---|
ClickHouse ReplacingMergeTree | 寫(xiě)入快 | 數(shù)據(jù)一致性得不到保證,無(wú)法去重 | 低 | 不穩(wěn)定 | 正常 |
ClickHouse ReplicatedReplacingMergeTree | 可以去重,可以u(píng)pdate,去重延遲低 | merge時(shí)效性低,mid變化的場(chǎng)景無(wú)法merge | 正常 | 穩(wěn)定 | 正常 |
ClickHouse remote表 | 數(shù)據(jù)一致性得到保證 | 存在單節(jié)點(diǎn)寫(xiě)入可靠性問(wèn)題,查詢(xún)復(fù)雜需要先到指定節(jié)點(diǎn)拉數(shù)據(jù)再計(jì)算,不能local join,查詢(xún)僅限于右表 | 正常 | 穩(wěn)定 | 正常 |
flink row_number 去重 + ReplicatedMergeTree |
規(guī)避去重問(wèn)題,也規(guī)避mid hash變化的情況,數(shù)據(jù)一致性得到保證 | 數(shù)據(jù)不會(huì)update | 正常 | 穩(wěn)定 | 正常 |
去重方案總結(jié):a.ReplacingMergeTree 數(shù)據(jù)無(wú)法merge,忽大忽小,不能用。b.ReplicatedReplacingMergeTree 可以做去重,對(duì)hash字段不變化的情況下適合。c. remote表 查詢(xún)復(fù)雜,對(duì)性能有影響,存在副本的可靠性問(wèn)題。d.flink方案規(guī)避去重 和hash字段變化的問(wèn)題。
3.4 . Flink寫(xiě)入端遇到的問(wèn)題及優(yōu)化
問(wèn)題 1:Too many parts (328). Merges are processing significantly slower than inserts.
原因:剛開(kāi)始使用clickhouse的時(shí)候都有遇到過(guò)該異常,出現(xiàn)異常的原因是因?yàn)镸ergeTree的merge的速度跟不上目錄生成的速度, 數(shù)據(jù)目錄越來(lái)越多就會(huì)拋出這個(gè)異常, 所以一般情況下遇到這個(gè)異常,降低一下插入頻次就可以。
解決:
1. 服務(wù)端參數(shù)調(diào)整,將parts_to_throw_insert參數(shù)調(diào)大值10000,默認(rèn)值300 對(duì)我們大流量的應(yīng)用場(chǎng)景來(lái)說(shuō)較小。
2. 客戶(hù)端參數(shù)調(diào)整,調(diào)小ck sink 并行度 小并發(fā) 大批次寫(xiě)入。小并發(fā),我們通過(guò)修改執(zhí)行計(jì)劃調(diào)整flink 算子并行度,如下圖kafka source的并行度=72 ck sink并行度=24 大批次,例如調(diào)整connector參數(shù) 'sink.buffer-flush.max-rows' = '200000','sink.buffer-flush.interval' = '60s' 20W條記錄或60s產(chǎn)生一個(gè)batch批量寫(xiě)入CK
3.分區(qū)時(shí)間字段event_time選擇單調(diào)遞增的時(shí)間,流量數(shù)據(jù)選擇nginx日志時(shí)間 time_local,曝光數(shù)據(jù)不適合選擇忽大忽小的activity_starttime ,訂單數(shù)據(jù)選擇add_time創(chuàng)建時(shí)間。
問(wèn)題2:Unexpected NULL value of not Nullable type Int64
原因:ck建表時(shí)如果去掉nullable限制,插入時(shí),就必須給一個(gè)確定的值,否則會(huì)flush時(shí)執(zhí)行失敗,影響flink sql job穩(wěn)定性。
解決:
1. ck建表時(shí)每個(gè)字段加上默認(rèn)值,或建表時(shí)加上Nullable 約束(不建議,但是主要這種約束不要太多,主要會(huì)占用過(guò)多的存儲(chǔ)空間,也會(huì)降低了查詢(xún)效率)。
2.flink sql在處理數(shù)據(jù)時(shí),加上coalesce 空值處理函數(shù)。
四、ClickHouse查詢(xún)優(yōu)化
4.1.schema 定義優(yōu)化
CREATE TABLE goods_click_app_h5_ck_hm on cluster ck_cluster (`goods_id` Int64 default -9999,`app_version` String default '-9999',....`dt` Date,`exp_page_id` Int32 default -9999)ENGINE = ReplicatedMergeTree('/clickhouse/tables/{layer}-{shard}/goods_click_app_h5_ck_hm', '{replica}')PARTITION BY (dt, exp_page_id)ORDER BY (activity_type)TTL dt + INTERVAL 32 DAYSETTINGS index_granularity = 8192
① 選擇有副本的merge引擎
② 按dt作為分區(qū),分區(qū)內(nèi)的part 文件進(jìn)行異步合并
③ 按照字段order by 排序,提升查詢(xún)性能
④ 設(shè)置TTL過(guò)期時(shí)間
⑤ index_granularity 設(shè)置索引粒度為8192行一個(gè)查找單元
4.2.常用參數(shù)調(diào)整
此外,我們?cè)诖鎯?chǔ)策略里設(shè)置了冷熱數(shù)據(jù)多盤(pán)分離,極大提高熱數(shù)據(jù)的讀寫(xiě)速度。
五、物化視圖
5.1.物化視圖對(duì)常用維度組合進(jìn)行加速
使用ReplicatedSummingMergeTree引擎,相同的數(shù)據(jù)長(zhǎng)度集合,物化視圖和明細(xì)表查詢(xún)效率對(duì)比(相差將近10-100倍)。
物化視圖的創(chuàng)建
CREATE MATERIALIZED VIEW vip_sirius.multi_data_1000445_491_local ON cluster ck_cluster( date Date , `timestamp` UInt32 , `network_fail_total` Nullable(Int64) , `isp` String default '-null' , `pv_total` Nullable(Int64), `service_success_total` Nullable(Int64), `response_t_total` Nullable(Float64), `response_t_count_total` Nullable(Int64), `business_success_total` Nullable(Int64), `time_cnt_100` Nullable(Int64), `time_cnt_200` Nullable(Int64), `time_cnt_500` Nullable(Int64), `time_cnt_5000` Nullable(Int64), `time_cnt_more_5000` Nullable(Int64))ENGINE =ReplicatedSummingMergeTree('/clickhouse/tables/{layer}-{shard}/multi_data_1000445_491_local', '{replica}')PARTITION BY dateORDER BY (timestamp,isp)TTL date + toIntervalDay(14)SETTINGS index_granularity = 8192,storage_policy = 'hotdata'AS select CAST(timestamp AS Date) AS date,timestamp , sum(network_fail_total) AS network_fail_total, `isp` , sum(pv_total) AS pv_total, sum(service_success_total) AS service_success_total, sum(response_t_total) AS response_t_total, sum(response_t_count_total) AS response_t_count_total, sum(business_success_total) AS business_success_total, sum(time_cnt_100) AS time_cnt_100, sum(time_cnt_200) AS time_cnt_200, sum(time_cnt_500) AS time_cnt_500, sum(time_cnt_5000) AS time_cnt_5000, sum(time_cnt_more_5000) AS time_cnt_more_5000FROM vip_sirius.multi_data_1000445_localGROUP BY timestamp ,isp Distributed table:CREATE TABLE vip_sirius.multi_data_1000445_491ON cluster ck_cluster AS vip_sirius.multi_data_1000445_491_localENGINE = Distributed('ck_cluster','vip_sirius','multi_data_1000445_491_local',rand())
查詢(xún)明細(xì)表
語(yǔ)句:
select sum(pv_total),toDateTime(timestamp) from multi_data_1000445 where date>='2021-02-10' and date<='2021-03-03' group by timestamp order by timestamp desc;
查詢(xún)物化視圖
語(yǔ)句:
select sum(pv_total),toDateTime(timestamp) from multi_data_1000445_491 where date>='2021-02-10' and date<='2021-03-03' group by timestamp order by timestamp desc ;
5.2 物化視圖的問(wèn)題
我們?cè)谑褂梦锘晥D的過(guò)程中,也遇到一些問(wèn)題。比如:
1、物化視圖維度比較多的時(shí)候,生成的結(jié)果表也會(huì)指數(shù)級(jí)增加。我們這些表最多的一個(gè)庫(kù),有著1500多張計(jì)算各種維度的物化視圖,且無(wú)法進(jìn)行表級(jí)合并。這樣在管理、監(jiān)控表的時(shí)候,帶來(lái)一些麻煩。
2、物化視圖維度增多的時(shí)候,寫(xiě)入數(shù)據(jù)將會(huì)帶來(lái)不小的消耗,在CPU,內(nèi)存等層面都會(huì)有更多的消耗,這樣在分配集群和角色資源的時(shí)候,會(huì)擾亂原有的分配計(jì)劃。
總而言之,物化視圖是一把雙刃劍。在帶來(lái)速度加速效果明顯的同時(shí),也會(huì)帶來(lái)資源、管理上的一些弊端,用戶(hù)使用的時(shí)候要把握好這些優(yōu)缺點(diǎn)。
六、展望
6.1 ClickHouse和Spark/Presto融合
HyperLogLog是大數(shù)據(jù)分析常用的去重計(jì)算分析方法,在我們之前的應(yīng)用中已經(jīng)打通了Spark,Presto的HyperLogLog對(duì)象,即在一種引擎里生產(chǎn)的HyperLogLog對(duì)象,在其他引擎均可以解析、計(jì)算與分析。
未來(lái)我們會(huì)打通Clickhouse的HyperLogLog的數(shù)據(jù)對(duì)象,將C++和JAVA做統(tǒng)一序列化和反序列化。
最終達(dá)到在hadoop中通過(guò)Spark和Presto等引擎ETL出的HyperLogLog,導(dǎo)入Clickhouse也可以直接用Clickhouse的語(yǔ)法查出。DWS/ADS層可以共享數(shù)據(jù),使得ClickHouse在A(yíng)DS層數(shù)據(jù)可以加速。
6.2 業(yè)務(wù)使用
后續(xù)我們有push效果分析,廣告投入效果等應(yīng)用場(chǎng)景,陸陸續(xù)續(xù)接入的Clickhouse。
我們也在探索使用RoaringBitmap來(lái)進(jìn)行字段長(zhǎng)度不一的 user_id,push_id等各種ID的精確去重、留存分析等。
RoaringBitmap:http://roaringbitmap.org/
6.3 ClickHouse底層架構(gòu)迭代演進(jìn)
隨著業(yè)務(wù)的推進(jìn)和發(fā)展,我們之后會(huì)通過(guò)以下幾個(gè)方向,繼續(xù)優(yōu)化Clickhouse在唯品會(huì)的推進(jìn)和使用。
6.3.1 存算分離
我們都知道Clickhouse是自帶本地化存儲(chǔ)的OLAP引擎,本地化存儲(chǔ)在海量數(shù)據(jù)請(qǐng)求的情況下,會(huì)有I/O速度受限,擴(kuò)容復(fù)雜(需修改clickhouse的存儲(chǔ)策略),不能按需自動(dòng)擴(kuò)縮容,Clickhouse不好上AI云平臺(tái)等諸多限制。
所以我們有計(jì)劃將這部分存儲(chǔ)打到云上,實(shí)現(xiàn)存算分離,可以做到用網(wǎng)絡(luò)的傳輸?shù)母咚俾蚀蚱票镜豂/O的讀寫(xiě)瓶頸,按照需求自動(dòng)擴(kuò)縮容云端存儲(chǔ),將Clickhouse上到我們自己的AI云平臺(tái)便于管理。
我們將會(huì)從修改存儲(chǔ)策略接口代碼,多種云存儲(chǔ)或者分布式存儲(chǔ)來(lái)對(duì)數(shù)據(jù)進(jìn)行分類(lèi),不同熱度、容量的數(shù)據(jù)對(duì)應(yīng)不同的存儲(chǔ)策略。
6.3.2 寫(xiě)入優(yōu)化
目前我們寫(xiě)入主要是寫(xiě)入分布式表,將來(lái)會(huì)考慮測(cè)試優(yōu)化寫(xiě)入分布式表的性能和hash功能,來(lái)支持更高的寫(xiě)入tps。
6.3.3 接入管控
目前我們屬于Clickhouse業(yè)務(wù)推廣階段,對(duì)Clickhouse使用方管控較少,也沒(méi)做過(guò)多的存儲(chǔ)、計(jì)算、查詢(xún)角色等方面的管控。數(shù)據(jù)安全乃大數(shù)據(jù)重中之重,我們將在接下來(lái)的工作中逐步完善這一塊。
6.3.4 SQL管控
在Clickhouse的新版中,已經(jīng)加入了RBAC的訪(fǎng)問(wèn)控制管理,官方也推薦使用這種方式。
參考:https://clickhouse.tech/docs/en/operations/access-rights(點(diǎn)擊閱讀原文)
我們將會(huì):
1、用default創(chuàng)建一個(gè)root賬戶(hù),作為管理者賬戶(hù)。
2、所有授權(quán)的操作通過(guò)root賬戶(hù)GRANT完成。
3、禁用default用戶(hù)的管理功能。
6.3.5 資源管控
在資源層面,我們會(huì)結(jié)合存算分離,給不同的業(yè)務(wù)分配不同的用戶(hù),不同的用戶(hù)在云平臺(tái)上申請(qǐng)的存儲(chǔ)資源有限。且會(huì)對(duì)每個(gè)用戶(hù)的存儲(chǔ)進(jìn)行價(jià)值計(jì)算。