CeresDBRust 高性能云原生時序數(shù)據(jù)庫
CeresDB 是一款高性能、分布式的云原生時序數(shù)據(jù)庫,采用 Rust 編寫。
CeresDB 架構(gòu)介紹
CeresDB 是一個時序數(shù)據(jù)庫,與經(jīng)典時序數(shù)據(jù)庫相比,CeresDB 的目標是能夠同時處理時序型和分析型兩種模式的數(shù)據(jù),并提供高效的讀寫。
在經(jīng)典的時序數(shù)據(jù)庫中,Tag列(InfluxDB稱之為Tag,Prometheus稱之為Label)通常會對其生成倒排索引,但在實際使用中,Tag的基數(shù)在不同的場景中是不一樣的 ———— 在某些場景下,Tag的基數(shù)非常高(這種場景下的數(shù)據(jù),我們稱之為分析型數(shù)據(jù)),而基于倒排索引的讀寫要為此付出很高的代價。而另一方面,分析型數(shù)據(jù)庫常用的掃描 + 剪枝方法,可以比較高效地處理這樣的分析型數(shù)據(jù)。
因此 CeresDB 的基本設(shè)計理念是采用混合存儲格式和相應(yīng)的查詢方法,從而達到能夠同時高效處理時序型數(shù)據(jù)和分析型數(shù)據(jù)。
下圖展示了 CeresDB 單機版本的架構(gòu)
┌──────────────────────────────────────────┐
│ RPC Layer (HTTP/gRPC/MySQL) │
└──────────────────────────────────────────┘
┌──────────────────────────────────────────┐
│ SQL Layer │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Parser │ │ Planner │ │
│ └─────────────────┘ └─────────────────┘ │
└──────────────────────────────────────────┘
┌───────────────────┐ ┌───────────────────┐
│ Interpreter │ │ Catalog │
└───────────────────┘ └───────────────────┘
┌──────────────────────────────────────────┐
│ Query Engine │
│ ┌─────────────────┐ ┌─────────────────┐ │
│ │ Optimizer │ │ Executor │ │
│ └─────────────────┘ └─────────────────┘ │
└──────────────────────────────────────────┘
┌──────────────────────────────────────────┐
│ Pluggable Table Engine │
│ ┌────────────────────────────────────┐ │
│ │ Analytic │ │
│ │┌────────────────┐┌────────────────┐│ │
│ ││ Wal ││ Memtable ││ │
│ │└────────────────┘└────────────────┘│ │
│ │┌────────────────┐┌────────────────┐│ │
│ ││ Flush ││ Compaction ││ │
│ │└────────────────┘└────────────────┘│ │
│ │┌────────────────┐┌────────────────┐│ │
│ ││ Manifest ││ Object Store ││ │
│ │└────────────────┘└────────────────┘│ │
│ └────────────────────────────────────┘ │
│ ┌ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
│ Another Table Engine │ │
│ └ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ ─ │
└──────────────────────────────────────────┘
性能優(yōu)化與實驗結(jié)果
CeresDB 組合使用了列式混合存儲、數(shù)據(jù)分區(qū)、剪枝、高效掃描等技術(shù),解決海量時間線(high cardinality)下寫入查詢性能變差的問題。
寫入優(yōu)化
CeresDB 采用類 LSM(Log-structured merge-tree)寫入模型,無需在寫入時處理復(fù)雜的倒排索引,因此寫入性能上較好。
查詢優(yōu)化
主要采用以下技術(shù)手段提高查詢性能:
剪枝:
-
min/max 剪枝:構(gòu)建代價比較低,在特定場景,性能較好
-
XOR 過濾器:提高對 parquet 文件中的 row group 的篩選精度
高效掃描:
-
多個 SST 間并發(fā):同時掃描多個 SST 文件
-
單個 SST 內(nèi)部并發(fā):支持 Parquet 層并行拉取多個 row group
-
合并小 IO:針對 OSS 上的文件,合并小 IO 請求,提高拉取效率
-
本地 cache:緩存 OSS 拉取文件,支持內(nèi)存和磁盤緩存
性能測試結(jié)果
采用 TSBS 進行性能測試。壓測參數(shù)如下:
-
10 個 Tag
-
10 個 Field
-
時間線(Tags 組合數(shù))100w 量級
壓測機器配置:24c90g
InfluxDB 版本:1.8.5
CeresDB 版本:1.0.0
寫入性能對比
InfluxDB 寫入性能隨著時間下降較多。CeresDB 在寫入穩(wěn)定后,寫入速率趨于平穩(wěn),并且總體寫入性能表現(xiàn)為 InfluxDB 的 1.5 倍以上(一段時間后可達 2 倍以上差距)
下圖中,單行 row 包含 10 個 Field。
上圖為 Influxdb,下圖為 CeresDB
查詢性能對比
低篩選度條件(條件:os=Ubuntu15.10),CeresDB 比 InfluxDB 快 26 倍,具體數(shù)據(jù)如下:
-
CeresDB 查詢耗時:15s
-
InfluxDB 查詢耗時:6m43s
高篩選度條件(命中的數(shù)據(jù)較少,條件:hostname=[8 個],此時理論上傳統(tǒng)倒排索引會更有效),這是 InfluxDB 更有優(yōu)勢的場景,此時在預(yù)熱完成條件下,CeresDB 比 InfluxDB 慢 5 倍。
-
CeresDB:85ms
-
InfluxDB:15ms
快速開始
獲取代碼
通過 git 克隆代碼倉庫并進入代碼目錄:
git clone [email protected]:CeresDB/ceresdb.git cd ceresdb
通過 Docker 運行
確保開發(fā)環(huán)境安裝了 docker,通過倉庫中的提供的 Dockerfile 進行鏡像的構(gòu)建:
docker build -t ceresdb .
使用編譯好的鏡像,啟動服務(wù):
docker run -d -t --name ceresdb -p 5440:5440 -p 8831:8831 ceresdb
通過源碼編譯運行
安裝依賴
目前為了編譯 CeresDB,需要安裝相關(guān)依賴,以及 Rust 工具鏈。
開發(fā)依賴(Ubuntu20.04)
開發(fā)環(huán)境這里以 Ubuntu20.04 為例,執(zhí)行如下的命令,即可安裝好所需的依賴:
apt install git curl gcc g++ libssl-dev pkg-config cmake
需要注意的是,項目的編譯對 cmake、gcc、g++ 等實際上都是有版本要求的,如果開發(fā)環(huán)境使用的是較老的 Linux 發(fā)行版的話,一般需要手動安裝較高版本的這些依賴。
Rust
Rust 的安裝建議通過 rustup,安裝了 rustup 之后,進入到 CeresDB 項目的時候,會自動根據(jù) rust-toolchain 文件下載指定的 Rust 版本。
理論上執(zhí)行了之后,需要添加環(huán)境變量,才能使用 Rust 工具鏈,一般會把下面的命令放入到自己的 ~/.bashrc 或者 ~/.bash_profile 中:
source $HOME/.cargo/env
編譯和運行
編譯 Release 版本,執(zhí)行如下命令:
cargo build --release
使用下載的代碼中提供的默認配置文件,即可啟動:
./target/ceresdb-server --config ./docs/example.toml
進行數(shù)據(jù)讀寫
CeresDB 支持自定義擴展的 SQL 協(xié)議,目前可以通過 http 服務(wù)以 SQL 語句進行數(shù)據(jù)的讀寫、表的創(chuàng)建。
建表
curl --location --request POST 'http://127.0.0.1:5440/sql' \ --header 'Content-Type: application/json' \ --data-raw '{ "query": "CREATE TABLE `demo` (`name` string TAG, `value` double NOT NULL, `t` timestamp NOT NULL, TIMESTAMP KEY(t)) ENGINE=Analytic with (enable_ttl='\''false'\'')" }'
插入數(shù)據(jù)
curl --location --request POST 'http://127.0.0.1:5440/sql' \ --header 'Content-Type: application/json' \ --data-raw '{ "query": "INSERT INTO demo(t, name, value) VALUES(1651737067000, '\''ceresdb'\'', 100)" }'
查詢數(shù)據(jù)
curl --location --request POST 'http://127.0.0.1:5440/sql' \ --header 'Content-Type: application/json' \ --data-raw '{ "query": "select * from demo" }'
查看建表信息
curl --location --request POST 'http://127.0.0.1:5440/sql' \ --header 'Content-Type: application/json' \ --data-raw '{ "query": "show create table demo" }'
刪除表
curl --location --request POST 'http://127.0.0.1:5440/sql' \ --header 'Content-Type: application/json' \ --data-raw '{ "query": "DROP TABLE demo" }'
