[tidb] 3.7.7 TiKV optimization(TiKV Server 優化)

      網友投稿 937 2025-03-31

      tikv架構

      tikv分層設計

      tikv的模塊

      tikv請求處理及優化

      寫請求

      1.檢查是否worker pool 滿了,可以調大scheduler-worker-pool-size

      2.raftstore是不是慢了,通過判斷是否有寫延時

      3.raftstore或者tikv的cpu是否繁忙

      raststore pool及apply pool是否不足,可以調大store-pool-size或者apply-pool-size的數值。

      4.io操作是否慢

      5.負載是否高

      6.網絡是否有延時

      讀分析處理

      讀流程圖

      1.查看thread pool 是否不夠

      2.些等待是否過高,查看是否有大量掃描,錯誤的執行計劃等。

      3.block cache命中率是否比較低

      TiKV 線程池性能調優

      參考:https://docs.pingcap.com/zh/tidb/stable/tune-tikv-thread-performance

      線程池介紹

      在 TiKV 4.0 中,線程池主要由 gRPC、Scheduler、UnifyReadPool、Raftstore、Apply、RocksDB 以及其它一些占用 CPU 不多的定時任務與檢測組件組成,這里主要介紹幾個占用 CPU 比較多且會對用戶讀寫請求的性能產生影響的線程池。

      gRPC 線程池:負責處理所有網絡請求,它會把不同任務類型的請求轉發給不同的線程池。

      Scheduler 線程池:負責檢測寫事務沖突,把事務的兩階段提交、悲觀鎖上鎖、事務回滾等請求轉化為 key-value 對數組,然后交給 Raftstore 線程進行 Raft 日志復制。

      Raftstore 線程池:負責處理所有的 Raft 消息以及添加新日志的提議 (Propose)、將日志寫入到磁盤,當日志在多數副本中達成一致后,它就會把該日志發送給 Apply 線程。

      Apply 線程池:當收到從 Raftstore 線程池發來的已提交日志后,負責將其解析為 key-value 請求,然后寫入 RocksDB 并且調用回調函數通知 gRPC 線程池中的寫請求完成,返回結果給客戶端。

      RocksDB 線程池:RocksDB 進行 Compact 和 Flush 任務的線程池,關于 RocksDB 的架構與 Compact 操作請參考?RocksDB: A Persistent Key-Value Store for Flash and RAM Storage。

      UnifyReadPool 線程池:TiKV 4.0 推出的新特性,由之前的 Coprocessor 線程池與 Storage Read Pool 合并而來,所有的讀取請求包括 kv get、kv batch get、raw kv get、coprocessor 等都會在這個線程池中執行。

      TiKV 的只讀請求

      TiKV 的讀取請求分為兩類:

      一類是指定查詢某一行或者某幾行的簡單查詢,這類查詢會運行在 Storage Read Pool 中。

      另一類是復雜的聚合計算、范圍查詢,這類請求會運行在 Coprocessor Read Pool 中。

      從 4.0 版本開始,支持兩類讀取請求使用同一個線程池,以減少線程數量,降低用戶使用成本,默認不開啟(默認點查詢和 Coprocessor 請求使用不同的線程池)。用戶可以通過將?readpool.storage.use-unified-pool?設置為 true 來打開統一線程池。

      TiKV 線程池調優

      gRPC 線程池的大小默認配置(server.grpc-concurrency)是 4。由于 gRPC 線程池幾乎不會有多少計算開銷,它主要負責網絡 IO、反序列化請求,因此該配置通常不需要調整。

      如果部署的機器 CPU 核數特別少(小于等于 8),可以考慮將該配置(server.grpc-concurrency)設置為 2。

      如果機器配置很高,并且 TiKV 承擔了非常大量的讀寫請求,觀察到 Grafana 上的監控 Thread CPU 的 gRPC poll CPU 的數值超過了 server.grpc-concurrency 大小的 80%,那么可以考慮適當調大?server.grpc-concurrency?以控制該線程池使用率在 80% 以下(即 Grafana 上的指標低于?80% * server.grpc-concurrency?的值)。

      Scheduler 線程池的大小配置 (storage.scheduler-worker-pool-size) 在 TiKV 檢測到機器 CPU 核數大于等于 16 時默認為 8,小于 16 時默認為 4。它主要用于將復雜的事務請求轉化為簡單的 key-value 讀寫。但是?scheduler 線程池本身不進行任何寫操作。

      如果檢測到有事務沖突,那么它會提前返回沖突結果給客戶端。

      如果未檢測到事務沖突,那么它會把需要寫入的 key-value 合并成一條 Raft 日志交給 Raftstore 線程進行 Raft 日志復制。

      通常來說為了避免過多的線程切換,最好確保 scheduler 線程池的利用率保持在 50%~75% 之間。(如果線程池大小為 8 的話,那么 Grafana 上的 TiKV-Details.Thread CPU.scheduler worker CPU 應當在 400%~600% 之間較為合理)

      Raftstore 線程池是 TiKV 最為復雜的一個線程池,默認大小(raftstore.store-pool-size)為 2,所有的寫請求都會先在 Raftstore 線程 fsync 的方式寫入 RocksDB(除非手動將?raftstore.sync-log?設置為 false;而?raftstore.sync-log?設置為 false,可以提升一部分寫性能,但也會增加在機器故障時數據丟失的風險)。

      由于存在 I/O,Raftstore 線程理論上不可能達到 100% 的 CPU。為了盡可能地減少寫磁盤次數,將多個寫請求攢在一起寫入 RocksDB,最好控制其整體 CPU 使用在 60% 以下(按照線程數默認值 2,則 Grafana 監控上的 TiKV-Details.Thread CPU.Raft store CPU 上的數值控制在 120% 以內較為合理)。不要為了提升寫性能盲目增大 Raftstore 線程池大小,這樣可能會適得其反,增加了磁盤負擔讓性能變差。

      UnifyReadPool 負責處理所有的讀取請求。默認配置(readpool.unified.max-thread-count)大小為機器 CPU 數的 80% (如機器為 16 核,則默認線程池大小為 12)。

      通常建議根據業務負載特性調整其 CPU 使用率在線程池大小的 60%~90% 之間 (如果用戶 Grafana 上 TiKV-Details.Thread CPU.Unified read pool CPU 的峰值不超過 800%, 那么建議用戶將?readpool.unified.max-thread-count?設置為 10,過多的線程數會造成更頻繁的線程切換,并且搶占其他線程池的資源)。

      RocksDB 線程池是 RocksDB 進行 Compact 和 Flush 任務的線程池,通常不需要配置。

      如果機器 CPU 核數較少,可將?rocksdb.max-background-jobs?與?raftdb.max-background-jobs?同時設置為 4。

      如果遇到了 Write Stall,可查看 Grafana 監控上?RocksDB-kv?中的 Write Stall Reason 有哪些指標不為 0。

      如果是由 pending compaction bytes 相關原因引起的,可將?rocksdb.max-sub-compactions?設置為 2 或者 3(該配置表示單次 compaction job 允許使用的子線程數量,TiKV 4.0 版本默認值為 3,3.0 版本默認值為 1)。

      如果原因是 memtable count 相關,建議調大所有列的?max-write-buffer-number(默認為 5)。

      如果原因是 level0 file limit 相關,建議調大如下參數為 64 或者更高:

      rocksdb.defaultcf.level0-slowdown-writes-trigger rocksdb.writecf.level0-slowdown-writes-trigger rocksdb.lockcf.level0-slowdown-writes-trigger rocksdb.defaultcf.level0-stop-writes-trigger rocksdb.writecf.level0-stop-writes-trigger rocksdb.lockcf.level0-stop-writes-trigger

      TiKV 內存參數性能調優

      參考:https://docs.pingcap.com/zh/tidb/stable/tune-tikv-memory-performance

      TiKV 最底層使用的是 RocksDB 做為持久化存儲,所以 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 存儲的是鎖信息,系統使用默認參數。

      [tidb] 3.7.7 TiKV optimization(TiKV Server 優化)

      Raft RocksDB 實例存儲 Raft log。

      default?CF 主要存儲的是 Raft log,與其對應的參數位于?[raftdb.defaultcf]?項中。

      所有的 CF 默認共同使用一個 block cache 實例。通過在?[storage.block-cache]?下設置?capacity?參數,你可以配置該 block cache 的大小。block cache 越大,能夠緩存的熱點數據越多,讀取數據越容易,同時占用的系統內存也越多。如果要為每個 CF 使用單獨的 block cache 實例,需要在?[storage.block-cache]?下設置?shared=false,并為每個 CF 配置單獨的 block cache 大小。例如,可以在?[rocksdb.writecf]?下設置?block-cache-size?參數來配置?write?CF 的大小。

      注意:

      在 TiKV 3.0 之前的版本中,不支持使用?shared block cache,需要為每個 CF 單獨配置 block cache。

      每個 CF 有各自的?write-buffer,大小通過?write-buffer-size?控制。

      參數說明

      # 日志級別,可選值為:trace,debug,warn,error,info,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 [storage.block-cache] ## 是否為 RocksDB 的所有 CF 都創建一個 `shared block cache`。 ## ## RocksDB 使用 block cache 來緩存未壓縮的數據塊。較大的 block cache 可以加快讀取速度。 ## 推薦開啟 `shared block cache` 參數。這樣只需要設置全部緩存大小,使配置過程更加方便。 ## 在大多數情況下,可以通過 LRU 算法在各 CF 間自動平衡緩存用量。 ## ## `storage.block-cache` 會話中的其余配置僅在開啟 `shared block cache` 時起作用。 # shared = true ## `shared block cache` 的大小。正常情況下應設置為系統全部內存的 30%-50%。 ## 如果未設置該參數,則由以下字段或其默認值的總和決定。 ## ## * rocksdb.defaultcf.block-cache-size 或系統全部內存的 25% ## * rocksdb.writecf.block-cache-size 或系統全部內存的 15% ## * rocksdb.lockcf.block-cache-size 或系統全部內存的 2% ## * raftdb.defaultcf.block-cache-size 或系統全部內存的 2% ## ## 要在單個物理機上部署多個 TiKV 節點,需要顯式配置該參數。 ## 否則,TiKV 中可能會出現 OOM 錯誤。 # capacity = "1GB" [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-path = "/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" [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" [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"

      TiKV 內存使用情況

      除了以上列出的?block-cache?以及?write-buffer?會占用系統內存外:

      需預留一些內存作為系統的 page cache

      TiKV 在處理大的查詢的時候(例如?select * from ...)會讀取數據然后在內存中生成對應的數據結構返回給 TiDB,這個過程中 TiKV 會占用一部分內存

      TiKV 機器配置推薦

      生產環境中,不建議將 TiKV 部署在 CPU 核數小于 8 或內存低于 32GB 的機器上

      如果對寫入吞吐要求比較高,建議使用吞吐能力比較好的磁盤

      如果對讀寫的延遲要求非常高,建議使用 IOPS 比較高的 SSD 盤

      任務調度

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:excel2007如何保存為dbf(保存為excel格式怎么弄)
      下一篇:wps表格輸入身份證號和電話號碼有的有錯誤提示有的沒有(wps輸入身份證號碼為什么后面的數不對)
      相關文章
      亚洲一区影音先锋色资源| 亚洲精品无码午夜福利中文字幕| 亚洲AV无码一区二区三区DV| 精品国产日韩亚洲一区| 亚洲AV日韩AV无码污污网站 | 亚洲一级免费视频| 亚洲激情在线观看| 香蕉视频在线观看亚洲| 怡红院亚洲怡红院首页| 国产午夜亚洲不卡| 亚洲日韩一页精品发布| 亚洲女同成av人片在线观看| 国产AⅤ无码专区亚洲AV| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 亚洲情A成黄在线观看动漫软件 | 在线观看亚洲成人| 综合久久久久久中文字幕亚洲国产国产综合一区首 | 亚洲av伊人久久综合密臀性色| 国精无码欧精品亚洲一区| 久久亚洲精品中文字幕三区| 亚洲VA中文字幕不卡无码| 亚洲精品国产成人专区| 亚洲精品电影在线| 亚洲1234区乱码| 亚洲色无码专区一区| 亚洲AV日韩AV一区二区三曲 | 亚洲精品第五页中文字幕| 亚洲AV综合色区无码二区偷拍 | 亚洲综合欧美色五月俺也去| 亚洲国产精品成人AV在线| 日韩色日韩视频亚洲网站| 亚洲国产成人精品女人久久久 | 国产偷国产偷亚洲高清在线| 亚洲男人在线无码视频| 亚洲色欲色欲www在线丝| 久久久久亚洲AV片无码| 亚洲色图.com| 精品国产日韩久久亚洲| 精品亚洲国产成人av| 亚洲日韩VA无码中文字幕| 亚洲熟妇无码另类久久久|