MySQL 最佳實踐: RDS 只讀例項延遲分析

發表於2016-07-22

前言

只讀例項是目前 RDS 使用者實現資料讀寫分離的一種常見架構,使用者只需要將業務中的讀請求分擔到只讀節點上,就可以緩解主庫查詢壓力,同時也可以把一些 OLAP 的分析查詢放到另外的只讀節點上,減小複雜統計查詢對主庫的衝擊,RDS只讀節點架構圖如下:

screenshot

由於RDS只讀節點採用原生的MySQL Binlog複製技術,那麼延遲必然會成為其成立之初就會存在的問題。延遲會導致只讀節點與主庫的資料出現不一致,進而可能造成業務上邏輯的混亂或者資料不正確。

最近也收到了很多使用者關於只讀例項延遲的問題反饋,下面將會分析RDS只讀例項出現延遲的幾種常見場景,希望能夠幫助使用者理解和處理只讀節點的延遲,更好地使用只讀節點:

  1. 只讀節點規格過小(10%)
  2. 主庫的TPS過高(20%)
  3. 主庫的DDL(alter、drop、repair)(40%)
  4. 主庫大事務(insert..select)(20%)
  5. 其他(無主鍵)(10%)

screenshot

場景一:只讀例項規格配置過小導致延遲

這類延遲場景的出現往往是主節點購買的一個較大規格的配置,而只讀節點卻購買了一個最小規格的配置(例如240M記憶體/150 IOPS)。

分析:只讀節點的資料為了和主節點保持同步,採用了MySQL原生的binlog複製技術,由一個IO執行緒和一個SQL執行緒來完成,IO執行緒負責將主庫的binlog拉取到只讀節點,SQL執行緒負責消費這些binlog日誌,這兩個執行緒會消耗掉只讀節點的IO資源,所以當只讀節點IOPS配置不夠的時候,則會導致只讀節點的資料出現延遲:

screenshot

可以通過只讀節點效能監控來判斷是否已經達到只讀例項的資源配額:

screenshot

screenshot

所以當這樣的延遲情況的發生的時候,需要使用者升級只讀例項的規格(可以參考主庫此時的IOPS的消耗情況),防止由於只讀例項的規格較小導致了資料延遲。

最佳實踐:只讀例項節點的配置大於或者等於主節點的配置;

場景二:主庫的TPS過高導致只讀節點延遲

這一類的延遲也是非常常見的延遲,由於只讀節點與主庫的同步採用的是單執行緒同步,而主庫的壓力是併發多執行緒寫入,這樣勢必會導致只讀節點的資料延遲,可以通過觀察只讀節點的TPS與主節點的TPS效能資料來完成判斷:

主庫的TPS效能資料:

screenshot

只讀節點的TPS效能資料:

screenshot

針對這樣場景的延遲,開啟只讀節點的並行複製是解決這一問題的根本方法,目前RDS生產環境預設開啟了並行複製。但是並行複製也不能夠徹底解決單表更新的問題,所以使用者需要排查業務寫入壓力是否正常,適當對業務進行優化或者拆分,保證主庫的TPS不會導致slave出現延遲。

場景三:主庫的DDL(alter、drop、repair、create)導致只讀節點延遲

這種延遲是非常常見的延遲, 可以分為兩類:

第一類:只讀節點與主庫的DDL同步是序列進行的,如果DDL操作在主庫執行時間很長,那麼同樣在備庫也會消耗同樣的時間,比如在主庫對一張500W的表新增一個欄位耗費了10分鐘,那麼在只讀節點上也同樣會耗費10分鐘,所以只讀節點會延遲600S,其他常見操作比如:

範例:只讀節點出現延遲

screenshot

主例項備庫同樣出現延遲:

screenshot

檢視主庫這這一段時間是否存在DDL,發現主庫在新增索引:

screenshot

第二類:由於只讀節點上會有使用者的查詢在上面執行,所以如果只讀節點上有一個執行時間非常長的的查詢正在執行,那麼這個查詢會堵塞來自主庫的DDL,直到查詢結束為止,進而導致了只讀節點的資料延遲。在只讀節點上可以通過執行show processlist命令檢視連線的狀態處於: Waiting for table metadata lock

screenshot

這個時候只需要kill掉只讀節點上的大查詢就可以恢復只讀節點與主節點的資料同步。

場景四:主庫執行大事務導致延遲

這一種延遲場景也是比較常見的,比如在主庫執行一個大的update、delete、insert … select的事務操作,產生大量的binlog傳送到只讀節點,只讀節點需要花費與主庫相同的時間來完成該事務操作,進而導致了只讀節點的延遲。只讀例項發生延遲,在只讀節點執行show slave statusG命令,可以通過兩個關鍵的位點引數來判斷只讀例項上是否在執行大事務:Seconds_Behind_Master不斷增加,但是Exec_Master_Log_Pos 卻沒有發生變化,這樣則可以判斷只讀節點的SQL執行緒在執行一個大的事務或者DDL操作。

例如下面的例子,使用者在主庫執行了一條insert … select非常大的插入操作,該操作產生了近幾十G的binlog檔案傳輸到只讀節點,進而導致了只讀節點出現應用binlog延遲:

screenshot

screenshot

針對此類大事務延遲的場景,需要將大事務拆分成為小事務進行排量提交,這樣只讀節點就可以迅速的完成事務的執行,不會造成資料的延遲。

場景五:其他只讀例項出現延遲的情況

如對無主鍵的表進行刪除(可以參考MySQL主鍵的缺少導致備庫hang),RDS目前已經支援對錶新增隱式主鍵,但是對於以前歷史建立的表需要進行重建才能支援隱式主鍵。

總結

綜上所述,當只讀例項出現延遲後的排查思路:

  1. 看只讀節點IOPS定位是否存在資源瓶頸;
  2. 看只讀節點的binlog增長量定位是否存在大事務;
  3. 看只讀節點的comdml效能指標,對比主節點的commdml定位是否是主庫寫入壓力過高導致;
  4. 看只讀節點show full processlist,判斷是否有Waiting for table metadata lock和alter,repair,create等ddl操作。

最佳實踐

  1. 使用innodb儲存引擎;
  2. 只讀例項的規格不低於主例項;
  3. 大事務拆分為小事務;
  4. 購買多個只讀節點冗餘;
  5. DDL變更期間觀察是否有大查詢。

相關文章