MySQL InnoDB Cluster – how to manage a split-brain situation

来源:https://www.cnblogs.com/kerrycode/p/18356570
-Advertisement-
Play Games

本文是翻譯MySQL InnoDB Cluster – how to manage a split-brain situation[1]這篇文章,如有翻譯不妥或不對的地方,敬請諒解與指正。請尊重原創和翻譯勞動成果,轉載的時候請註明出處。謝謝! 每次我展示MySQL InnoDB Cluster時,在 ...


本文是翻譯MySQL InnoDB Cluster – how to manage a split-brain situation[1]這篇文章,如有翻譯不妥或不對的地方,敬請諒解與指正。請尊重原創和翻譯勞動成果,轉載的時候請註明出處。謝謝!

每次我展示MySQL InnoDB Cluster時,在創建集群的演示中,很多人都不明白為什麼當我集群中已有2個成員時,我的集群還不能容忍任何故障。 事實上,當您創建MySQL InnoDB集群時,只要您添加了第二個實例,您就可以看到狀態信息:

    "status""OK_NO_TOLERANCE",      
    "statusText""Cluster is NOT tolerant to any failures.",

仲裁(Quorum)

[譯者註釋] 這裡Quorum翻譯成仲裁,直譯是法定人數。個人認為翻譯成仲裁更好一些。

這是為什麼呢?這是因為,要成為網路主分區(網路主分區指包含服務的網路分區,在預設的單主模式中指具有主節點的網路分區)的一部分,您的網路分區必須達到大多數節點(法定人數)。在MySQL InnoDB集群(和許多其他集群解決方案一樣)中,要達到法定人數,分區中的成員數量必須大於50%。

[譯者註釋]:這裡所謂的網路主分區(primary partition),其實是指集群中的節點可能由於網路故障導致變成了2個或多個隔離區域。是一個網路拓撲概念。

因此,當我們已有2個節點時,如果兩個伺服器之間出現網路問題,集群將分裂為2個分區。每個分區將擁有總成員數量的 50%(2 個中的1個)。那麼50% > 50% 嗎?不!在MySQL InnoDB集群的環境下,沒有一個網路分區會達到法定人數,也沒有一個網路分區允許查詢。這就是原因。

事實上,第一臺伺服器會發現它再也無法與第二台伺服器通信了……但為什麼呢?是第二台伺服器宕機了嗎?是不是網路介面出了問題?我們不知道,所以我們無法決定。

讓我們看一下這個由3名成員組成的集群 (3/3 = 100%):

如果我們看一下cluster.status()命令的輸出信息,我們可以看到,有3個節點時可以容忍一個節點出現故障:

"status""OK",      
"statusText""Cluster is ONLINE and can tolerate up to ONE failure.",

現在讓我們想象一下,我們遇到一個網路問題,它會隔離其中一個成員/節點:

我們可以在cluster.status()命令的輸出信息中看到節點丟失: 只要一個分區仍然具有法定人數(2/3 = 66%,大於 50%),我們的集群就仍然能夠提供交易服務。

    "mysql6:3306": {
         "address""mysql6:3306",
          "mode""n/a",
          "readReplicas": {},
          "role""HA",
          "status""(MISSING)"
    }

這裡我想介紹一個非常重要的概念,因為這並不總是顯而易見的。InnoDB Cluster 和 Group Replication 中的集群概念是不同的。實際上,InnoDB Cluster 依賴於DBA使用 MySQL Shell創建的元數據。這些元數據描述了集群的設置方式。Group Replication 以不同的方式看待集群。它以上次檢查時的狀態以及現在的狀態來看待集群……並更新該視圖。這通常被稱為世界觀(view of the world)。 因此,在上面的示例中,InnoDB 集群看到 3 個節點:2 個線上,1 個丟失。對於組複製,在短時間內,網路分區中節點處於UNREACHABLE狀態,幾秒鐘後,在被多數人從組中逐出後(因此只有在仍有多數人的情況下),該節點不再是集群的一部分。組大小現在是 2/2(2/2 而不是 2/3)。此信息可以通過performance_schema.replication_group_members獲取。

如果我們的網路問題更加嚴重,並將我們的集群分成 3 個,如下圖所示,那麼集群將處於“離線”狀態,因為這 3 個分區均未達到法定多數,即 1/3 = 33% (<50%):

在這種情況下,MySQL 服務將無法正常工作,直到人工修複該問題。

解決問題

當集群中不再有網路主分區時(如上例所示),DBA 需要恢復服務。和往常一樣,MySQL 錯誤日誌中已經有一些信息:

2019-04-10T13:34:09.051391Z 0 [Warning] [MY-011493] [Repl] Plugin group_replication 
reported: 'Member with address mysql4:3306 has become unreachable.'
2019-04-10T13:34:09.065598Z 0 [Warning] [MY-011493] [Repl] Plugin group_replication 
reported: 'Member with address mysql5:3306 has become unreachable.'
2019-04-10T13:34:09.065615Z 0 [ERROR] [MY-011495] [Repl] Plugin group_replication 
reported: 'This server is not able to reach a majority of members in
the group. This server will now block all updates. The server will
remain blocked until contact with the majority is restored. It is 
possible to use group_replication_force_members to force a new group
membership.

從消息中我們可以看到這正是我們在這裡解釋的情況/場景。我們可以從命令cluster.status()的輸出信息看到集群被“阻止”了:

"status""NO_QUORUM",      
"statusText""Cluster has no quorum as visible from 'mysql4:3306'
               and cannot process write transactions. 
               2 members are not active"

我們有兩個解決方案來解決這個問題:

  1. 使用SQL和組複製變數
  2. 使用 MySQL Shell 的 adminAPI

使用SQL和組複製變數進行修複

手冊[2]中解釋了這個過程(組複製:網路分區)。 在DBA想要用來恢復服務的節點上,如果只剩下一個節點,我們可以使用全局變數group_replication_force_members,並使用您可以在group_replication_local_address找到的伺服器的GCS地址(如果有多個伺服器線上但未達到大多數,則應將所有伺服器添加到此變數中):

set global group_replication_force_members=@@group_replication_local_address;

請註意,最佳做法是關閉其他節點,以避免在強制仲裁過程中再次出現任何類型的衝突。

集群將再次可用。我們可以在錯誤日誌中看到情況已解決:

2019-04-10T14:41:15.232078Z 0 [Warning] [MY-011498] [Repl] Plugin group_replication 
reported: 
'The member has resumed contact with a majority of the members in the group. 
Regular operation is restored and transactions are unblocked.'

當節點上線後不要忘記刪除變數group_replication_force_members的值

set global group_replication_force_members='';

當網路問題解決後,節點將嘗試重新連接,但由於我們強製成員身份/資格,這些節點將被拒絕。您需要通過以下方式將其重新加入群組:

  • 重新啟動 mysqld服務
  • 重新啟動組複製(stop group_replication; start group_replication)
  • 使用 MySQL Shell ( cluster.rejoinInstance())

使用 MySQL Shell的adminAPI

另一個選項是使用MySQL Shell的adminAPI。這當然是更好的選擇!使用 AdminAPI,您甚至不需要知道用於 GCS 的埠即可恢復仲裁。 在下麵的示例中,我們將使用名為mysql4的伺服器來重新激活我們的集群:

cluster.forceQuorumUsingPartitionOf('clusteradmin@mysql4'

並且當網路問題解決後,Shell 還可以用於重新加入其他實例(在本例中為mysql6):

cluster.rejoinInstance('clusteradmin@mysql6'

結論

如果您遇到任何原因在 MySQL InnoDB 群集上失去仲裁的情況,請不要驚慌。選擇要使用的節點(或仍可相互通信的節點列表),如果可以的話,請關閉或停止其他節點上的mysqld服務。然後 MySQL Shell再次幫助你,你可以使用 adminAPI 強制仲裁併用一個命令中重新激活您的群集!

Bonus

如果您想知道您的 MySQL 伺服器是否屬於網路主分區(占多數的分區),您可以運行以下命令:

mysql> SELECT IF( MEMBER_STATE='ONLINE' AND ((
 SELECT COUNT(*) FROM performance_schema.replication_group_members 
 WHERE MEMBER_STATE NOT IN ('ONLINE''RECOVERING')) >= 
 ((SELECT COUNT(*) 
   FROM performance_schema.replication_group_members)/2) = 0), 'YES''NO' ) 
` in primary partition` 
 FROM performance_schema.replication_group_members 
 JOIN performance_schema.replication_group_member_stats 
 USING(member_id) where member_id=@@global.server_uuid;
+----------------------+
| in primary partition |
+----------------------+
| NO                   |
+----------------------+

或者使用addition_to_sys_GR.sql這個SQL來確認。

USE sys;

DELIMITER $$

CREATE FUNCTION my_id() RETURNS TEXT(36DETERMINISTIC NO SQL RETURN (SELECT @@global.server_uuid as my_id);$$

-- new function, contribution from Bruce DeFrang
CREATE FUNCTION gr_member_in_primary_partition()
    RETURNS VARCHAR(3)
    DETERMINISTIC
    BEGIN
      RETURN (SELECT IF( MEMBER_STATE='ONLINE' AND ((SELECT COUNT(*) FROM
    performance_schema.replication_group_members WHERE MEMBER_STATE NOT IN ('ONLINE''RECOVERING')) >=
    ((SELECT COUNT(*) FROM performance_schema.replication_group_members)/2) = 0),
    'YES''NO' ) FROM performance_schema.replication_group_members JOIN
    performance_schema.replication_group_member_stats USING(member_id) where member_id=my_id());
END$$

CREATE VIEW gr_member_routing_candidate_status AS SELECT
sys.gr_member_in_primary_partition() as viable_candidate,
IF( (SELECT (SELECT GROUP_CONCAT(variable_value) FROM
performance_schema.global_variables WHERE variable_name IN ('read_only',
'super_read_only')) != 'OFF,OFF'), 'YES''NO'as read_only,
Count_Transactions_Remote_In_Applier_Queue as transactions_behind, Count_Transactions_in_queue as 'transactions_to_cert' 
from performance_schema.replication_group_member_stats where member_id=my_id();$$

DELIMITER ;


SQL>select gr_member_in_primary_partition();
+----------------------------------+
| gr_member_in_primary_partition() |
+----------------------------------+
| YES                              |
+----------------------------------+
1 row in set (0.0288 sec)
參考資料
[1]

1: https://lefred.be/content/mysql-innodb-cluster-how-to-manage-a-split-brain-situation/

[2]

2: https://dev.mysql.com/doc/refman/8.0/en/group-replication-network-partitioning.html

掃描上面二維碼關註我 如果你真心覺得文章寫得不錯,而且對你有所幫助,那就不妨幫忙“推薦"一下,您的“推薦”和”打賞“將是我最大的寫作動力! 本文版權歸作者所有,歡迎轉載,但未經作者同意必須保留此段聲明,且在文章頁面明顯位置給出原文連接.
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在當今數字化的時代,數據已然成為企業決策與運營的關鍵要素。而保障數據的完整性、準確性以及及時性,對於企業的發展有著舉足輕重的意義。在數據運維管理範疇內,補數據屬於大數據開發和運維人員常用的運維操作手段。 周期補數據和定時補數據作為兩個相對特殊的補數據方式,在各類不同的場景中均發揮著至關重要的作用。 ...
  • GreatSQL 並行Load Data加快數據導入 資料庫信息 資料庫版本:GreatSQL 8.0.32-25 Clickhouse表需要導入到 GreatSQL 中,表數據量龐大所以選用導出CSV的方式。 測試數據復現操作 load data MySQL load data 語句能快速將一個文 ...
  • 1.資料庫結構優化 一個好的資料庫設計方案對於資料庫的性能往往會起到事半功倍的效果。優化設計需要考慮數據冗餘、查詢和更新的速度、欄位的數據類型是否合理等多方面的因素。 將欄位很多的表分解成多個表 概述:對於欄位較多的表,如果有些欄位的使用頻率很低,可以將這些欄位分離出來形成新表。這樣可以減少表的數據 ...
  • 指標是反映企業的各項核心業務活動、管理成效的數據體系,指標體系作為聯結業務邏輯與數據實體的關鍵橋梁,是構建高質量數據統計的基礎單元,併在量化業務績效和效果評估中扮演著核心角色。 為了更好地服務於客戶並提供切實可行的實踐指導,自4月24日起,袋鼠雲將推出全新《指標體系建設實戰》系列直播。該系列內容覆蓋 ...
  • 摘要:當多個引擎/節點同時訪問和修改數據時,如何保證數據在各個引擎/節點之間的一致性成為了一項挑戰。本文將深入探討MySQL集群在保持數據一致性的解決方案。 本文分享自華為雲社區《【華為雲MySQL技術專欄】MySQL 8.0事務提交原理解析!》,作者:GaussDB資料庫。 1. 概述 MySQL ...
  • Flink CDC 於 2021 年 11 月 15 日發佈了最新版本 2.1,該版本通過引入內置 Debezium 組件,增加了對 Oracle 的支持。 Flink下載地址 https://flink.apache.org/downloads/ 其他必需的jar包(cdc、jdbc、mysq和o ...
  • 數字化轉型提速中!傳統農牧食品行業也尋求搭上數字化轉型的快車,通過物聯網、大數據、人工智慧等現代信息技術,實現生產、加工、流通等環節的智能化和自動化,提高生產效率、優化資源配置、提升產品質量,並滿足消費者對食品安全和可追溯性的需求。 在數字化浪潮的推動下,鐵騎力士集團作為一家歷史悠久的農牧食品企業, ...
  • 作者 | 月影幽篁 在當前數據驅動的業務環境中,快速且高效的數據處理能力至關重要。Apache SeaTunnel以其卓越的性能和靈活性,成為數據工程師和開發者的首選工具之一。本文將介紹如何在集群環境中搭建Apache SeaTunnel 2.3.5版本的 Zeta-Server,並概述其使用方法。 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...