tiKV 最底層使用的是 RocksDB(tidb3.0版本中將使用tian存儲引擎) 做為持久化存儲,所以 TiKV 的很多性能相關的參數都是與 RocksDB 相關的。TiKV 使用了兩個 RocksDB 實例,默認 RocksDB 實例存儲 KV 數據,Raft RocksDB 實例(簡稱 RaftDB)存儲 Raft 數據。
TiKV 使用了 RocksDB 的 Column Families
(CF) 特性。
-
默認 RocksDB 實例將 KV 數據存儲在內部的
default
、write
和lock
3 個 CF 內。default
CF 存儲的是真正的數據,與其對應的參數位於[rocksdb.defaultcf]
項中;write
CF 存儲的是數據的版本信息 (MVCC) 以及索引相關的數據,相關的參數位於[rocksdb.writecf]
項中;lock
CF 存儲的是鎖信息,系統使用默認參數。
-
Raft RocksDB 實例存儲 Raft log。
default
CF 主要存儲的是 Raft log,與其對應的參數位於[raftdb.defaultcf]
項中。
每個 CF 都有單獨的 block-cache
,用於緩存數據塊,加速 RocksDB 的讀取速度,block-cache 的大小通過參數 block-cache-size
控制,block-cache-size 越大,能夠緩存的熱點數據越多,對讀取操作越有利,同時占用的系統內存也會越多。
每個 CF 有各自的 write-buffer
,大小通過 write-buffer-size
控制
# 日志級別,可選值為:trace,debug,info,warn,error,off log-level = "info" [server] # 監聽地址 # addr = "127.0.0.1:20160" # gRPC 線程池大小 # grpc-concurrency = 4 # TiKV 每個實例之間的 gRPC 連接數 # grpc-raft-conn-num = 10 # TiDB 過來的大部分讀請求都會發送到 TiKV 的 Coprocessor 進行處理,該參數用於設置 # coprocessor 線程的個數,如果業務是讀請求比較多,增加 coprocessor 的線程數,但應比系統的 # CPU 核數小。例如:TiKV 所在的機器有 32 core,在重讀的場景下甚至可以將該參數設置為 30。在沒有 # 設置該參數的情況下,TiKV 會自動將該值設置為 CPU 總核數乘以 0.8。 # end-point-concurrency = 8 # 可以給 TiKV 實例打標簽,用於副本的調度 # labels = {zone = "cn-east-1", host = "118", disk = "ssd"} [storage] # 數據目錄 # data-dir = "/tmp/tikv/store" # 通常情況下使用默認值就可以了。在導數據的情況下建議將該參數設置為 1024000。 # scheduler-concurrency = 102400 # 該參數控制寫入線程的個數,當寫入操作比較頻繁的時候,需要把該參數調大。使用 top -H -p tikv-pid # 發現名稱為 sched-worker-pool 的線程都特別忙,這個時候就需要將 scheduler-worker-pool-size # 參數調大,增加寫線程的個數。 # scheduler-worker-pool-size = 4 [pd] # pd 的地址 # endpoints = ["127.0.0.1:2379","127.0.0.2:2379","127.0.0.3:2379"] [metric] # 將 metrics 推送給 Prometheus pushgateway 的時間間隔 interval = "15s" # Prometheus pushgateway 的地址 address = "" job = "tikv" [raftstore] # 默認為 true,表示強制將數據刷到磁盤上。如果是非金融安全級別的業務場景,建議設置成 false, # 以便獲得更高的性能。 sync-log = true # Raft RocksDB 目錄。默認值是 [storage.data-dir] 的 raft 子目錄。 # 如果機器上有多塊磁盤,可以將 Raft RocksDB 的數據放在不同的盤上,提高 TiKV 的性能。 # raftdb-dir = "/tmp/tikv/store/raft" region-max-size = "384MB" # Region 分裂閾值 region-split-size = "256MB" # 當 Region 寫入的數據量超過該閾值的時候,TiKV 會檢查該 Region 是否需要分裂。為了減少檢查過程 # 中掃描數據的成本,數據過程中可以將該值設置為32MB,正常運行狀態下使用默認值即可。 region-split-check-diff = "32MB" [rocksdb] # RocksDB 進行后台任務的最大線程數,后台任務包括 compaction 和 flush。具體 RocksDB 為什么需要進行 compaction, # 請參考 RocksDB 的相關資料。在寫流量比較大的時候(例如導數據),建議開啟更多的線程, # 但應小於 CPU 的核數。例如在導數據的時候,32 核 CPU 的機器,可以設置成 28。 # max-background-jobs = 8 # RocksDB 能夠打開的最大文件句柄數。 # max-open-files = 40960 # RocksDB MANIFEST 文件的大小限制. # 更詳細的信息請參考:https://github.com/facebook/rocksdb/wiki/MANIFEST max-manifest-file-size = "20MB" # RocksDB write-ahead logs 目錄。如果機器上有兩塊盤,可以將 RocksDB 的數據和 WAL 日志放在 # 不同的盤上,提高 TiKV 的性能。 # wal-dir = "/tmp/tikv/store" # 下面兩個參數用於怎樣處理 RocksDB 歸檔 WAL。 # 更多詳細信息請參考:https://github.com/facebook/rocksdb/wiki/How-to-persist-in-memory-RocksDB-database%3F # wal-ttl-seconds = 0 # wal-size-limit = 0 # RocksDB WAL 日志的最大總大小,通常情況下使用默認值就可以了。 # max-total-wal-size = "4GB" # 可以通過該參數打開或者關閉 RocksDB 的統計信息。 # enable-statistics = true # 開啟 RocksDB compaction 過程中的預讀功能,如果使用的是機械磁盤,建議該值至少為2MB。 # compaction-readahead-size = "2MB" [rocksdb.defaultcf] # 數據塊大小。RocksDB 是按照 block 為單元對數據進行壓縮的,同時 block 也是緩存在 block-cache # 中的最小單元(類似其他數據庫的 page 概念)。 block-size = "64KB" # RocksDB 每一層數據的壓縮方式,可選的值為:no,snappy,zlib,bzip2,lz4,lz4hc,zstd。 # no:no:lz4:lz4:lz4:zstd:zstd 表示 level0 和 level1 不壓縮,level2 到 level4 采用 lz4 壓縮算法, # level5 和 level6 采用 zstd 壓縮算法,。 # no 表示沒有壓縮,lz4 是速度和壓縮比較為中庸的壓縮算法,zlib 的壓縮比很高,對存儲空間比較友 # 好,但是壓縮速度比較慢,壓縮的時候需要占用較多的 CPU 資源。不同的機器需要根據 CPU 以及 I/O 資 # 源情況來配置怎樣的壓縮方式。例如:如果采用的壓縮方式為"no:no:lz4:lz4:lz4:zstd:zstd",在大量 # 寫入數據的情況下(導數據),發現系統的 I/O 壓力很大(使用 iostat 發現 %util 持續 100% 或者使 # 用 top 命令發現 iowait 特別多),而 CPU 的資源還比較充裕,這個時候可以考慮將 level0 和 # level1 開啟壓縮,用 CPU 資源換取 I/O 資源。如果采用的壓縮方式 # 為"no:no:lz4:lz4:lz4:zstd:zstd",在大量寫入數據的情況下,發現系統的 I/O 壓力不大,但是 CPU # 資源已經吃光了,top -H 發現有大量的 bg 開頭的線程(RocksDB 的 compaction 線程)在運行,這 # 個時候可以考慮用 I/O 資源換取 CPU 資源,將壓縮方式改成"no:no:no:lz4:lz4:zstd:zstd"。總之,目 # 的是為了最大限度地利用系統的現有資源,使 TiKV 的性能在現有的資源情況下充分發揮。 compression-per-level = ["no", "no", "lz4", "lz4", "lz4", "zstd", "zstd"] # RocksDB memtable 的大小。 write-buffer-size = "128MB" # 最多允許幾個 memtable 存在。寫入到 RocksDB 的數據首先會記錄到 WAL 日志里面,然后會插入到 # memtable 里面,當 memtable 的大小到達了 write-buffer-size 限定的大小的時候,當前的 # memtable 會變成只讀的,然后生成一個新的 memtable 接收新的寫入。只讀的 memtable 會被 # RocksDB 的 flush 線程(max-background-flushes 參數能夠控制 flush 線程的最大個數) # flush 到磁盤,成為 level0 的一個 sst 文件。當 flush 線程忙不過來,導致等待 flush 到磁盤的 # memtable 的數量到達 max-write-buffer-number 限定的個數的時候,RocksDB 會將新的寫入 # stall 住,stall 是 RocksDB 的一種流控機制。在導數據的時候可以將 max-write-buffer-number # 的值設置的更大一點,例如 10。 max-write-buffer-number = 5 # 當 level0 的 sst 文件個數到達 level0-slowdown-writes-trigger 指定的限度的時候, # RocksDB 會嘗試減慢寫入的速度。因為 level0 的 sst 太多會導致 RocksDB 的讀放大上升。 # level0-slowdown-writes-trigger 和 level0-stop-writes-trigger 是 RocksDB 進行流控的 # 另一個表現。當 level0 的 sst 的文件個數到達 4(默認值),level0 的 sst 文件會和 level1 中 # 有 overlap 的 sst 文件進行 compaction,緩解讀放大的問題。 level0-slowdown-writes-trigger = 20 # 當 level0 的 sst 文件個數到達 level0-stop-writes-trigger 指定的限度的時候,RocksDB 會 # stall 住新的寫入。 level0-stop-writes-trigger = 36 # 當 level1 的數據量大小達到 max-bytes-for-level-base 限定的值的時候,會觸發 level1 的 # sst 和 level2 種有 overlap 的 sst 進行 compaction。 # 黃金定律:max-bytes-for-level-base 的設置的第一參考原則就是保證和 level0 的數據量大致相 # 等,這樣能夠減少不必要的 compaction。例如壓縮方式為"no:no:lz4:lz4:lz4:lz4:lz4",那么 # max-bytes-for-level-base 的值應該是 write-buffer-size 的大小乘以 4,因為 level0 和 # level1 都沒有壓縮,而且 level0 觸發 compaction 的條件是 sst 的個數到達 4(默認值)。在 # level0 和 level1 都采取了壓縮的情況下,就需要分析下 RocksDB 的日志,看一個 memtable 的壓 # 縮成一個 sst 文件的大小大概是多少,例如 32MB,那么 max-bytes-for-level-base 的建議值就應 # 該是 32MB * 4 = 128MB。 max-bytes-for-level-base = "512MB" # sst 文件的大小。level0 的 sst 文件的大小受 write-buffer-size 和 level0 采用的壓縮算法的 # 影響,target-file-size-base 參數用於控制 level1-level6 單個 sst 文件的大小。 target-file-size-base = "32MB" # 在不配置該參數的情況下,TiKV 會將該值設置為系統總內存量的 40%。如果需要在單個物理機上部署多個 # TiKV 節點,需要顯式配置該參數,否則 TiKV 容易出現 OOM 的問題。 # block-cache-size = "1GB" [rocksdb.writecf] # 保持和 rocksdb.defaultcf.compression-per-level 一致。 compression-per-level = ["no", "no", "lz4", "lz4", "lz4", "zstd", "zstd"] # 保持和 rocksdb.defaultcf.write-buffer-size 一致。 write-buffer-size = "128MB" max-write-buffer-number = 5 min-write-buffer-number-to-merge = 1 # 保持和 rocksdb.defaultcf.max-bytes-for-level-base 一致。 max-bytes-for-level-base = "512MB" target-file-size-base = "32MB" # 在不配置該參數的情況下,TiKV 會將該值設置為系統總內存量的 15%。如果需要在單個物理機上部署多個 # TiKV 節點,需要顯式配置該參數。版本信息(MVCC)相關的數據以及索引相關的數據都記錄在 write 這 # 個 CF 里面,如果業務的場景下單表索引較多,可以將該參數設置的更大一點。 # block-cache-size = "256MB" [raftdb] # RaftDB 能夠打開的最大文件句柄數。 # max-open-files = 40960 # 可以通過該參數打開或者關閉 RaftDB 的統計信息。 # enable-statistics = true # 開啟 RaftDB compaction 過程中的預讀功能,如果使用的是機械磁盤,建議該值至少為2MB。 # compaction-readahead-size = "2MB" [raftdb.defaultcf] # 保持和 rocksdb.defaultcf.compression-per-level 一致。 compression-per-level = ["no", "no", "lz4", "lz4", "lz4", "zstd", "zstd"] # 保持和 rocksdb.defaultcf.write-buffer-size 一致。 write-buffer-size = "128MB" max-write-buffer-number = 5 min-write-buffer-number-to-merge = 1 # 保持和 rocksdb.defaultcf.max-bytes-for-level-base 一致。 max-bytes-for-level-base = "512MB" target-file-size-base = "32MB" # 通常配置在 256MB 到 2GB 之間,通常情況下使用默認值就可以了,但如果系統資源比較充足可以適當調大點。 block-cache-size = "256MB"
tikv內存使用情況
- TiKV 在處理大的查詢的時候(例如
select * from ...
)會讀取數據然后在內存中生成對應的數據結構返回給 TiDB,這個過程中 TiKV 會占用一部分內存