【原創】基於Keepalived做主備的MySQL在切換時遇到的問題

摩雲飛發表於2016-05-11
問題描述 
MySQL 基於 keepalived 實現主備切換,業務 A 和業務 B (其實 A 和 B 上跑的業務是相同的 )同時使用 MySQL 做資料庫查詢。通過重啟 keepalived 服務來測試 MySQL 主備切換後,能夠為業務提供正常的服務。 

問題現象 
測試人員發現 MySQL 主從切換之後,與業務 A 相關的 TCP 連線資訊已經變更為新 TCP 連線,而與業務 B 相關的 TCP 連線資訊仍舊未變化。 

具體環境如下 
業務A:172.16.177.158 
業務B:172.16.177.159 

VIP:172.16.177.147 
MySQL master:172.16.177.148 
MySQL slave:172.16.177.149 

 


在業務正常執行狀態下,業務A 通過 VIP 與 MySQL master(148)建立 6 條 TCP 連線(業務開發人員告知的),分別對應埠 
43666、 43668、 43669、 43670、 43673、 43674。 

當通過重啟 148 機器上的 keepalived 服務來完成 VIP 切換,從而達成 MySQL 主備切換時,可以看到如下抓包資訊: 

如下為 158 上的 TCP 連結資訊。 
 
 
 

可以看到,上面出現了 10 個 RST ……,呃,先不管為什麼多出來 4 個吧。 

下面看一下 148 (原 MySQL master)上來自 158 的連線資訊。 
 
 

      從上面兩個截圖中,只能看到有兩條 TCP 鏈路上出現了新的請求,並且因為重啟了 keepalived 的原因,出現了 TCP 的重發。這兩條 TCP 鏈路對應的埠分別為: 43673、43669。 
這裡重發請求的埠與 158 上的抓包中顯示的一致。 

再看一下 149 (原 MySQL slave)上來自 158 的連線資訊。 
 
 
 

可以看到這裡也出現了 10 條 TCP 鏈路被 RST 。與上面的 10 條 TCP 連結是對應的。 

綜上,整個過程可以描述為: 
  • 最開始 158 與 148 建立了6條 OCS 業務的 TCP 連線;
  • 在重啟 keepalived 的時候,恰好使用埠 43673 和 43669 的 TCP 連線正在信令互動,而此時正處於 VIP 147 從 148 向 149 漂移的過程之中,此時這兩條 TCP 鏈路上的請求會因為得不到任何回應而觸發重傳;
  • 當 VIP 成功繫結到 149 上後,上述兩條 TCP 鏈路上的重傳請求會被 RST,而當其他 TCP 鏈路上有新的請求時,才會被 RST。被 RST 後,OSC 會重新建立 TCP 連線。

下面單獨看下每條 TCP 鏈路的狀況: 

埠 43673 的 TCP 鏈路。 

 

埠為 43669 的 TCP 鏈路。 
 
埠為 43666 的 TCP 鏈路。 
 
埠為 43674 的 TCP 鏈路。 
 
埠為 43670 的 TCP 鏈路。 
 
埠為 43668 的 TCP 鏈路。 
 
埠為 43671 的 TCP 鏈路。 
 
埠為 43665 的 TCP 鏈路。 
 
埠為 43672 的 TCP 鏈路。 
 
埠為 43667 的 TCP 鏈路。 
 


上述現象在對於 159 上的業務來說也是這樣,不再重複說明。 

總結: 
      上述問題的出現值得思考的地方有,通過重啟 keepalived 來促使 MySQL 主備切換這種方式對於實際應用場景是否有意義?!如果實際情況中真的出現類似於 keepalived 重啟導致的 MySQL 主從切換,那麼由此導致的主從不一致將如何解決 ?!業務程式通過某種保活機制觸發對當前 TCP 鏈路是否處於“半開啟”狀態的檢測時間間隔多少比較合適?MySQL 上的 wait_timeout 設定多少比較合適!? 
      真正讓人感到不安的是,僅通過重啟 keepalived 來進行主備切換,無論是 MySQL 側還是業務側,居然都不會收到 TCP 的 FIN 或 RST ,而只會在業務層面有“動作”時才能發現 TCP 鏈路的問題,這種現象對類似 MySQL 這種服務來說必然會造成一些問題。 






相關文章