做者:黃夢龍git
衆所周知,PD 是整個 TiDB 集羣的核心,負責全局元信息的存儲以及 TiKV 集羣負載均衡調度,本文將詳細介紹 PD 調度系統的原理,並經過幾個典型場景的分析和處理方式,分享調度策略的最佳實踐和調優方法,幫助你們在使用過程當中快速定位問題。本文內容基於 3.0 版本,更早的版本(2.x)缺乏部分功能的支持,可是基本原理相似,也能夠以本文做爲參考。github
首先咱們介紹一下調度系統涉及到的相關概念,理解這些概念以及它們相互之間的關係,有助於在實踐中快速定位問題並經過配置進行調整。api
Store安全
PD 中的 Store 指的是集羣中的存儲節點,也就是 tikv-server 實例。注意 Store 與 TiKV 實例是嚴格一一對應的,即便在同一主機甚至同一塊磁盤部署多個 TiKV 實例,這些實例也會對應不一樣的 Store。網絡
Region / Peer / Raft Group併發
每一個 Region 負責維護集羣的一段連續數據(默認配置下平均約 96 MiB),每份數據會在不一樣的 Store 存儲多個副本(默認配置是 3 副本),每一個副本稱爲 Peer。同一個 Region 的多個 Peer 經過 raft 協議進行數據同步,因此 Peer 也用來指代 raft 實例中的成員。TiKV 使用 multi-raft 模式來管理數據,即每一個 Region 都對應一個獨立運行的 raft 實例,咱們也把這樣的一個 raft 實例叫作一個 Raft Group。app
Leader / Follower / Learner負載均衡
它們分別對應 Peer 的三種角色。其中 Leader 負責響應客戶端的讀寫請求;Follower 被動地從 Leader 同步數據,當 Leader 失效時會進行選舉產生新的 Leader;Learner 是一種特殊的角色,它只參與同步 raft log 而不參與投票,在目前的實現中只短暫存在於添加副本的中間步驟。工具
Region Split性能
TiKV 集羣中的 Region 不是一開始就劃分好的,而是隨着數據寫入逐漸分裂生成的,分裂的過程被稱爲 Region Split。
其機制是集羣初始化時構建一個初始 Region 覆蓋整個 key space,隨後在運行過程當中每當 Region 數據達到必定量以後就經過 Split 產生新的 Region。
Pending / Down
Pending 和 Down 是 Peer 可能出現的兩種特殊狀態。其中 Pending 表示 Follower 或 Learner 的 raft log 與 Leader 有較大差距,Pending 狀態的 Follower 沒法被選舉成 Leader。Down 是指 Leader 長時間沒有收到對應 Peer 的消息,一般意味着對應節點發生了宕機或者網絡隔離。
Scheduler
Scheduler(調度器)是 PD 中生成調度的組件。PD 中每一個調度器是獨立運行的,分別服務於不一樣的調度目的。經常使用的調度器及其調用目標有:
balance-leader-scheduler
:保持不一樣節點的 Leader 均衡。balance-region-scheduler
:保持不一樣節點的 Peer 均衡。hot-region-scheduler
:保持不一樣節點的讀寫熱點 Region 均衡。evict-leader-{store-id}
:驅逐某個節點的全部 Leader。(經常使用於滾動升級)Operator
Operator 是應用於一個 Region 的,服務於某個調度目的的一系列操做的集合。例如「將 Region 2 的 Leader 遷移至 Store 5」,「將 Region 2 的副本遷移到 Store 1, 4, 5」 等。
Operator 能夠是由 Scheduler 經過計算生成的,也能夠是由外部 API 建立的。
Operator Step
Operator Step 是 Operator 執行過程的一個步驟,一個 Operator 經常會包含多個 Operator Step。
目前 PD 可生成的 Step 包括:
TransferLeader
:將 Region Leader 遷移至指定 PeerAddPeer
:在指定 Store 添加 FollowerRemovePeer
:刪除一個 Region PeerAddLearner
:在指定 Store 添加 Region LearnerPromoteLearner
:將指定 Learner 提高爲 FollowerSplitRegion
:將指定 Region 一分爲二宏觀上來看,調度流程大致可劃分爲 3 個部分:
1. 信息收集
TiKV 節點週期性地向 PD 上報 StoreHeartbeat
和 RegionHeartbeat
兩種心跳消息。其中 StoreHeartbeat
包含了 Store 的基本信息,容量,剩餘空間,讀寫流量等數據,RegionHeartbeat
包含了 Region 的範圍,副本分佈,副本狀態,數據量,讀寫流量等數據。PD 將這些信息梳理並轉存供調度來決策。
2. 生成調度
不一樣的調度器從自身的邏輯和需求出發,考慮各類限制和約束後生成待執行的 Operator。這裏所說的限制和約束包括但不限於:
3. 執行調度
生成的 Operator 不會當即開始執行,而是首先會進入一個由 OperatorController
管理的一個等待隊列。OperatorController
會根據配置以必定的併發從等待隊列中取出 Operator 進行執行,執行的過程就是依次把每一個 Operator Step 下發給對應 Region 的 Leader。
最終 Operator 執行完畢會被標記爲 finish 狀態或者超時被標記爲 timeout,並從執行列表中移除。
Region 負載均衡調度主要依賴 balance-leader
和 balance-region
這兩個調度器,這兩者的調度目標是將 Region 均勻地分散在集羣中的全部 Store 上。它們的側重點又有所不一樣:balance-leader
關注 Region 的 Leader,能夠認爲目的是分散處理客戶端請求的壓力;balance-region
關注 Region 的各個 Peer,目的是分散存儲的壓力,同時避免出現爆盤等情況。
balance-leader
與 balance-region
有着相似的調度流程,首先根據不一樣 Store 的對應資源量的狀況分別打一個分,而後不斷從得分較高的 Store 選擇 Leader 或 Peer 遷移到得分較低的 Store 上。
這二者的分數計算上也有必定差別:balance-leader
比較簡單,使用 Store 上全部 Leader 所對應的 Region Size 加和做爲得分;balance-region
因爲要考慮不一樣節點存儲容量可能不一致的狀況,會分三種狀況,當空間富餘時使用數據量計算得分(使不一樣節點數據量基本上均衡),當空間不足時由使用剩餘空間計算得分(使不一樣節點剩餘空間基本均衡),處於中間態時則同時考慮兩個因素作加權和看成得分。
此外,爲了應對不一樣節點可能在性能等方面存在差別的問題,咱們還支持爲 Store 設置 balance 權重。leader-weight
和 region-weight
分別用於控制 leader 權重以及 region 權重,這兩個配置的默認值都爲 1
。假如把某個 Store 的 leader-weight
設爲 2
,調度穩定後,則該節點的 leader 數量約爲普通節點的 2 倍;假如把某個 Store 的 region-weight
設爲 0.5
,那麼調度穩定後該節點的 region 數量約爲其餘節點的一半。
熱點調度對應的調度器是 hot-region-scheduler
。目前 3.0 版本統計熱點 Region 的方式比較單一,就是根據 Store 上報的信息,統計出持續一段時間讀或寫流量超過必定閾值的 Region,而後再用與 Balance 相似的方式把這些 Region 分散開來。
對於寫熱點,熱點調度會同時嘗試打散熱點 Region 的 Peer 和 Leader;對於讀熱點,因爲只有 Leader 承載讀壓力,熱點調度會嘗試將熱點 Region 的 Leader 打散。
讓 PD 感知不一樣節點分佈的拓撲是爲了經過調度使不一樣 Region 的各個副本儘量分散,保證高可用和容災。例如集羣有 3 個數據中心,最安全的調度方式就是把 Region 的 3 個 Peer 分別放置在不一樣的數據中心,這樣任意一個數據中心故障時,都能繼續提供服務。
PD 會在後臺不斷掃描全部 Region,當發現 Region 的分佈不是當前的最優化狀態時,會生成調度替換 Peer,將 Region 調整至最佳狀態。
負責這個檢查的組件叫 replicaChecker
(跟 Scheduler 相似,可是不可關閉),它依賴於 location-labels
這個配置來進行調度。好比配置 [zone, rack, host]
定義了三層的拓撲結構:集羣分爲多個 zone(可用區),每一個 zone 下有多個 rack(機架),每一個 rack 下有多個 host(主機)。PD 在調度時首先會嘗試將 Region 的 Peer 放置在不一樣的 zone,假如沒法知足(好比配置 3 副本但總共只有 2 個 zone)則退而求其次保證放置在不一樣的 rack,假如 rack 的數量也不足以保證隔離,那麼再嘗試 host 級別的隔離,以此類推。
縮容是指預備將某個 Store 下線,經過命令將該 Store 標記爲 Offline
狀態,此時 PD 經過調度將待下線節點上的 Region 遷移至其餘節點。故障恢復是指當有 Store 發生故障且沒法恢復時,有 Peer 分佈在對應 Store 上的 Region 會產生缺乏副本的情況,此時 PD 須要在其餘節點上爲這些 Region 補副本。
這兩種狀況的處理過程基本上是同樣的。由 replicaChecker
檢查到 Region 存在異常狀態的 Peer,而後生成調度在健康的 Store 建立新副本替換掉異常的。
Region merge 指的是爲了不刪除數據後大量小 Region 甚至空 Region 消耗系統資源,經過調度把相鄰的小 Region 合併的過程。Region merge 由 mergeChecker
負責,其過程與 replicaChecker
相似,也是在後臺遍歷,發現連續的小 Region 後發起調度。
查看調度系統的狀態的手段主要包括:Metrics,pd-ctl,日誌。本文簡要介紹 Metrics 和 pd-ctl 兩種方式,更具體的信息能夠參考官方文檔中 PD 監控 以及 PD Control 使用 的章節。
Grafana PD / Operator 頁面展現了 Operator 相關統計。其中比較重要的有:
Schedule Operator Create
:展現 Operator 的建立狀況,從名稱能夠知道 Operator 是哪一個調度器建立的以及建立的緣由。
Operator finish duration
:展現了 Operator 執行耗時的狀況
Operator Step duration
:展現不一樣 Operator Step 執行耗時的狀況
查詢 Operator 的 pd-ctl 命令有:
operator show
:查詢當前調度生成的全部 Operator
operator show [admin | leader | region]
:按照類型查詢 Operator
Grafana PD / Statistics - Balance 頁面展現了負載均衡相關統計,其中比較重要的有:
Store Leader/Region score
:展現每一個 Store 的得分
Store Leader/Region count
:展現每一個 Store 的 Leader/Region 數量
Store available
:展現每一個 Store 的剩餘空間
使用 pd-ctl 的 store 命令能夠查詢 Store 的得分,數量,剩餘空間,weight 等信息。
Grafana PD / Statistics - hotspot 頁面展現了熱點 Region 的相關統計,其中比較重要的有:
Hot write Region’s leader/peer distribution
:展現了寫熱點 Region 的 Leader/Peer 分佈狀況
Hot read Region’s leader distribution
:展現了讀熱點 Region 的 Leader 分佈狀況
使用 pd-ctl 一樣能夠查詢上述信息,可使用的命令有:
hot read
:查詢讀熱點 Region 信息
hot write
:查詢寫熱點 Region 信息
hot store
:按 Store 統計熱點分佈狀況
region topread [limit]
:查詢當前讀流量最大的 Region
region topwrite [limit]
:查詢當前寫流量最大的 Region
Grafana PD / Cluster / Region health 面板展現了異常狀態 Region 數的統計,其中包括 Pending Peer,Down Peer,Offline Peer,以及副本數過多或過少的 Region。
經過 pd-ctl 的 region check 命令能夠查看具體異常的 Region 列表:
region check miss-peer
:缺副本的 Region
region check extra-peer
:多副本的 Region
region check down-peer
:有副本狀態爲 Down 的 Region
region check pending-peer
:有副本狀態爲 Pending 的 Region
在線調整調度策略主要使用 pd-ctl 工具來完成,能夠經過如下 3 個方面來控制 PD 的調度行爲。本文作一些簡要介紹,更具體的信息能夠參考官方文檔中 PD Control 使用 的章節。
pd-ctl 支持動態建立和刪除 Scheduler 的功能,咱們能夠經過這些操做來控制 PD 的調度行爲,以下所示:
scheduler show
:顯示當前系統中的 Scheduler
scheduler remove balance-leader-scheduler
:刪除(停用)balance leader 調度器
scheduler add evict-leader-scheduler-1
:添加移除 Store 1 的全部 Leader 的調度器
PD 還支持繞過調度器,直接經過 pd-ctl 來建立或刪除 Operator,以下所示:
operator add add-peer 2 5
:在 Store 5 上爲 Region 2 添加 Peer
operator add transfer-leader 2 5
:將 Region 2 的 Leader 遷移至 Store 5
operator add split-region 2
:將 Region 2 拆分爲 2 個大小至關的 Region
operator remove 2
:取消 Region 2 當前待執行的 Operator
使用 pd-ctl 執行 config show
命令能夠查看全部的調度參數,執行 config set {key} {value}
能夠調整對應參數的值。這裏舉例說明常見的參數,更詳情的說明請參考 PD 調度參數指南:
leader-schedule-limit
:控制 Transfer Leader 調度的併發數
region-schedule-limit
:控制增刪 Peer 調度的併發數
disable-replace-offline-replica
:中止處理節點下線的調度
disable-location-replacement
:中止處理調整 Region 隔離級別相關的調度
max-snapshot-count
:每一個 Store 容許的最大收發 Snapshot 的併發數
須要說明的是,PD 的打分機制決定了通常狀況下,不一樣 Store 的 Leader Count 和 Region Count 不同多並不表明負載是不均衡的。須要從 TiKV 的實際負載或者存儲空間佔用來判斷是否有 Balance 不均衡的情況。
確認存在 Leader / Region 分佈不均衡的現象後,首先要觀察不一樣 Store 的打分狀況。
若是不一樣 Store 的打分是接近的,說明 PD 認爲此時已是均衡狀態了,可能的緣由有:
存在熱點致使負載不均衡。須要根據熱點調度相關的信息進一步分析,能夠參考下文熱點調度的部分。
存在大量的空 Region 或小 Region,致使不一樣 Store 的 Leader 數量差異特別大,致使 raftstore 負擔太重。須要開啓 Region Merge 並儘量加速合併,能夠參考下文關於 Region Merge 的部分。
不一樣 Store 的軟硬件環境存在差別。能夠酌情調整 leader-weight
和 region-weight
來控制 Leader / Region 的分佈。
其餘不明緣由。也可使用調整權重這個兜底的方法,經過調整 leader-weight 和 region-weight 來調整至用戶以爲合理的分佈。
若是不一樣 Store 的打分差別較大,須要進一步檢查 Operator 相關 Metrics,特別關注 Operator 的生成和執行狀況,這時大致上又分兩種狀況。
一種狀況是生成的調度是正常的,可是調度的速度很慢。可能的緣由有:
調度速度受限於 limit 配置。PD 默認配置的 limit 比較保守,在不對正常業務形成顯著影響的前提下,能夠酌情將 leader-schedule-limit
或 region-schedule-limit
調大一些,此外, max-pending-peer-count
以及 max-snapshot-count
限制也能夠放寬。
系統中同時運行有其它的調度任務產生競爭,致使 balance 速度上不去。這種狀況下若是 balance 調度的優先級更高,能夠先停掉其餘的調度或者限制其餘調度的速度。例如 Region 沒均衡的狀況下作下線節點操做,下線的調度與 Region Balance 會搶佔 region-schedule-limit
配額,此時咱們能夠把 replica-schedule-limit
調小將下線調度的速度限制住,或者乾脆設置 disable-replace-offline-replica = true
來暫時關閉下線流程。
調度執行得太慢。能夠檢查 Operator Step 的耗時來進行判斷。一般不涉及到收發 Snapshot 的 Step(好比 TransferLeader
,RemovePeer
,PromoteLearner
等)的完成時間應該在毫秒級,涉及到 Snapshot 的 Step(如 AddLearner
,AddPeer
等)的完成時間爲數十秒。若是耗時明顯太高,多是 TiKV 壓力過大或者網絡等方面的瓶頸致使的,須要具體狀況具體分析。
另外一種狀況是沒能生成對應的 balance 調度。可能的緣由有:
調度器未被啓用。好比對應的 Scheduler 被刪除了,或者 limit 被設置爲 0
。
因爲其它約束沒法進行調度。好比系統中有 evict-leader-scheduler
,此時沒法把 Leader 遷移至對應的 Store。再好比設置了 Label property,也會致使部分 Store 不接受 Leader。
集羣拓撲的限制致使沒法均衡。好比 3 副本 3 數據中心的集羣,因爲副本隔離的限制,每一個 Region 的 3 個副本都分別分佈在不一樣的數據中心,假如這 3 個數據中心的 Store 數不同,最後調度就會收斂在每一個數據中心均衡,可是全局不均衡的狀態。
這個場景仍是從 Operator 相關 Metrics 入手,分析 Operator 的生成執行狀況。
若是調度在正常生成,只是速度很慢。可能的緣由有:
調度速度受限於 limit 配置。下線對應的 limit 參數是 replica-schedule-limit
,能夠把它適當調大。與 Balance 相似,max-pending-peer-count
以及 max-snapshot-count
限制一樣也能夠放寬。
系統中同時運行有其它的調度任務產生競爭,或者調度執行得太慢了。處理方法在上一節已經介紹過了,再也不贅述。
下線單個節點時,因爲待操做的 Region 有很大一部分(3 副本配置下約 1/3)的 Leader 都集中在下線的節點上,下線速度會受限於這個單點生成 Snapshot 的速度。能夠經過手動給這個節點添加一個 evict-leader
調度遷走 Leader 來加速。
若是沒有對應的 Operator 調度生成,可能的緣由有:
下線調度被關閉,或者 replica-schedule-limit
被設爲 0。
找不到節點來轉移 Region。例如相同 Label 的替代節點容量都大於 80%,PD 爲了不爆盤的風險會中止調度。這種狀況須要添加更多節點,或者刪除一些數據釋放空間。
目前 PD 沒有對節點上線特殊處理,節點上線實際上就是依靠 balance region 機制來調度的,因此參考前面 Region 分佈不均衡的排查步驟便可。
熱點調度的問題大致上能夠分爲如下幾種狀況。
一種是從 PD 的 metrics 能看出來有很多 hot Region,可是調度速度跟不上,不能及時地把熱點 Region 分散開來。
解決方法是加大 hot-region-schedule-limit
,並減小其餘調度器的 limit 配額,從而加快熱點調度的速度。還有 hot-region-cache-hits-threshold
調小一些可使 PD 對流量的變化更快作出反應。
第二種狀況是單一 Region 造成熱點的狀況,好比大量請求頻繁 scan 一個小表。這個能夠從業務角度或者 metrics 統計的熱點信息看出來。因爲單 Region 熱點現階段沒法使用打散的手段來消除,須要確認熱點 Region 後先手動添加 split-region
調度將這樣的 Region 拆開。
還有一種狀況是從 PD 的統計來看沒有熱點,可是從 TiKV 的相關 metrics 能夠看出部分節點負載明顯高於其餘節點,成爲整個系統的瓶頸。
這是由於目前 PD 統計熱點 Region 的維度比較單一,僅針對流量進行分析,在某些場景下沒法準備定位出熱點。例如部分 Region 有大量的點查請求,從流量上來看並不顯著,可是太高的 QPS 致使關鍵模塊達到瓶頸。這個問題當前的處理方式是:首先從業務層面肯定造成熱點的 table,而後添加 scatter-range-scheduler
來使得這個 table 的全部 Region 均勻分佈。TiDB 也在其 HTTP API 中提供了相關接口來簡化這個操做,具體能夠參考 TiDB HTTP API 文檔。
與前面討論過的全部調度慢的問題相似,Region Merge 速度慢也頗有多是受到 limit 限制(Region Merge 同時受限於 merge-schedule-limit
及 region-schedule-limit
),或者是與其餘調度器產生了競爭,處理方法再也不贅述了。
假如咱們已經從統計得知系統中有大量的空 Region,這時能夠經過把 max-merge-region-size
和 max-merge-region-keys
調整爲較小值來加快 Merge 速度。這是由於 Merge 的過程涉及到副本遷移,因而 Merge 的 Region 越小,速度就越快。若是 Merge Operator 生成的速度已經有幾百 opm,想進一步加快,還能夠把 patrol-region-interval
調整爲 "10ms" ,這個能加快巡檢 Region 的速度,可是會消耗更多的 CPU。
還有一種特殊狀況:曾經建立過大量 Table 而後又清空了(truncate 操做也算建立 Table),此時若是開啓了 split table 特性,這些空 Region 是沒法合併的,此時須要調整如下參數關閉這個特性:
TiKV split-region-on-table
設爲 false
PD namespace-classifier
設爲 「」
另外對於 3.0.4 和 2.1.16 之前的版本,Region 的統計 approximate_keys
在特定狀況下(大部分發生在 drop table 以後)統計不許確,形成 keys 的統計值很大,沒法知足 max-merge-region-keys
的約束,能夠把 max-merge-region-keys
這個條件放開,調成很大的值來繞過這個問題。
沒有人工介入時,PD 處理 TiKV 節點故障的默認行爲是,等待半小時以後(可經過 max-store-down-time
配置調整),將此節點設置爲 Down
狀態,並開始爲涉及到的 Region 補充副本。
實踐中,若是能肯定這個節點的故障是不可恢復的,能夠當即作下線處理,這樣 PD 能儘快補齊副本,下降數據丟失的風險。與之相對,若是肯定這個節點是能恢復的,但可能半小時以內來不及,則能夠把 max-store-down-time
臨時調整爲比較大的值,這樣能避免超時以後產生沒必要要的補副本產生資源浪費。
本文介紹了 PD 調度的概念,原理以及常見問題的處理方法,但願讀者能夠在理解調度系統的基礎上,參考本文按圖索驥解決生產中遇到的調度相關的問題。PD 的調度策略還在不斷的演進和完善中,也期待你們踊躍提出寶貴的改進意見。