得物可觀測(cè)平臺(tái)架構(gòu)升級(jí):基于GreptimeDB的全新監(jiān)控體系實(shí)踐
一、摘要
二、部署架構(gòu)
1. GreptimeDB分布式架構(gòu)
2. 透明數(shù)據(jù)緩存
3. 無(wú)畏擴(kuò)縮容
三、GreptimeDB Flow 流計(jì)算實(shí)踐
1. 多級(jí)持續(xù)聚合架構(gòu)
2. UV 近似統(tǒng)計(jì):HyperLogLog
3. 效果與收益
四、最佳實(shí)踐與落地建議
一、摘 要
在前端可觀測(cè)分析場(chǎng)景中,需要實(shí)時(shí)觀測(cè)并處理多地、多環(huán)境的運(yùn)行情況,以保障 Web 應(yīng)用和移動(dòng)端的可用性與性能。傳統(tǒng)方案往往依賴代理 Agent → 消息隊(duì)列 → 流計(jì)算引擎 → OLAP 存儲(chǔ)的多級(jí)架構(gòu),雖然能滿足基本數(shù)據(jù)接入與查詢需求,但面臨以下困難與挑戰(zhàn):
- 分層架構(gòu)的精細(xì)化演進(jìn):
當(dāng)前分層模型在支撐多業(yè)務(wù)場(chǎng)景時(shí),需要為分鐘級(jí)、小時(shí)級(jí)、天級(jí)等不同時(shí)間粒度的數(shù)據(jù)視圖分別構(gòu)建計(jì)算鏈路。這種模式在保障靈活性的同時(shí),可能存在存儲(chǔ)與計(jì)算資源的重復(fù)消耗現(xiàn)象,如何通過(guò)增量計(jì)算或動(dòng)態(tài)視圖技術(shù)實(shí)現(xiàn)"一次計(jì)算多級(jí)復(fù)用",或?qū)⒊蔀樘嵘Y源利用效率的關(guān)鍵突破點(diǎn)。
- 復(fù)雜分析場(chǎng)景的效能平衡:
在應(yīng)對(duì)全量 Join、多維交叉分析等高復(fù)雜度場(chǎng)景時(shí),現(xiàn)有的按量計(jì)費(fèi)機(jī)制與計(jì)算資源調(diào)度策略,可能在高頻業(yè)務(wù)周期(如大促活動(dòng))中面臨成本曲線的非線性增長(zhǎng)挑戰(zhàn)。探索預(yù)計(jì)算加速、智能冷熱分層與彈性資源調(diào)度的深度結(jié)合,或許能進(jìn)一步釋放大規(guī)模分析場(chǎng)景的性價(jià)比潛力。
- 生產(chǎn)環(huán)境的安全加固:
基于 SQL 的敏捷開發(fā)模式在提升數(shù)據(jù)處理效率的同時(shí),也對(duì)企業(yè)級(jí)數(shù)據(jù)資產(chǎn)管理提出了更高要求。通過(guò)強(qiáng)化語(yǔ)法預(yù)校驗(yàn)、分區(qū)保護(hù)機(jī)制、操作審計(jì)追溯等防護(hù)手段,構(gòu)建覆蓋開發(fā)、測(cè)試、發(fā)布全流程的可靠性護(hù)城河,將有效降低誤操作風(fēng)險(xiǎn)并提升數(shù)據(jù)治理成熟度。
本文聚焦將前端可觀測(cè)后端數(shù)據(jù)分析場(chǎng)景演進(jìn)到 GreptimeDB 的實(shí)踐,深入剖析如何利用 GreptimeDB Flow 引擎實(shí)現(xiàn) 10s、1m、10m 等多粒度持續(xù)聚合,結(jié)合HyperLogLog 與 UDDsketch 函數(shù),為前端可觀測(cè)場(chǎng)景提供高性能、低成本且易于運(yùn)維的端到端解決方案。
二、部署架構(gòu)
圖片
為解決前述痛點(diǎn),逐步將時(shí)序/觀測(cè)數(shù)據(jù)場(chǎng)景遷移至 GreptimeDB,并借助其內(nèi)置的Flow引擎(SQL)自動(dòng)維護(hù)秒級(jí)、分鐘級(jí)、小時(shí)級(jí)等多精度下采樣表,可極大簡(jiǎn)化分層建模和物化視圖運(yùn)維。
GreptimeDB分布式架構(gòu)
采用 GreptimeDB 開源的分布式模式,在這種模式下,GreptimeDB 的節(jié)點(diǎn)可以分為如下角色:
圖片
- Frontend:負(fù)責(zé)協(xié)議處理、請(qǐng)求校驗(yàn)和鑒權(quán)、初步查詢優(yōu)化,是一個(gè)無(wú)狀態(tài)節(jié)點(diǎn),可以根據(jù)負(fù)載任意擴(kuò)縮容。
- Datanode:負(fù)責(zé)管理數(shù)據(jù)分片、處理數(shù)據(jù)寫入和持久化以及執(zhí)行具體的查詢。
- Flownode:對(duì)于配置了流計(jì)算任務(wù)的集群,F(xiàn)lownode 負(fù)責(zé)接受 Frontend 鏡像而來(lái)的寫入請(qǐng)求并執(zhí)行流計(jì)算任務(wù)。流計(jì)算的結(jié)果最終會(huì)被寫入到 Datanode 中進(jìn)行持久化。
- Metasrv:GreptimeDB 的控制面組件,負(fù)責(zé)管理集群的元數(shù)據(jù)(如表的分片路由信息等)。Metasrv 本身是無(wú)狀態(tài)的,這里我們采用 PostgreSQL 作為后端存儲(chǔ)。
透明數(shù)據(jù)緩存
GreptimeDB 對(duì)數(shù)據(jù)訪問層進(jìn)行了高度的抽象,負(fù)責(zé)管理數(shù)據(jù)分片的 Datanode 并不需要感知到數(shù)據(jù)文件位于本地磁盤還是對(duì)象存儲(chǔ)。但是考慮到當(dāng)使用對(duì)象存儲(chǔ)時(shí)數(shù)據(jù)文件的訪問延遲會(huì)大大增加,因此 GreptimeDB 設(shè)計(jì)了多層的透明數(shù)據(jù)緩存來(lái)解決此問題。
(GreptimeDB 的緩存結(jié)構(gòu))
GreptimeDB 的緩存結(jié)構(gòu)如上圖所示。從緩存所在位置可以分為磁盤緩存和內(nèi)存緩存兩類:
- 磁盤緩存的數(shù)據(jù)來(lái)源通常是對(duì)象存儲(chǔ),其類似于操作系統(tǒng)的 page cache,只不過(guò) page cache 是利用內(nèi)存加速磁盤數(shù)據(jù)的訪問,而 GreptimeDB 的這部分緩存則是利用磁盤加速對(duì)象存儲(chǔ)的訪問,將頻繁訪問的文件按范圍緩存到磁盤可以實(shí)現(xiàn)更低的查詢延遲,并且能夠智能根據(jù)訪問模式實(shí)現(xiàn)預(yù)?。╬refetch)、IO 合并等優(yōu)化。
- 內(nèi)存緩存除了原始的文件內(nèi)容之外也包括從磁盤/對(duì)象存儲(chǔ)的原始內(nèi)容反序列化出來(lái)的數(shù)據(jù)結(jié)構(gòu),如字段的 min/max,bloomfilter 等等。
而從數(shù)據(jù)類型來(lái)分可以分為結(jié)構(gòu)化和非結(jié)構(gòu)化兩類:
- 非結(jié)構(gòu)化緩存的內(nèi)容通常是文件的二進(jìn)制內(nèi)容,而緩存的 key 則是文件名加上字節(jié)范圍。比如在 flush 的過(guò)程中寫入到對(duì)象存儲(chǔ)的文件往往是大概率很快就會(huì)被查詢的熱數(shù)據(jù),因此可以在本地緩存一份避免查詢請(qǐng)求穿透到對(duì)象存儲(chǔ)。
- 結(jié)構(gòu)化緩存則是文件、索引的內(nèi)容或元數(shù)據(jù)反序列化得到的結(jié)構(gòu)體,這些數(shù)據(jù)在查詢剪枝時(shí)頻繁被用到,因此 GreptimeDB 緩存了反序列化之后的結(jié)構(gòu),避免頻繁反序列化帶來(lái)的開銷。
盡管 GreptimeDB 的緩存機(jī)制較為復(fù)雜,但是用戶無(wú)需過(guò)多了解細(xì)節(jié),只需要給定特定的緩存大小,GreptimeDB 會(huì)自動(dòng)分配各類緩存的配額以及管理緩存的分配和釋放,具體調(diào)優(yōu)指南請(qǐng)參考附錄[1]。
無(wú)畏擴(kuò)縮容
GreptimeDB 的最小數(shù)據(jù)讀寫單元是表的數(shù)據(jù)分片(稱之為 region)。Region 可以在不同的節(jié)點(diǎn)之間進(jìn)行遷移。目前開源版本的 GreptimeDB 支持手動(dòng)通過(guò) migrate_region函數(shù)進(jìn)行 region 的遷移(詳見附錄[3])。當(dāng)監(jiān)控發(fā)現(xiàn)某些 datanode 的負(fù)載較高時(shí),可以將部分 region 遷移到其他較為空閑的 datanode 上避免可用性的降級(jí)。
圖片
此外,GreptimeDB 是面向云原生基礎(chǔ)設(shè)施設(shè)計(jì)的數(shù)據(jù)庫(kù),其 Metasrv 節(jié)點(diǎn)能夠?qū)崟r(shí)采集各個(gè)節(jié)點(diǎn)的負(fù)載并且將流量在不同節(jié)點(diǎn)之間進(jìn)行分配。對(duì)于不同的負(fù)載讀寫特性,還可以利用 Kubernetes 的彈性調(diào)度特性來(lái)調(diào)整不同節(jié)點(diǎn)組的副本數(shù)量來(lái)實(shí)現(xiàn)讀寫分離。關(guān)于 GreptimeDB 讀寫分離的實(shí)踐,可以參考附錄[2]。
三、GreptimeDB Flow 流計(jì)算實(shí)踐
GreptimeDB Flow 是一個(gè)專為時(shí)序場(chǎng)景設(shè)計(jì)的輕量級(jí)流計(jì)算引擎。 它特別適用于提取 - 轉(zhuǎn)換 - 加載 (ETL) 過(guò)程或執(zhí)行即時(shí)的過(guò)濾、計(jì)算和查詢,例如求和、平均值和其他聚合。通過(guò)在 Frontend 將寫入流量鏡像一份到 Flownode 進(jìn)行計(jì)算再寫回 Frontend 并進(jìn)行持久化,它可以確保數(shù)據(jù)被增量和連續(xù)地處理,根據(jù)到達(dá)的新的流數(shù)據(jù)更新最終結(jié)果。
圖片
更加重要的是,編寫一個(gè) Flow 流計(jì)算任務(wù)無(wú)需額外的學(xué)習(xí)成本,它完全使用 SQL 語(yǔ)句定義計(jì)算任務(wù)。如以下語(yǔ)句:
圖片
定義了一個(gè)名叫 ngx_status_count 的任務(wù),它負(fù)責(zé)流式地統(tǒng)計(jì) ngx_access_log 表中每分鐘內(nèi)每個(gè)不同狀態(tài)碼的訪問日志數(shù)量。在AS 之后的任務(wù)定義部分是一個(gè)標(biāo)準(zhǔn)的 SQL,因此對(duì)于熟悉 SQL 的開發(fā)者來(lái)說(shuō)極容易上手。
多級(jí)持續(xù)聚合架構(gòu)
10s 粒度熱數(shù)據(jù)層
CREATE FLOW rpc_cost_10s
SINK TO rpc_cost_10s_agg
EXPIRE AFTER '12hours'::INTERVAL
AS SELECT
app_name,
url,
date_bin('10s'::INTERVAL, timestamp) AS time_window,
uddsketch(cost_time_ms, 0.01, 0.001) AS cost_sketch
FROM rpc_cost_time
GROUP BY app_name, url, date_bin('10s'::INTERVAL, timestamp);
說(shuō)明:每 10s 計(jì)算一次 UDDsketch,近似捕獲耗時(shí)分布,并寫入“熱表”,支持毫秒級(jí)查詢。
1m 粒度中層 Roll?up
CREATE FLOW rpc_cost_1m
SINK TO rpc_cost_1m_agg
EXPIRE AFTER '30days'::INTERVAL
AS SELECT
app_name,
url,
date_bin('1m'::INTERVAL, time_window) AS time_window_1m,
uddsketch_merge(cost_sketch) AS cost_sketch_1m
FROM rpc_cost_10s_agg
GROUP BY app_name, url, date_bin('1m'::INTERVAL, time_window);
說(shuō)明:周期性合并 10s 粒度的 sketch,生成分鐘級(jí)聚合,保留 30 天。
10m 粒度冷層
CREATE FLOW rpc_cost_10m
SINK TO rpc_cost_10m_agg
EXPIRE AFTER '180days'::INTERVAL
AS SELECT
app_name,
url,
date_bin('10m'::INTERVAL, time_window_1m) AS time_window_10m,
uddsketch_merge(cost_sketch_1m) AS cost_sketch_10m
FROM rpc_cost_1m_agg
GROUP BY app_name, url, date_bin('10m'::INTERVAL, time_window_1m);
說(shuō)明:進(jìn)一步合并至 10 分鐘級(jí),存入低成本對(duì)象存儲(chǔ),保留 180 天。
UV 近似統(tǒng)計(jì):HyperLogLog
和耗時(shí)分布統(tǒng)計(jì)類似,統(tǒng)計(jì)各個(gè) URL 的獨(dú)立訪問量(UV)也是常見的需求。不過(guò)想要精確統(tǒng)計(jì)特定時(shí)間段的 UV 成本是極高的,因此業(yè)界往往使用近似算法來(lái)實(shí)現(xiàn) UV 計(jì)算,如 HyperLogLog。GreptimeDB v0.12 提供了對(duì) HyperLogLog 相關(guān)函數(shù)的支持,結(jié)合 Flow 可以實(shí)現(xiàn)強(qiáng)大的任意時(shí)間段 UV 近似統(tǒng)計(jì)。
圖片
10s UV 狀態(tài)
CREATE FLOW uv_hll_10s
SINK TO uv_state_10s
EXPIRE AFTER '12hours'::INTERVAL
AS SELECT
app_name,
url,
date_bin('10s'::INTERVAL, ts) AS time_window,
hll(user_id) AS uv_state
FROM access_log
GROUP BY app_name, url, date_bin('10s'::INTERVAL, ts);
- hll 函數(shù): Flow 任務(wù)中我們通過(guò) hll 函數(shù)將同一時(shí)間窗口內(nèi)的 user_id 進(jìn)行散列并寫入到 uv_state_10s 的 uv_state 字段中。
- uv_state BINARY 類型: 是一個(gè)二進(jìn)制字段(BINARY 類型),無(wú)法直接進(jìn)行查詢。如果要查詢某個(gè)10 秒的時(shí)間窗口內(nèi)的獨(dú)立訪問用戶量,需要通過(guò) hll_count 函數(shù)來(lái)進(jìn)行查詢。
SELECT
`app_name`,
`url`,
hll_count(`uv_state`) as uv_count
FROM uv_state_10s
WHERE time_window = 1743479260;
1m UV 聚合
- 如果用戶需要進(jìn)一步將 10 秒的訪問數(shù)據(jù)聚合到 1 分鐘或者直接需要查詢特定時(shí)間段內(nèi)的用戶訪問數(shù)量,則可以通過(guò)hll_merge 函數(shù)來(lái)對(duì)二進(jìn)制的 HyperLogLog 狀態(tài)進(jìn)行合并。
CREATE FLOW uv_hll_1m
SINK TO uv_state_1m
EXPIRE AFTER '180days'::INTERVAL
AS SELECT
app_name,
url,
date_bin('1m'::INTERVAL, time_window) AS time_window_1m,
hll_merge(uv_state) AS uv_state
FROM uv_state_10s
GROUP BY app_name, url, date_bin('1m'::INTERVAL, time_window);
- 查詢示例:
SELECT
app_name,
url,
hll_count(uv_state) AS uv_count
FROM uv_state_1m
WHERE time_window_1m = '2025-04-20T15:23:00Z';
GROUP BY app_name, url;
效果與收益
- 查詢性能顯著提升:
預(yù)聚合 + 多級(jí) Roll?up,避免全量掃描,P99 查詢延遲從秒級(jí)降至毫秒級(jí)。
圖片
- 存儲(chǔ)與成本可控:
不同粒度數(shù)據(jù)設(shè)置差異化 TTL:10s 熱表保留 1 天,1m 中表保留 7 天,10m 冷表保留 180 天,冷熱分離降低存儲(chǔ)成本。
- 資源解偶 & 彈性擴(kuò)縮容:
Frontend、Flownode、Datanode 獨(dú)立伸縮,流計(jì)算、存儲(chǔ)、查詢?nèi)呋ゲ桓蓴_。
- 開發(fā)效率提升:
Flow 編寫使用標(biāo)準(zhǔn) SQL,上手難度低,Roll?up、HyperLogLog、UDDsketch 等內(nèi)置函數(shù)無(wú)需額外學(xué)習(xí)曲線。
四、最佳實(shí)踐與落地建議
- 合理劃分?jǐn)?shù)據(jù)分層:根據(jù)監(jiān)控場(chǎng)景與 SLA 要求確定不同粒度保留策略。
- 調(diào)整 sketch 精度:UDDsketch 支持自定義誤差范圍(α、β 參數(shù)),可根據(jù)業(yè)務(wù)側(cè)對(duì) P50/P99 精度要求調(diào)優(yōu)。
- 監(jiān)控與告警:為各級(jí)聚合任務(wù)配置失敗重試與告警機(jī)制,確保持續(xù)計(jì)算的穩(wěn)定性。
- 資源規(guī)劃:根據(jù)寫入 QPS 與聚合復(fù)雜度合理預(yù)估 Flownode 與 Datanode 數(shù)量,結(jié)合對(duì)象存儲(chǔ)帶寬設(shè)計(jì)分區(qū)策略。
參考文檔:
1. 性能調(diào)優(yōu)技巧 | GreptimeDB Documentation | Unified Time-Series Database(https://docs.greptime.com/zh/user-guide/administration/performance-tuning-tips/#%E5%A2%9E%E5%A4%A7%E7%BC%93%E5%AD%98%E5%A4%A7%E5%B0%8F)
2. 【使用指南】在 Kubernetes 上部署讀寫分離的 GreptimeDB 集群
3. Region Migration | GreptimeDB Documentation | Unified Time-Series Database(https://docs.greptime.com/zh/user-guide/administration/manage-data/region-migration/#select-a-datanode-as-the-migration-destination)