TiKV 縮容不掉如何解決?

語言: CN / TW / HK

TiKV節點縮容不掉,通常遇到的情況:

  • 1、經常遇到的情況是:3個節點的tikv叢集縮容肯定會一直卡著,因為沒有新節點接受要下線kv的region peer。

  • 2、另外就是除縮容tikv外,剩下的KV硬碟使用情況比較高,到達schedule.high-space-ratio=0.6的限制,導致該tikv的region無法遷移。

但是今天要討論的是:我先執行了擴容,然後再進行的縮容,仍然卡著就說不過去了。

問題現場

版本:TiDB v5.2.1 情況說明:這個tidb是有tiflash節點的,並且這個叢集是一路從3.X升級到5.2.1版本 問題現場:為了下線一個3kv叢集中的一個kv,我們在24號擴容了一個新kv,然後擴容完畢後,下線某個kv,都過了2天,該kv還是處於pending offline的狀態,看監控leader+reigon已經切走了,為啥該kv的狀態仍然沒有tombstone?

p_offline.png

下圖是擴容和縮容tikv的監控,從下圖可以發現擴容和縮容都已經完畢了。 

scalein_kv.png

問題排查

(1)先看看有縮容問題的TIKV節點日誌

檢視日誌發現有:KvService::batch_raft send response fail報錯,查了下asktug,發現這些報錯指向一個4.X的bug:raft 大小限制的過大,超過 gRPC 傳輸通訊限制導致 raft message 卡住的問題,所以影響了 region 的排程。將 TiKV 叢集的 raft-max-size-per-msg 這個配置調小,降低 raft message 大小來看是否能恢復 region 排程。

如果其他人的4.X版本遇到這個問題可以通過上面方式搞定,但是目前我已經升級到了5.2.1,所以上面方法不適合解決我的這個問題。相關的報錯日誌如下:

$ grep 'ERROR' tikv.log
[2022/03/28 09:34:38.062 +08:00] [ERROR] [kv.rs:729] ["KvService::batch_raft send response fail"] [err=RemoteStopped]
[2022/03/28 09:34:38.062 +08:00] [ERROR] [kv.rs:729] ["KvService::batch_raft send response fail"] [err=RemoteStopped]
[2022/03/28 09:34:38.227 +08:00] [ERROR] [pd.rs:83] ["Failed to send read flow statistics"] [err="channel has been closed"]
[2022/03/28 09:34:38.261 +08:00] [ERROR] [kv.rs:729] ["KvService::batch_raft send response fail"] [err=RemoteStopped]
[2022/03/28 09:34:38.261 +08:00] [ERROR] [kv.rs:729] ["KvService::batch_raft send response fail"] [err=RemoteStopped]
[2022/03/28 09:34:55.711 +08:00] [ERROR] [server.rs:1030] ["failed to init io snooper"] [err_code=KV:Unknown] [err="\"IO snooper is not started due to not compiling with BCC\""]

(2)檢視節點情況,發現該節點除了狀態為Offline外,leader_count/region_count都為0,為啥都為0了,等了2天還是pending offline?沒有變tombstone?

tiup ctl:v5.2.1 pd -u http://pd-ip:2379 store 5
{
  "store": {
    "id": 5,
    "address": "xxxx:20160",
    "state": 1,
    "version": "5.2.1",
    "status_address": "xxxxx:20180",
    "git_hash": "2c99f317d4ba125b772a8b94a6c3c0eb9d07ac59",
    "start_timestamp": 1648465247,
    "deploy_path": "/data/deploy/bin",
    "last_heartbeat": 1648517045511041818,
    "state_name": "Offline"
  },
  "status": {
    "capacity": "0B",
    "available": "0B",
    "used_size": "0B",
    "leader_count": 0,
    "leader_weight": 1,
    "leader_score": 0,
    "leader_size": 0,
    "region_count": 0,
    "region_weight": 1,
    "region_score": 0,
    "region_size": 0,
    "slow_score": 0,
    "start_ts": "2022-03-28T19:00:47+08:00",
    "last_heartbeat_ts": "2022-03-29T09:24:05.511041818+08:00",
    "uptime": "14h23m18.511041818s"
  }
}

(3)檢視有問題tikv節點的region資訊。

結果發現不得了的結果,這個不能成功下線的tikv store 5,竟然還有一個id為434317的region,這個region沒有leader,有3個voter(在store 5 、1 、 4上)和2個Learner(在tiflash store 390553和390554上),並且這2個tiflash store還是叢集升級前4.0.9版本的store id,並且之前對tikv/tiflash節點執行過scale-in --force等暴力下線的操作,至於該region為啥沒有選出leader,一則可能是bug,二則可能是暴力下線tikv/tiflash導致。

也就是說:這個沒有leader的region:434317,因為他在store_id:5 上還有記錄,這個問題成為了阻礙該tikv一直卡到offline狀態無法成功下線的原因。

$ tiup ctl:v5.2.1 pd -u http://pd-ip:2379 region store 5
{
  "count": 1,
  "regions": [
    {
      "id": 434317,
      "start_key": "748000000000002DFFB95F720000000000FA",
      "end_key": "748000000000002DFFB95F728000000003FF3F16990000000000FA",
      "epoch": {
        "conf_ver": 7,
        "version": 4204
      },
      "peers": [
        {
          "id": 434318,
          "store_id": 1,
          "role_name": "Voter"
        },
        {
          "id": 434319,
          "store_id": 4,
          "role_name": "Voter"
        },
        {
          "id": 434320,
          "store_id": 5,
          "role_name": "Voter"
        },
        {
          "id": 434321,
          "store_id": 390553,
          "role": 1,
          "role_name": "Learner",
          "is_learner": true
        },
        {
          "id": 434322,
          "store_id": 390554,
          "role": 1,
          "role_name": "Learner",
          "is_learner": true
        }
      ],
      "leader": {
        "role_name": "Voter"
      },
      "written_bytes": 0,
      "read_bytes": 0,
      "written_keys": 0,
      "read_keys": 0,
      "approximate_size": 0,
      "approximate_keys": 0
    }
  ]
}

(4)檢視下該region對應的庫表資訊,看是否對業務有影響,執行後發現是個空region:

$ curl http://tidb-server-ip:10080/regions/434317
{
 "start_key": "dIAAAAAAAC25X3I=",
 "end_key": "dIAAAAAAAC25X3KAAAAAAz8WmQ==",
 "start_key_hex": "748000000000002db95f72",
 "end_key_hex": "748000000000002db95f7280000000033f1699",
 "region_id": 434317,
 "frames": null
}

問題已經定位,下面是如何解決了

問題解決

(1)使用pd-ctl,看看是否能讓434317選出leader,或者通過新增peer,刪除peer等方式解決問題。

執行嘗試如下

// 把 Region 434317 的 leader 排程到 store 4
$tiup ctl:v5.2.1 pd -u http://pd-ip:2379 operator add transfer-leader 434317 4
    Failed! [500] "cannot build operator for region with no leader"

// 在 store 1094772 上新增 Region 434317 的副本
$tiup ctl:v5.2.1 pd -u http://pd-ip:2379 operator add add-peer 434317 1094772
    Failed! [500] "cannot build operator for region with no leader"

// 移除要下線 store 5 上的 Region 434317 的副本
$ tiup ctl:v5.2.1 pd -u http://pd-ip:2379 operator add remove-peer 434317 5
    Failed! [500] "cannot build operator for region with no leader"

發現通過pd-ctl折騰的這條路走不通,因為要想實現上述操作,需要在region有leader的情況下才能操作。

(2)那我使用pd-ctl去把這個store delete如何?

tiup ctl:v5.2.1 pd -u http://pd-ip:2379 store delete 5
Success!

看到Sucess很激動,但是pd-ctl store一看,store 5還是在記錄裡面。發現這一招也不管用。

(3)tiup scale-in --force強制/暴力下線該tikv如何?

tiup cluster scale-in dsp_report -N 10.203.93.36:20160 --force

執行完畢,tiup裡面確實沒了。雖然說眼不見心不煩,但是pd-ctl store檢視tikv資訊還是有,崩潰!

(4)最後只能祭出tikv-ctl工具,來刪除這個region,因為我上文提到了這個region本是空reigon,刪除也不影響業務。具體tikv-ctl的使用和介紹就不詳細說明了,可以參見我之前的公眾號文章:TiDB叢集恢復之TiKV叢集不可用

./tikv-ctl --db /data/deploy/data/db tombstone -r 434317 --force

這麼操作後,整個世界安靜了,我的“強迫症”也得到滿足,這個region終於“乾淨”了。

PS:其他人遇到類似的問題,該排查方案可以參考;也可以先停止下線操作,先升級到高階版本後再嘗試縮容的,這裡告訴大家一個小妙招:我如何收回正在執行的scale-in呢?看下面:

curl -X POST http://${pd_ip}:2379/pd/api/v1/store/${store_id}/state?state=Up

store的狀態轉換

最後這個小結講講Store狀態,TiKV Store 的狀態具體分為 Up,Disconnect,Offline,Down,Tombstone。各狀態的關係如下:

  • Up:表示當前的 TiKV Store 處於提供服務的狀態。

  • Disconnect:當 PD 和 TiKV Store 的心跳資訊丟失超過 20 秒後,該 Store 的狀態會變為 Disconnect 狀態,當時間超過 max-store-down-time 指定的時間後,該 Store 會變為 Down 狀態。

  • Down:表示該 TiKV Store 與叢集失去連線的時間已經超過了 max-store-down-time 指定的時間,預設 30 分鐘。超過該時間後,對應的 Store 會變為 Down,並且開始在存活的 Store 上補足各個 Region 的副本。

  • Offline:當對某個 TiKV Store 通過 PD Control 進行手動下線操作,該 Store 會變為 Offline 狀態。該狀態只是 Store 下線的中間狀態,處於該狀態的 Store 會將其上的所有 Region 搬離至其它滿足搬遷條件的 Up 狀態 Store。當該 Store 的 leadercount 和 regioncount (在 PD Control 中獲取) 均顯示為 0 後,該 Store 會由 Offline 狀態變為 Tombstone 狀態。在 Offline 狀態下,禁止關閉該 Store 服務以及其所在的物理伺服器。下線過程中,如果叢集裡不存在滿足搬遷條件的其它目標 Store(例如沒有足夠的 Store 能夠繼續滿足叢集的副本數量要求),該 Store 將一直處於 Offline 狀態。

  • Tombstone:表示該 TiKV Store 已處於完全下線狀態,可以使用 remove-tombstone 介面安全地清理該狀態的 TiKV。 

tikv-store-status-relationship.png

本小節來自官網:http://docs.pingcap.com/zh/tidb/stable/tidb-scheduling#%E4%BF%A1%E6%81%AF%E6%94%B6%E9%9B%86

 

本人作者:@代曉磊_360 
發表時間:2022/4/25 原文連結:http://tidb.net/blog/ec7009ac