CentOS7上MySQL5.7 InnoDB Cluster安裝(一主兩從複製)

  1. 前導知識
平時最頻繁用到的InnoDB集羣管理AdminAPI:
  • mysqlsh --uri icadmin@linux01:3306
  • var cluster = dba.getCluster('myCluster');
  • var cluster = dba.rebootClusterFromCompleteOutage(); --需要在最後更新的實例上執行!
  • cluster.status();
  • cluster.rejoinInstance('linux01:3306');
  • cluster.removeInstance('linux01:3306');
  • cluster.addInstance('linux01:3306');
MySQL InnoDB Cluster 爲 MySQL 提供了一個完整的高可用解決方案。通過使用 MySQL Shell 提供的 AdminAPI,你可以輕鬆地配置和管理一組至少由3個MySQL服務器實例組成的 InnoDB 集羣。
InnoDB 集羣中的每個 MySQL 服務器實例都運行 MySQL Group Replication(組複製),該複製提供了在 InnoDB 集羣中複製數據的機制,具有內置的故障切換功能。AdminAPI 使我們避免了直接在 InnoDB 集羣中使用組複製。從 MySQL 8.0.27開始,你還可以通過鏈接一個主 InnoDB 集羣及其一個或多個異地(例如不同數據中心)副本來組成 InnoDB ClusterSet,以此來提供異地容災功能。
MySQL Router 可以根據你部署的集羣自動配置自己,並將客戶端應用程序透明地連接到 MySQL 服務器實例。如果 MySQL 服務器實例發生意外故障,集羣將自動重新配置。在默認的單主模式下,InnoDB 集羣只有一個讀寫服務器實例——主服務器,多個輔助服務器實例是主服務器的副本。如果主服務器故障,輔助服務器將自動升級爲主服務器角色。MySQL Router 檢測到這一點後,會將客戶端應用程序的請求轉發到新的 MySQL 主服務器上。高級用戶還可以將集羣配置爲具有多個主節點,但大多情況都不必要這樣做。
InnoDB 集羣至少由三個 MySQL 服務器實例組成,並提供高可用性和可擴展性功能。將使用到以下 MySQL 技術:
  • MySQL Shell,它是MySQL官方提供的高級客戶端和代碼編輯器。
  • MySQL Server 和 Group Replication(組複製),它們配合工作可以使一組MySQL實例對外提供高可能性。InnoDB Cluster提供了另一種易於使用的編程方式來使用Group Replication(組複製)功能。
  • MySQL Router,一個能在應用程序和InnoDB集羣之間提供透明路由的輕量級中間件,是官方提供的MySQL實例負載均衡器(不再需要藉助類似HAProxy的第三方負載均衡器了)。
如下圖1展示了上述各組件是如何協同工作的:
0
基於MySQL的Group Replication(組複製)構建的集羣,可提供自動成員管理、容錯、自動故障切換等功能。InnoDB集羣通常以單主模式(single-primary)運行,具有一個主實例(primary讀寫)和多個輔助實例(secondary只讀)。高級用戶還可以利用多主模式(multi-primary),其中所有實例都是主實例。
你可以使用 MySQL Shell 提供的 AdminAPI 來操作 InnoDB集羣。AdminAPI 有 JavaScript 和 Python 兩種版本,非常適合通過編寫腳本來自動化部署MySQL,以實現高可用性和可擴展性。通過使用 MySQL Shell 的 AdminAPI,你可以避免手動配置許多實例。AdminAPI 爲 MySQL 實例集(組)提供了一個高效的現代化接口,可以方便地在一個統一的工具中進行配置、管理和監控部署工作。
InnoDB Cluster支持MySQL Clone(克隆),這使你可以方便地向集羣配置新的實例。在過去,一個新的實例加入到MySQL集羣實例集之前,你可能需要通過某種方式手動將事務傳輸到待加入的新實例中。這可能涉及製作文件副本、手動複製它們等等。使用InnoDB Cluster,你只需向集羣添加一個實例,它就會被自動配置。
類似地,InnoDB Cluster與 MySQL Router 也進行了緊密集成,你可以使用AdminAPI來使它們一起工作。MySQL Router可以基於InnoDB Cluster,通過一個被稱爲bootstrapping(引導)的過程自動化的配置它自己,你無需手動配置路由。然後 MySQL Router 便可透明地將客戶端應用程序連接到InnoDB集羣,爲客戶端連接提供路由和負載平衡。這種集成還允許你使用 AdminAPI 管理基於 InnoDB Cluster 引導的 MySQL Router 的某些方面。InnoDB Cluster 的集羣狀態信息包含了基於集羣引導的 MySQL Router 的詳細信息。Operations 使你可以在集羣級別創建 MySQL Router 用戶,以使用基於集羣引導的 MySQL Router 等等。
備註:AdminAPI 與運行 MySQL 5.7 的實例兼容,但功能集有所減少。爲了獲得使用 AdminAPI 和 InnoDB集羣的最佳體驗,官方建議升級到MySQL 8.0。但鑑於國內大多數公司還在使用 MySQL 5.7 ,我們這裏將先基於該版本進行集羣搭建(MySQL Community Server 5.7.37),後續將會基於MySQL 8.0再搭一次(並實現可異地容災的InnoDB ClusterSet)!
  1. 正式開始
  1. InnoDB集羣要求
在進行 InnoDB Cluster 的生產部署安裝之前,請確保要使用的 MySQL 服務器實例滿足以下要求:
  • InnoDB Cluster使用組複製,因此你的服務器實例必須滿足相同的要求(參考組複製要求)。AdminAPI 提供 dba.checkInstanceConfiguration() 方法來驗證某個實例是否滿足組複製要求,以及 dba.configureInstance() 方法來配置某個實例以滿足要求。(注意:使用沙箱部署時,實例會自動配置爲滿足這些要求。)
  • 用於組複製的數據以及用於 InnoDB 集羣的數據,必須存儲在 InnoDB 事務存儲引擎中。使用其他存儲引擎(包括臨時內存存儲引擎)可能會導致組複製錯誤。在使用組複製和 InnoDB 集羣之前,需要將使用其他存儲引擎的所有錶轉換爲使用 InnoDB 引擎。你可以通過在MySQL服務器實例上設置 disabled_storage_engines 系統變量來防止使用其他存儲引擎,例如:disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
  • 在安裝配置集羣時,任何MySQL服務器實例都不能有入站複製通道(到達型)。在一個複製組上,由Group Replication(組複製)自動創建的通道才允許被採用(group_replication_applier 和 group_replication_recovery)。InnoDB 集羣不支持手工配置的異步複製通道,使用 AdminAPI 管理的除外。如果要將現有複製拓撲遷移到一個InnoDB集羣部署,並且需要在安裝過程中暫時跳過此驗證,則可以在創建集羣時使用force選項繞過它。
  • 必須在要與 InnoDB Cluster 一起使用的所有實例上啓用Performance Schema。
  • MySQL Shell 用於配置 InnoDB 集羣中的服務器時使用到的配置腳本需要訪問Python。Windows版本的 MySQL Shell 中已經包含了 Python,不需要用戶再做配置。在類 Unix 系統上,Python 必須配置爲 shell 環境的一部份。要檢查你的 Unix 類系統是否正確配置了Python,請執行以下操作:$ /usr/bin/env python ,如果Python解釋器啓動,則無需進一步操作。如果前面的命令失敗,請在你的 Unix類系統上安裝正確版本的Python,並在 /usr/bin/python 和你安裝的 Python 二進制可執行文件之間創建一個軟鏈接。
  • 從8.0.17版開始,MySQL實例必須在 InnoDB 集羣中使用唯一的 server_id 。當你使用 Cluster.addInstance(instance) 操作時,如果 instance 的 server_id 已經被集羣中的其他實例使用,那麼該操作將失敗並報錯。(我們這次使用的版本是5.7.37,但最好也將 server_id 進行唯一化)
  • 從8.0.23版開始,應將MySQL實例配置爲使用並行複製申請者(applier)。(後面進行異地容災的 InnoDB ClusterSet 搭建時會講如何配置)
  • 在配置 InnoDB 集羣的某個MySQL實例過程中,實例要使用的絕大部分系統變量都已經被配置好了。但是 AdminAPI 不會進行 transaction_isolation 系統變量的配置,這意味着它將保持默認值 REPEATABLE READ 。這不會影響單主模式(single-primary)集羣,但是如果你使用的是多主模式(multi-primary)集羣,那麼除非你的應用程序確實依賴默認值 REPEATABLE READ ,否則我們強列建議將值設置爲 READ COMMITTED 隔離級別。
  • 實例的相關配置項,尤其是組複製配置項,必須位於單個 option 文件中。InnoDB Cluster只支持服務器實例的單個 option 文件,不支持使用--defaults-extra-file 選項指定附加的 option 文件。對於任何使用實例 option 文件的 AdminAPI 操作,必須指定主文件。 如果你想爲與 InnoDB Cluster 無關的配置項使用多 option 文件,你必須手動配置這些文件,並考慮多 option 文件的使用優先規則,確保它們被正確更新,並確保與 InnoDB Cluster 相關的設置沒有錯誤地被一個未被認可的額外 option 文件中的選項覆蓋。
  1. InnoDB集羣限制
由於InnoDB Cluster使用了Group Replication(組複製),所以除了下面列的限制外,還要考慮組複製的限制:
  • InnoDB 集羣不管理手動配置的異步複製通道。Group Replication(組複製)和 AdminAPI 不確保異步複製僅在主服務器上處於活動狀態,並且不跨實例複製狀態。這可能會導致複製不再工作的各種情況,並且可能導致集羣出現腦裂。只有從 MySQL 8.0.27 版本開始可用的 InnoDB ClusterSet 才支持在一個 InnoDB 集羣與另一個集羣之間的複製,它管理着從一個活動的主讀寫 InnoDB 集羣到多個只讀副本集羣的複製工作。
  • InnoDB Cluster 被設計爲在局域網中部署。在廣域網上部署單個 InnoDB 集羣對寫性能有顯著影響。穩定且低延遲的網絡對於InnoDB 集羣成員服務器使用底層 Group Replication(組複製)技術相互通信以達成事務共識非常重要。然而,InnoDB ClusterSet 是被設計爲跨多個數據中心部署的,每個 InnoDB 集羣部署在單個數據中心中,通過異步複製通道將它們連接起來。
  • 對於 AdminAPI 操作,你只能使用 TCP/IP 連接和經典的 MySQL 協議連接到InnoDB集羣中的服務器實例。AdminAPI操作不支持使用 Unix sockets 和 named pipes(命名管道),AdminAPI 操作也不支持使用 X 協議。同樣的限制也適用於MySQL 服務器實例本身之間的連接。(注意:客戶端應用程序可以使用 X 協議、Unix sockets 和 named pipes(命名管道)連接到InnoDB集羣中的實例,這些限制僅適用於使用 AdminAPI 命令的管理操作,以及集羣內實例之間的連接)
  • AdminAPI 和 InnoDB Cluster支持 MySQL Server 5.7 版本的實例。但是對這些實例會有一些限制,並且有一些功能在這版本上不支持。(後面會在“使用運行MySQL 5.7的實例”中專門列一下具體那些功能)
  • 使用多主模式時,不支持針對同一對象但在不同服務器上發出的併發DDL語句和DML語句。在某個對象上發出數據定義語句(DDL)期間,在同一對象上但從不同服務器實例發出併發數據操作語句(DML),可能會導致在不同實例上執行的DDL衝突風險而未被檢測到。(參考組複製的限制)
  1. InnoDB集羣的用戶帳戶
InnoDB集羣中的成員服務器使用三種類型的用戶帳戶。一個 InnoDB 集羣服務器配置帳戶用於爲集羣配置服務器實例。可以爲管理員創建一個或多個 InnoDB 集羣管理員帳戶,以便在集羣安裝後管理服務器實例。可以爲 MySQL Router 實例創建一個或多個 MySQL Router 帳戶,用於連接到集羣。這些用戶帳戶必須存在 InnoDB 集羣中的所有成員服務器上都存在,並且使用相同的用戶名和密碼。
  • InnoDB 集羣服務器配置帳戶
此帳戶用於創建和配置 InnoDB 集羣的成員服務器。每個成員服務器只有一個服務器配置帳戶。集羣中的每個成員服務器必須使用相同的用戶帳戶名和密碼。爲此,你可以在服務器上使用 root 帳戶,但如果這樣做,集羣中每個成員服務器上的 root 帳戶必須具有相同的密碼。出於安全原因,不建議這樣做。
首選方法是使用 clusterAdmin 選項中的 dba.configureInstance()命令創建一個 InnoDB集羣服務器配置賬號。爲提高安全性,請在交互提示下指定密碼,也可以使用 clusterAdminPassword  選項指定密碼。在將成爲 InnoDB 集羣一部分的每個服務器實例上以相同的方式創建相同的帳戶,使用相同的用戶名和密碼——包括你連接以創建集羣的實例,以及之後將加入集羣的實例。
dba.configureInstance()命令會自動授予帳戶所需的權限(你也可以手動設置該帳戶並授權,但不建議這麼做)。除了完整的 MySQL 管理員權限外,該帳戶還需要對 InnoDB 集羣元數據表擁有完整的讀寫權限。
使用 dba.configureInstance()命令創建一個 InnoDB集羣服務器配置賬號不會複製到集羣內的其他服務器上。MySQL Shell 禁用了 dba.configureInstance()命令的二進制日誌記錄。這意味着你必須在每個 MySQL 服務器實例上單獨創建該帳戶。
  • InnoDB 集羣管理員帳戶
這些帳戶在你完成集羣配置之後,可用於管理 InnoDB 集羣。你可以設置多個,每個帳戶必須存在於 InnoDB 集羣中的每個成員服務器上,並具有相同的用戶名和密碼。
爲了給 InnoDB ClusterSet 創建 InnoDB 集羣管理員賬號,你需要在將所有實例添加到集羣后執行 cluster.setupAdminAccount()命令。該命令將使用你給定的用戶名和密碼創建賬號,並賦予必要的權限。使用cluster.setupAdminAccount()創建一個賬號的事務將被寫入到二進制日誌,併發送到集羣內所有其他服務器實例上,用於在這些服務器上創建相同的賬號。(備註:如果主InnoDB 集羣是在MySQL Shell 8.0.20之前版本部署的,cluster.setupAdminAccount()命令可能與 update 選項一起使用,以更新 InnoDB集羣服務器配置帳戶的權限,這是未寫入二進制日誌的命令的特殊用法)
  • MySQL Router 帳戶
這些賬號被 MySQL Router 用於連接到 InnoDB 集羣中的MySQL服務器實例。你可以設置多個此類賬號,每個帳戶必須存在於InnoDB 集羣中的每個成員服務器上,並具有相同的用戶名和密碼。創建 MySQL Router 帳戶的過程與創建 InnoDB 羣集管理員帳戶相同,但使用的是 cluster.setupRouterAccount() 命令。(也會寫binary log 進行同步創建)
InnoDB集羣創建的內部用戶帳戶
作爲使用組複製的一部分,InnoDB 集羣會創建內部恢復用戶,以實現羣集中服務器之間的連接。這些用戶是集羣的內部用戶,生成的用戶名遵循 mysql_innodb_cluster_server_id@% 的命名方案,其中 server_id 對每個實例是唯一的。在 8.0.17 之前的版本中,生成用戶的用戶名遵循 mysql_innodb_cluster_r[10_numbers] 的命名方案。
這些內部用戶使用的主機名設置爲“%”。在 v8.0.17 之前,ipAllowlist 會通過在 ipAllowlist 中每個主機一個賬號來影響主機名行爲。
每個內部用戶都有一個隨機生成的密碼。從 8.0.18 版開始,AdminAPI 允許你更改內部用戶生成的密碼。請參閱【重置恢復帳戶密碼】。隨機生成的用戶將獲得以下授權:GRANT REPLICATION SLAVE ON *.* to internal_user;
內部用戶帳戶在 seed 實例上創建,然後複製到集羣中的其他實例。內部用戶包括:
  • 通過執行 dba.createCluster()命令創建一個新集羣時生成的
  • 通過執行 Cluster.addInstance()命令向集羣添加一個新實例時生成的
  • 使用主要成員正在使用的身份驗證插件時生成的
在 v8.0.17 之前,ipAllowlist 會導致 Cluster.rejoinInstance()命令移除老的內部用戶並生成新的用戶,而不是重用它們。
重置恢復帳戶密碼
從8.0.18版開始,你可以使用 Cluster.resetRecoveryAccountsPassword()命令重置InnoDB羣集創建的內部恢復帳戶的密碼,例如爲了遵循自定義密碼生存期策略。使用 Cluster.resetRecoveryAccountsPassword()命令重置羣集使用的所有內部恢復帳戶的密碼。該命令爲每個聯機實例的內部恢復帳戶設置一個新的隨機密碼,如果無法訪問實例,則操作失敗。你可以使用 force 選項忽略此類脫機的實例,但不建議這樣做,在使用此命令之前將實例重新聯機更安全。此命令僅適用於InnoDB Cluster創建的密碼,不能用於更新手動創建的密碼。(備註:執行此操作的用戶必須具有所有必需的管理權限,尤其是創建用戶權限CREATE USER,以確保無論所需的密碼驗證策略如何,都可以更改恢復帳戶的密碼。換句話說,這與系統變量 password_require_current 是否啓用無關)
  1. InnoDB集羣生產部署
在生產環境中,組成 InnoDB 集羣的MySQL服務器實例運行在以網絡鏈接的多個主機上,而不是一臺機器上。在組建 InnoDB 集羣之前,我們必須將所需的軟件安裝到要作爲集羣服務器實例的每臺機器上。
下圖說明了將組建的 InnoDB 集羣的邏輯架構(IP只是做示例作用):
0
注意:對於生產部署,必須持久化實例上的任何配置變更,如何做到這一點取決於實例上運行的MySQL版本。
爲了將服務器的連接信息傳遞給 AdminAPI,可以使用類似 URI 的連接字符串或數據字典,本例中我們將使用類似 URI 的連接字符串。
 
接下來開始 MySQL InnoDB 集羣的實際安裝部署工作:
一、首先按如下配置準備三臺虛擬機(手動固定IP,Linux遠程客戶端使用的是SecureCRT):
HostName:linux01、linux02、linux03
操作系統:CentOS-7-x86_64
初始內存:2G
初始CPU:1P2C
初始硬盤:40G
網絡模型:Bridge
IP地址:192.168.0.251、192.168.0.252、192.168.0.253
網關地址:192.168.0.1
DNS地址:10.198.1.1,114.114.114.114
0
開啓三臺虛擬機,使用ping命令檢查三臺虛擬機之間的網絡是否互通(還必須可以訪問互聯網),然後對它們進行基本的環境準備工作,包括:
    1. 使用 hostnamectl --static set-hostname <你的主機名> 命令分別修改三臺虛擬機的主機名爲linux01、linux02和linux03,使用 hostnamectl status 命令查看是否修改成功;
    0
      1. 在三臺虛擬機上分別執行 yum install -y lrzsz 、yum install -y rsync 和yum install -y vim 命令,確保後面可能會用到的工具軟件都成功安裝;
      2. 通過 vi /etc/hosts 命令將三臺虛擬機的 hosts 文件內容修改爲如下的值並保存:
      0
       
        1. 通過 reboot -h now 命令分別重啓三臺虛擬機;
        2. 通過 ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa 命令分別在三臺虛擬機上生成RSA密鑰對文件;
        3. 在每臺虛擬機上都執行這三條命令 cat ~/.ssh/id_rsa.pub | ssh root@linux01 "cat - >> ~/.ssh/authorized_keys" 、cat ~/.ssh/id_rsa.pub | ssh root@linux02 "cat - >> ~/.ssh/authorized_keys" 、cat ~/.ssh/id_rsa.pub | ssh root@linux03 "cat - >> ~/.ssh/authorized_keys" ,將自己的RSA公鑰文件內容追加到每臺虛擬機的 authorized_keys 文件中(使三臺虛擬機之間免密登錄,如果SSH未安裝,請先自行安裝);
        4. 在每臺虛擬機上都執行 mkdir /opt/software 和 mkdir /opt/servers 創建我們後面軟件包的存放路徑和安裝路徑;
        二、準備好MySQL Server、MySQL Shell和MySQL Router的安裝包
        到MySQL官網去下載本例要用的MySQL相關組件包,這些包在官網有非常多的版本,下載哪些?怎麼搭配使用?
        本例中我們做的是MySQL 5.7的InnoDB集羣,主包MySQL Server肯定是要選5.7系列的最新免費版,當前(2022年4月)最新免費版爲 mysql-community-server-5.7.37 ,版本名中的 community 代表社區版的意思,也就是免費的,不要去下收費版,你懂的!我們的三臺虛擬機安裝的都是Redhat Linux系列下的 CentOS-7-x86_64 操作系統,所以本次下載的MySQL Server安裝包爲:mysql-community-server-5.7.37-1.el7.x86_64.rpm
        另外,在安裝MySQL Server 5.7.* 時,按官方建議:在大多數情況下,你需要安裝 mysql-community-server、mysql-community-client、mysql-community-libs、mysql-community-common和 mysql-community-libs-compat軟件包,以獲得功能正常的標準MySQL安裝。所以我們要將上述幾個包都下載下來:
        0
        將這些包通過 rz 命令上傳到三臺虛擬機的 /opt/software 目錄下:
        0
         
        對於MySQL Shell和MySQL Router這裏要重點說明一下,因爲你可能在官網上找不到帶 "5.7.*" 字樣的MySQL Shell和MySQL Router !我們在官網的MySQL Shell和MySQL Router的下載頁中找到了如下的一些關於MySQL Shell和MySQL Router的說明:
        “MySQL Shell是一個交互式Javascript、Python或SQL接口,支持MySQL Server的開發和管理,是MySQL Server的一個組件。你可以使用MySQL Shell執行數據查詢和更新以及各種管理操作。強烈建議將MySQL Shell 8.0與MySQL Server 8.0和5.7配合使用。請升級到MySQL Shell 8.0。”
        “MySQL Router是一種輕量級中間件,在應用程序和任何後端MySQL服務器之間提供透明路由。它可以用於各種各樣的用例,例如通過有效地將數據庫流量路由到適當的後端MySQL服務器來提供高可用性和可擴展性。強烈建議將MySQL Router 8.0與MySQL Server 8.0和5.7配合使用。請升級到MySQL Router 8.0。”
        相信讀完上述兩段話,你應該知道了 —— MySQL Server 5.7 使用的MySQL Shell和MySQL Router 都是8.0.*的版本,事實上MySQL官網上目前也只有這個版本系列,連 “Looking for previous GA versions?” 的舊版本導向鏈接都沒有!
        MySQL Shell安裝包爲:mysql-shell-8.0.28-1.el7.x86_64.rpm
        MySQL Router安裝包爲:mysql-router-community-8.0.28-1.el7.x86_64.rpm
        三、安裝好MySQL Server、MySQL Shell和MySQL Router
        1.安裝MySQL Server:
        我們這裏按照官方RPM包安裝說明書進行標準MySQL安裝,在 linux01上執行命令cd /opt/software 轉到MySQL相關安裝包所在目錄,執行如下命令(我加了一個 -y 選項,讓該命令遇到依賴需要下載時進行自動下載):
        $> sudo yum install -y mysql-community-{server,client,common,libs}-*
        安裝過程中可能需要從互聯網上下載一些依賴包,所以在讓相應虛擬機可以連上互聯網,例如:我的需要下載net-tools-2.0-0.25.20131004git.el7.x86_64.rpm 依賴包:
        從上述截圖可以看到,mariadb-libs.x86_64 和 mysql-community-libs-compat 這兩個包將會在後續版本中被淘汰了(這裏不用管它)!由於基本都是本地RPM包,所以安裝過程非常絲滑快速:
        我們知道Linux安裝軟件無非就是解壓縮包並複製文件到指定目錄、創建用戶、修改配置、修改權限和環境變量等,那麼上述安裝命令會將MySQL安裝到那些目錄下呢?下表便是MySQL標準安裝後各文件或資源分發到的位置:
        文件或資源
        位置(Location)
        Client programs and scripts
        /usr/bin
        mysqld server
        /usr/sbin
        Configuration file
        /etc/my.cnf
        Data directory
        /var/lib/mysql
        Error log file
        For RHEL, Oracle Linux, CentOS or Fedora platforms: /var/log/mysqld.log
        For SLES: /var/log/mysql/mysqld.log
        Value of secure_file_priv
        /var/lib/mysql-files
        System V init script
        For RHEL, Oracle Linux, CentOS or Fedora platforms: /etc/init.d/mysqld
        For SLES: /etc/init.d/mysql
        Systemd service
        For RHEL, Oracle Linux, CentOS or Fedora platforms: mysqld
        For SLES: mysql
        Pid file
        /var/run/mysql/mysqld.pid
        Socket
        /var/lib/mysql/mysql.sock
        Keyring directory
        /var/lib/mysql-keyring
        Unix manual pages
        /usr/share/man
        Include (header) files
        /usr/include/mysql
        Libraries
        /usr/lib/mysql
        Miscellaneous support files (for example, error messages, and character set files)
        /usr/share/mysql
        上述安裝命令還將在系統上創建一個名爲 mysql 的用戶和一個名爲 mysql 的組。
        注意:使用較舊的軟件包安裝以前版本的MySQL可能會創建一個名爲 /usr/my.cnf 的配置文件。強烈建議你檢查文件的內容,並將其中所需的設置遷移到文件 /etc/my.cnf 文件,然後刪除 /usr/my.cnf。
        上述安裝命令完成之後,MySQL並不會自動啓動。對於RHEL、Oracle Linux、 CentOS 和 Fedora的系統使用下述命令啓動:
        $> systemctl start mysqld
        對於SLES的系統,將mysqld 換成 mysql 即可!
        如果操作系統已啓用 systemd,則應使用標準systemctl命令(或者參數顛倒的 service命令)來管理 MySQL 服務器服務(如stop、start、status和restart)。默認情況下,mysqld 服務處於啓用狀態,並在系統重新啓動時啓動。請注意,在 systemd 平臺上,某些事情可能會以不同的方式工作:例如,更改數據目錄的位置可能會引發問題。
        $> systemctl {start|stop|restart|status} mysqld
        $> service mysqld {start|stop|restart|status}
        在使用RPM和DEB軟件包進行升級安裝期間,如果在升級時MySQL服務器正在運行,則MySQL服務器將停止,升級完成後MySQL服務器將重新啓動。有一個例外:如果版本性質在升級過程中也發生了變化(例如從社區版轉到了商業版,或者反之亦然),那麼MySQL服務器不會重新啓動。
        在服務器初始啓動時,如果服務器的數據目錄爲空,則會發生以下情況:
        • 服務器會被初始化;
        • 在數據目錄(默認/var/lib/mysql)中生成SSL證書和密鑰文件;
        • 安裝並啓用 validate_password;
        • 將創建超級用戶帳戶 'root'@'localhost' ,爲root賬戶生成一個臨時初始密碼並保存到錯誤日誌文件(默認/var/log/mysqld.log)中。對RHEL、Oracle Linux、CentOS和Fedora系統可使用以下命令提取該密碼:
        $> sudo grep 'temporary password' /var/log/mysqld.log
        對於 SLES 的系統,將文件路徑換成 /var/log/mysql/mysqld.log 即可!
        拿到臨時初始密碼後,接下來要用該密碼登錄MySQL,併爲root賬戶指定一個符合validate_password密碼策略的新密碼:
        $> mysql -uroot -p
        mysql> ALTER USER 'root'@'localhost' IDENTIFIED BY '1qaz@WSX';
        備註:validate_password的默認密碼策略要求密碼長度至少爲8,幷包含至少一個大寫字母、一個小寫字母、一個數字和一個特殊符號!
        如果安裝過程中發生了某些錯誤,你可以到錯誤日誌文件中查看一下詳情(默認/var/log/mysqld.log)。
        如是上述過程都沒有問題的話,接下來我們要創建一個可以遠程登錄到 MySQL Server 的普通賬號,因爲出於安全考慮,超級賬號root默認是隻能在MySQL服務器本機登錄的,我們不要圖方便去改變root賬號的這個默認特性(生產真出了問題你負責不起的)。MySQL服務器本機使用 mysql -uroot -p 登錄MySQL,執行以下命令,創建一個名不myapp的普通賬號,並授以必要的權限:
        mysql> CREATE USER 'myapp'@'%' IDENTIFIED BY 'myapp1@WSX';
        mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,ALTER,DROP ON *.* TO 'myapp'@'%' WITH GRANT OPTION;
        mysql> flush privileges;
        創建賬號時使用的 'myapp'@'%' 其中%號表示該賬號可以在任何客戶端主機上登錄,一般用於給開發人員使用的MySQL賬號纔會這樣設置。爲了安全起見,生產環境一般會固定爲應用程序所在的特定IP或域名(例如'myapp'@'%.example.com');另外授權時使用了 ON *.* ,表示針對所有數據庫的所有對象。爲了安全起見,生產環境一般會固定爲應用程序所要連接的特定數據庫(例如 target_db.* );
        接下來我們嘗試一下在遠程客戶端(例如Navicat上)使用賬號 myapp 和密碼 myapp1@WSX 遠程登錄linux01上的MySQL服務器,但是在此之前我們還有一件重要事情要做——對MySQL使用的遠程連接端口號3306進行防火牆例外設置,並重新載入防火牆:
        $> sudo firewall-cmd --zone=public --add-port=3306/tcp --permanent
        $> sudo firewall-cmd --reload
        注意1:一定要帶上--permanent 參數才能永遠生效,否則系統重啓後丟失,另外 --zone 、--add-port 和 --permanent參數前面是兩個-;
          注意2:一定要重新載入防火牆,讓設置生效;
        使用Windows上的Navicat測試連接:
        按照上述步驟在linux02和linux03服務器上也安裝配置好MySQL,然後我們繼續...
        其它有必要提一下的內容:
        對於某些Linux發行版,可能需要增加 mysqld 可用的文件描述符數量(如何修改就自行查找了)。接下來我們看看mysqld 可用的文件描述符的默認數量:
        可以通過以下命令先查看一下操作系統對 mysqld 進程打開文件數的限制:ps -ef | grep mysqld找到 mysqld 的 pid,再用 cat /proc/<mysqld_pid>/limits | grep files 顯示進程打開文件數的限制:

         

         

        可以看到操作系統層面對 mysqld 進程打開文件數限制在5000,我們使用 root 賬號連接上MySQL 使用 select @@open_files_limit; 命令再看看MySQL自身所做的限制是多少:

         

         

        可以看到MySQL內部對打開文件數限制也是 5000。
        2.安裝MySQL Shell,並使用它的相關命令創建集羣:
        我們先將MySQL Shell的RPM包上傳到上面三臺虛擬機的 /opt/software 目錄下。
        MySQL Shell 是一個可以單獨安裝的組件,目前只能安裝在64位的Windows、Linux和macOS上(僅適用於有限數量的Linux發行版)。
        MySQL Shell的安裝非常簡單,安裝前沒有多餘的配置,只需要執行下 python --version 命令檢查一下系統中是否已經需要的Python依賴(版本最好高於Python 2.7.0),沒問題的話執行命令cd /opt/software 轉到MySQL Shell安裝包所在目錄,再執行下述命令即可:
        $> sudo yum install -y mysql-shell-*
        你也可以明確指定具體的RPM包文件名,例如 sudo yum install -y mysql-router-community-8.0.28-1.el7.x86_64.rpm
        安裝完後,可以執行 mysqlsh 命令驗證是否安裝成功!

         

         

        在其餘兩臺虛擬機上也做同樣的安裝操作就可以了!
        在MySQL Shell命令行窗口可以在JavaScript模式和SQL模式進行切換,默認是JavaScript模式:
        mysql-js> \sql --切換爲SQL模式
        mysql-js> \js --切換爲JavaScript模式
        好,到現在我們搭建 MySQL InnoDB 集羣所需要的軟件基本都已經安裝完成,剩下的工作是使用MySQL Shell AdminAPI把集羣配起來:
          1. 在三個MySQL Server上創建一個 InnoDB 集羣服務器配置帳戶——configer,必須是相同的賬號名稱和密碼,並授以相應的權限:
          $> mysql -uroot -p
          mysql> CREATE USER 'configer'@'%' IDENTIFIED BY 'configer1@WSX';
          mysql> GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,ALTER,DROP ON *.* TO 'configer'@'%' WITH GRANT OPTION;
          mysql> GRANT CREATE USER, FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHUTDOWN, SUPER ON *.* TO 'configer'@'%' WITH GRANT OPTION;
          mysql> GRANT ALTER ROUTINE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, EVENT, EXECUTE, INDEX, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER ON mysql_innodb_cluster_metadata.* TO 'configer'@'%' WITH GRANT OPTION;
          mysql> GRANT ALTER ROUTINE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, EVENT, EXECUTE, INDEX, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER ON mysql_innodb_cluster_metadata_bkp.* TO 'configer'@'%' WITH GRANT OPTION;
          mysql> GRANT ALTER ROUTINE, CREATE ROUTINE, CREATE TEMPORARY TABLES, CREATE VIEW, EVENT, EXECUTE, INDEX, LOCK TABLES, REFERENCES, SHOW VIEW, TRIGGER ON mysql_innodb_cluster_metadata_previous.* TO 'configer'@'%' WITH GRANT OPTION;
          mysql> flush privileges;
            1. 在三個MySQL Server所在虛擬機上用mysqlsh命令打開MySQL Shell,並分執行以下命令將其上的MySQL實例配置爲用於InnoDB集羣的實例(實際上這些命令會查找MySQL的配置文件my.cnf,將集羣需要的配置寫入其中,當然還有其他些方面的配置變更),同時指定 InnoDB 集羣管理員賬號——icadmin,必須是相同的賬號名稱和密碼(注意:MySQL 5.7用的是configureLocalInstance(),不是configureInstance()):
            linux01上:mysql-js> dba.configureLocalInstance("configer@linux01:3306",{clusterAdmin:"'icadmin'@'%'"});
            linux02上:mysql-js> dba.configureLocalInstance("configer@linux02:3306",{clusterAdmin:"'icadmin'@'%'"});
            linux03上:mysql-js> dba.configureLocalInstance("configer@linux03:3306",{clusterAdmin:"'icadmin'@'%'"});

             

             

            完了後根據提示使用 \q命令退出MySQL Shell,然後使用系統命令systemctl restart mysqld 將三臺虛擬機上的MySQL服務重啓。
              1. 使用以下命令重新進入MySQL Shell,並分別驗證三個MySQL Server實例的配置狀態是否已經能夠作爲InnoDB集羣的成員了:
              linux01上:#> mysqlsh --uri icadmin@linux01:3306
              linux01上:mysql-js> dba.checkInstanceConfiguration();
              linux02上:#> mysqlsh --uri icadmin@linux02:3306
              linux02上:mysql-js> dba.checkInstanceConfiguration();
              linux03上:#> mysqlsh --uri icadmin@linux03:3306
              linux03上:mysql-js> dba.checkInstanceConfiguration();

               

               

              當然,你也可以像下面這樣,只在一臺虛擬機的MySQL Shell命令行中將三個實例一起驗證完:
              linux01上:#> mysqlsh
              linux01上:mysql-js> dba.checkInstanceConfiguration('icadmin@linux01:3306');
              linux01上:mysql-js> dba.checkInstanceConfiguration('icadmin@linux02:3306');
              linux01上:mysql-js> dba.checkInstanceConfiguration('icadmin@linux03:3306');
              但不建議你這麼做!一開始我在linux01上做完所有實例的配置驗證,發現所有狀態都是"ok",可是後面將各實例添加到集羣時,發現linux03可以添加到集羣,linux02死活不行。重新在linux01上遠程檢查linux02的配置狀態依舊是 "ok"的,但在linux02本機上檢查卻報出瞭如下的錯誤:

               

               

              各種辦法我都試過了,都沒能解決,最後將linux02重裝系統,重新對其進行配置和安裝MySQL相關組件,然後才加進集羣裏了~~!!!
                1. 我們將linux01規劃爲創建集羣的種子節點,在linux01上使用集羣管理員賬號重新進入MySQL Shell中,執行以下命令創建一個名爲 "myCluster"的集羣:
                linux01上:#> mysqlsh --uri icadmin@linux01:3306
                linux01上:mysql-js> var cluster = dba.createCluster('myCluster');
                在創建集羣添加Seed Instance的過程中可能會報錯,這個時候要 cat /var/log/mysqld.log 打開日誌看看具體報錯,比如我的就是由於防火器阻止了端口33061上的連接所致:
                在防火像中像上面的3306端口一樣給放開就好了(三臺機都要)!
                還要將三臺機子的selinux關閉:
                #> setenforce 0
                #> vi /etc/selinux/config
                將其中的SELINUX設置爲disabled ,然後重新執行 dba.createCluster('myCluster');

                 

                 

                  1. 將其它MySQL實例成員添加到上面創建的集羣中
                  如果你前面使用 dba.createCluster('myCluster');創建集羣時,沒用 var cluster來承接,或者你創建完集羣后重新進入MySQL Shell的,那麼你可以通過下面命令來獲取的目標集羣對象(舊時代叫【句柄】):
                  mysql-js>var cluster=dba.getCluster('myCluster');
                  mysql-js>cluster.addInstance('icadmin@linux02:3306');
                  mysql-js>cluster.addInstance('icadmin@linux03:3306');
                  記住:如果在添加某個實例到集羣中報錯,首先要看看cat /var/log/mysqld.log 打開日誌看看具體報錯!
                  查看集羣簡要信息:
                  mysql-js>cluster.describe();

                   

                   

                  查看集羣詳細信息:
                  mysql-js>cluster.status();

                   

                   

                    1. 測試一下數據庫能否同步——在主節點上新建和刪除數據庫,分別在從庫上驗證是否同步了(這涉及到主節點二進制日誌和從節點中繼日誌配合工作的原理):

                     

                     

                      1. 測試一下故障轉移——在主節點上執行 systemctl stop mysqld 將其停掉(模擬主節點故障,這涉及到GTID相關的主節點選舉原理):

                       

                       

                        1. 測試一下故障恢復後數據庫能否同步——在新主節點上創建新表(注意:InnoDB集羣要求所有表必須有主鍵,我這邊沒有給t1表指定主鍵,後面會影響集羣狀態的),對其增、刪、改等操作,然後重新啓動因故障失聯的舊主節點,看看從故障中恢復的舊主節點上能否同步數據:

                         

                         

                        可以看到,從故障中恢復的舊節點沒有進行最新數據的同步!原因是:從故障中恢復後的舊主節點已經不在再是集羣的主節點了,但它的“super_read_only”選項仍然處於禁用狀態,導致其group_replication功能處於停止狀態!

                         

                         

                          1. 測試一下將故障中恢復的節點重新加入集羣——使用 cluster.rejoinInstance('linux01:3306'); 命令將故障恢復後的失聯節點重新加入集羣(MySQL 8.0.16之後的版本可以配置成故障恢復後自動重新加入集羣!):

                           

                           

                            1. 停止集羣——停止掉集羣內各個實例的group_replication:
                            mysql-js> shell.connect("icadmin@linux01:3306"); --鏈接上某個集羣實例(斷開連接用shell.disconnect();)
                            mysql-js> \sql --切換爲SQL模式
                            mysql-sql> stop group_replication;
                            mysql-sql> \js --切換爲JavaScript模式繼續停掉其它節點的組複製
                            重新加入集羣的故障節點會進行數據的同步,此時你在linux01上也能看到新主節點上新增的t1表了!至此集羣的配置和基本驗證完成!!!
                            可能的集羣問題整理:
                            整個集羣全部中斷後(例如上面的停止集羣或服務器全部重啓後),要在最後更新的實例上使用 var cluster = dba.rebootClusterFromCompleteOutage(); 命令重新啓動集羣。
                            如果集羣發生腦裂(split-brain),那麼你可以將整個集羣的所有實例全部重啓,然後var cluster = dba.rebootClusterFromCompleteOutage(); 命令重新啓動集羣。
                            如是dba.rebootClusterFromCompleteOutage();時出現類似——Dba.rebootClusterFromCompleteOutage: The active session instance (linux01:3306) isn't the most updated in comparison with the ONLINE instances of the Cluster's metadata. Please use the most up to date instance: 'linux03:3306'. (RuntimeError)的錯誤,根據提示——這是因爲你當前所在實例不是最後上次集羣停止前最後更新的實例(GTID不是最新),這時你要根據提示連接到最後更新的實例上(比如這裏提示爲'linux03:3306')執行dba.rebootClusterFromCompleteOutage();重啓集羣:
                            如果出現某個實例的GTID爲空,導致重新加入集羣失敗(ERROR: The target instance 'linux02:3306' has an empty GTID set so it cannot be safely rejoined to the cluster. Please remove it and add it back to the cluster.),那麼先將其移除,再重新加入:
                            mysql-js>cluster.removeInstance("linux02:3306");
                            mysql-js>cluster.addInstance('icadmin@linux02:3306');
                            如果只從庫由於組複製問題無法加回集羣,那可以可暫停從庫的組複製,然後重置它,再重新加入集羣:
                            mysql> stop group_replication; --(暫停組複製)
                            mysql> reset master;
                            mysql> reset slave;
                            mysql-js>cluster.addInstance('icadmin@linux02:3306');
                            mysql-js>cluster.rejoinInstance('icadmin@linux02:3306');
                            如果各種辦法都沒法恢復集羣了,那就只能重置整個集羣了(但是集羣上實例的數據庫數據不要去動):
                            主節點:
                            mysql-js>dba.dropMetadataSchema(); 登錄mysql-shell清空集羣
                            mysql> stop group_replication;
                            mysql> reset master; (清空日誌,確保和從庫的表沒有衝突)
                            mysql> reset slave;
                            其他節點(主要清理和主庫的主從信息, 確保主庫和從庫的表沒有衝突)
                            mysql> stop group_replication;
                            mysql> reset master;
                            mysql> reset slave
                            然後重新創建集羣,添加實例等操作。
                             
                            3.安裝MySQL Router,並使用它實現讀寫分離、負載均衡、故障轉移:
                            從前面出現過的這兩張集羣邏輯架構圖中我們可以清楚的看到:在一個MySQL InnoDB集羣中,MySQL Router 是獨立出來放在集羣外面的,這也是由它在整個集羣中所充當的角色所決定的。

                             

                             

                            MySQL Router作爲整個InnoDB集羣的流量入口(門神),肩負着流量承接、負載均衡、成員管理以及故障轉移的重任(就像前置Nginx服務器一樣),非常有必要使用一臺高性能的獨立服務器進行部署,還要配以足夠的帶寬(事實上,如果僅有一臺集中式MySQL Router服務器的話,它將成爲整個集羣性能和可用性的瓶頸,而解決這個問題方法是接下來要講的內容)。另外, MySQL Shell 作爲InnoDB集羣的管理入口,其實也可以放在整個集羣之上安裝,但在用MySQL Shell的指令dba.configureInstance("configer@linux01:3306");將MySQL Server實例配置爲用於InnoDB集羣的實例時,會在命令執行的本機查找MySQL Server的配置文件my.cnf,找不到將會報錯,所以上面三臺MySQL Server實例所在主機上也安裝上MySQL Shell。
                            實際生產中,爲了獲得最佳性能,MySQL Router通常會與它服務的客戶端應用程序安裝在同一臺主機上,主要原因有:
                            • 這將允許客戶端應用程序使用本地UNIX域socket來與MySQL Router建立鏈接,而不需要走TCP/IP;(注意:本地UNIX域socket只能在應用程序和MySQL Router之間發揮作用,在MySQL Router和MySQL Server之間不行)
                            • 這將減少網絡延遲;
                            • 這將允許MySQL Router直接使用分配給客戶端應用程序的MySQL賬號(例如[email protected])來連接MySQL,而不需要單獨爲MySQL Router的宿主機再分配一個額外的MySQL賬號(例如放大可登錄範圍的賬號myapp@%);
                            • 這將允許MySQL Router跟隨應用程序服務器一起橫向擴展,形成一對一的服務,消除集中式MySQL Router性能和可用性問題;

                             

                             

                            當然,你也可以在網絡上運行多個MySQL Router實例,並且不需要將MySQL Router 獨立部署到一臺機器上。這是因爲MySQL Router不會依賴於何特定的服務器或主機!
                            下面是官方給出的MySQL Router的系統要求:
                            • 硬件:至少需要1核CPU和256MB的內存,建議使用4核CPU和4GB以上的內存;
                            • 磁盤空間:最少需要100MB的空間;
                            • 外部庫依賴:大部分外部依賴都已經打包在了MySQL Router包中(例如protobuf和rapidjson),有一個例外,那就是OpenSSL,它僅在Windows版本的MySQL Router包中有捆綁。類Linux系統的包管理器會自動解決OpenSSL依賴,並根據需要安裝正確的OpenSSL版本。
                            爲了更接近真實生產環境,這裏我們再添加一臺更高配的虛擬機來安裝部署MySQL Router和MySQL Shell(後續的應用程序也將在該虛擬機上部署),配置如下(手動固定IP和主機名):
                            HostName:linux666
                            操作系統:CentOS-7-x86_64
                            初始內存:4G
                            初始CPU:1P4C
                            初始硬盤:20G
                            網絡模型:Bridge
                            IP地址:192.168.0.254
                            網關地址:192.168.0.1
                            DNS地址:10.198.1.1,114.114.114.114

                             

                             

                            注意:我的宿主機是五星級神機能帶得起這麼多虛擬機來,如果你的機器帶不起來,那麼可以將虛擬機的配置稍微降一降,我後面還有其他集羣和服務要用到這些虛擬機,所以配高一點!
                            將新的虛擬機linux666啓動起來,參照之前的三臺虛擬機對它進行環境的基本設置(四臺機子的 /etc/hosts 文件中要把linux666也加進去),最重要的是確保它能與之前的三臺虛擬機網絡互通(否則還路由個錘子)!
                            環境基本設置完成後,我們將MySQL Router包上傳到linux666的/opt/software目錄下。
                            現在來我們安裝MySQL Router:
                            MySQL Router 也是一個可以單獨安裝的組件,使用官方的DEB或RPM包安裝 MySQL Router 會器默認在其運行的主機上創建一個名爲“mysqlrouter”的本地系統用戶和組。使用RPM包安裝MySQL Router也很簡單,只需要執行命令cd /opt/software 轉到MySQL Router安裝包所在目錄,再執行下述命令即可:
                            $> sudo yum install -y mysql-router-*
                            你也可以明確指定具體的RPM包文件名,例如 sudo yum install -y mysql-router-community-8.0.28-1.el7.x86_64.rpm
                            當然你也可以使用rpm命令進行安裝:
                            $> sudo rpm -i mysql-router-community-8.0.28-1.el7.x86_64.rpm
                            關於MySQL Router的卸載可以使用以下命令:
                            $> sudo rpm -e mysql-router
                            或者
                            $> sudo yum remove mysql-router
                            但是這些卸載命令不會刪除MySQL Router的配置文件,你可能需要手動刪除以下路徑下的配置文件:
                            /etc/mysqlrouter
                            /etc/init.d/mysqlrouter
                            /etc/mysqlrouter/mysqlrouter.conf
                            /etc/apparmor.d/usr.sbin.mysqlrouter
                            最後可以再執行一下查找命令,看看哪裏還有餘留的文件,將它們刪除掉
                            $> whereis mysqlrouter
                             
                            接下來配置MySQL Router,實現InnoDB集羣讀寫分離和故障自動轉移:
                              1. 進行MySQL Rouer初始化引導(Bootstrapping) ——連接上InnoDB集羣獲取配集羣配置(執行命令先要先檢查一下集羣的狀態是否正常):
                              MySQL Router通過使用--bootstrap和其他命令行選項爲現有的InnoDB集羣自動配置MySQL Router。在引導過程中,MySQL Route連接到目標集羣,獲取其元數據來實現自我配置(如果對應的InnoDB集羣重新創建了,使用它的MySQL Router需要刪除舊引導生成的配置文件(/etc/mysqlrouter/mysqlrouter.conf),並重新初始化引導)。
                              $> mysqlrouter --bootstrap icadmin@linux01:3306 --user root
                              • icadmin 是InnoDB集羣管理員賬號,linux01:3306是集羣主節點或成員節點,如果給的是成員節點引導模塊會自動轉發到主節點(PRIMARY);
                              • --user root指定的是操作系統賬號,不MySQL Router用於連接到 InnoDB 集羣的賬號,該賬號你可以重新建一個專用的,我這邊直接用了root賬號;
                              [root@linux666 .ssh]# mysqlrouter --bootstrap icadmin@linux01:3306 --user root Please enter MySQL password for icadmin: # Bootstrapping system MySQL Router instance... - Creating account(s) (only those that are needed, if any) - Verifying account (using it to run SQL queries that would be run by Router) - Storing account in keyring - Adjusting permissions of generated files - Creating configuration /etc/mysqlrouter/mysqlrouter.conf Existing configuration backed up to '/etc/mysqlrouter/mysqlrouter.conf.bak' # MySQL Router configured for the InnoDB Cluster 'myCluster' After this MySQL Router has been started with the generated configuration $ /etc/init.d/mysqlrouter restart or $ systemctl start mysqlrouter or $ mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf InnoDB Cluster 'myCluster' can be reached by connecting to: ## MySQL Classic protocol - Read/Write Connections: localhost:6446 - Read/Only Connections: localhost:6447 ## MySQL X protocol - Read/Write Connections: localhost:6448 - Read/Only Connections: localhost:6449 [root@linux666 .ssh]#
                              可以看到配置完成後顯示:MySQL經典協議讀寫操作走的是6446端口,而只讀協議走的是6647端口,有興趣的話你可以進一步查看一下生成的MySQL Router配置文件 /etc/mysqlrouter/mysqlrouter.conf。後面啓動MySQL Router時,如不做特殊指定的話將使用這個生成的默認配置文件!
                              看到端口,我們要第一時間記得對它們進行防火牆例外設置,並重新載入防火牆:
                              $> sudo firewall-cmd --zone=public --add-port=6446/tcp --permanent
                              $> sudo firewall-cmd --zone=public --add-port=6447/tcp --permanent
                              $> sudo firewall-cmd --zone=public --add-port=6448/tcp --permanent
                              $> sudo firewall-cmd --zone=public --add-port=6449/tcp --permanent
                              $> sudo firewall-cmd --reload
                                1. 爲集羣配置 MySQL Router 帳戶:
                                在安裝有MySQL Shell的主機上連接上集羣,使用MySQL Shell AdminAPI爲集羣添加MySQL Router專用賬號(可以多個,但實際上可以不添加MySQL Router賬號,直接使用分配給應用程序的MySQL賬號即可,否則你還得爲這個新添加的專用賬號到MySQL服務器上做授權操作,默認權限很少)。
                                linux01上:#> mysqlsh --uri icadmin@linux01:3306
                                mysql-js>var cluster=dba.getCluster('myCluster');
                                mysql-js>cluster.setupRouterAccount('myrouter');
                                以上命令爲集羣創建了一個可以在任意位置向集羣發起連接的MySQL Router賬號——myrouter@%。如果要限制在某個IP或域名下才能發起連接,可以這樣做:
                                mysql-js>cluster.setupRouterAccount('[email protected]');

                                 

                                 

                                  1. 手動啓動MySQL Rouer:
                                  $> mysqlrouter &
                                  或者
                                  $> mysqlrouter --config=/path/to/file/your_router.conf &
                                  命令末尾的 & 符是爲了讓其以系統後臺進程的方式運行,不致於卡着終端窗口,執行完命令按回車即可!
                                    1. 驗證可以通過MySQL Router連接上MySQL集羣
                                    這一步你可以在linux666上安裝一個純的MySQL Client來做驗證,也可以直接用其他三臺機子上的MySQL客戶端:
                                    $>mysql -u myrouter -h linux666 -P 6446 -p

                                     

                                     

                                    還可以直接在Windows上用Navicat作驗證:

                                     

                                     

                                    講到這裏,順便整理一下應用程序通過MySQL Router連接上MySQL InnoDB集羣裏MySQL Server實例的過程:
                                    • MySQL客戶端或Connector連接器連接到MySQL Router的指定端口,例如這裏的6446或6447;
                                    • MySQL Router檢查可用的MySQL Server實例;
                                    • MySQL Router向合適的MySQL Server實例建立連接並打開(根據端口類型:讀寫(RW)端口發給主節點,只讀(RO)端口會進行負載均衡選取從節點);
                                    • MySQL Router在應用程序和MySQL服務器之間來回轉發數據包。
                                    • 如果連接的MySQL服務器出現故障,MySQL Router將斷開應用程序的連接。然後,應用程序可以重試連接到MySQL Router,MySQL Router會選擇另一個可用的MySQL服務器建立連接。
                                      1. 驗證讀寫分離:
                                      先查看一下InnoDB集羣中三臺MySQL Server實例的server_id是多少,並將它們記下來,分別打開三臺機子配置文件/etc/my.cnf得到結果如下:
                                      linux01上:server_id = 3029772939
                                      linux02上:server_id = 3920259733
                                      linux03上:server_id = 3585953301
                                      而當前集羣的狀態如下圖所示:

                                       

                                       

                                       

                                       

                                      從上面驗證結果可以看到,讀寫(RW)接口的請求發往了主節點,只讀(RO)接口的請求分別發往了從節點。讀寫分離和負載均衡驗證通過,這不是偶然情況,你可以多試幾次!
                                        1. 驗證故障轉移
                                        在上一步的基礎上,保持上一步的各個會話連接不要斷開,直接停掉當前的主節點(linux01上的MySQL Server實例),我們看看會發生什麼:

                                         

                                         

                                         

                                         

                                        我們看到故障轉移在上一步實驗的客戶端會話連接未關閉的情況下就自動發生了,但卻有一個只讀(RO)端口的連接連在了當前的新主節點上!這是爲什麼呢?不是說只讀(RO)端口建立連接時只會選擇從節點嗎?其實原因是:我們是在沒有關閉上一步的會話連接的情況下做的本次實驗,這次關掉舊主節點時,其它節點上原先保持住的會話連接並不會重新建立,只有原來建立在舊的主節點上的連接會重新進行連接!當然後續新發起的連接還是會根據端口類型:讀寫(RW)端口發給主節點,只讀(RO)端口會進行負載均衡選取從節點!
                                        好了,到此我們在CentOS7上MySQL5.7 InnoDB Cluster安裝(一主兩從複製)就已經完成了,裏面關於MySQL InnoDB Cluster利用的Paxos相關的分佈式一致性算法,故障時的主節選舉等,就需要各位自己去深入學習了,這個纔是重點!
                                        還有一個是將MySQL Router配置成隨操作系統一起啓動,安裝過程中自動創建的mysqlrouter.service服務有問題!
                                        後記:
                                        在虛擬機環境下,InnoDB集羣運行一段時間(特別是當宿主機休眠一段時間後),重新查看集羣狀態時,經常會有節點報錯離線—— "ERROR: group_replication has stopped with an error.",去目標節點的查看其MySQL服務器實全日誌tail -300 /var/log/mysqld.log經常看到這樣的報錯信息:[ERROR] Plugin group_replication reported: 'Member was expelled from the group due to network failures, changing member status to ERROR.',有時甚致直接發生腦裂(split-brain,這時你只能重啓所有MySQL Server實例再重新var cluster = dba.rebootClusterFromCompleteOutage(); 命令重新啓動集羣)。
                                        直接打開MySQL客戶端,登錄目標節點,重啓group_replication功能後又能恢復正常,如此反覆很不是爽!
                                        mysql> stop group_replication;
                                        mysql> start group_replication;
                                        mysql> select * from performance_schema.replication_group_members;

                                         

                                         

                                        從官網中找到如下幾個參數:

                                         

                                         

                                         

                                         

                                         
                                        看錶底下的說明,應該是集羣成員嘗試超過group_replication_recovery_retry_count參數設置的次數之後,如果還沒有跟組內的成員取得聯繫,那麼相應成員實例將放棄並停止自身的組複製。而當我的宿主機進入休眠狀態時,主機網卡不工作,虛擬機之間的網絡也變得不可用,該參數默認的10次嘗試很快就用完了!如果是生產環境的網絡不太好的原因,可以在InnoDB集羣成員所有節點上修改這參數的值,將其設置的大一點(對宿主機進入休眠狀態其實沒有多少作用,虛擬機最好將網絡適配器的“複製物理網絡連接狀態(P)”複選框勾上):
                                        mysql> set global group_replication_recovery_retry_count= 64;
                                        改完後記得重新啓動一下集羣:
                                        mysql-js>mysqlsh --uri icadmin@linux01:3306
                                        mysql-js>var cluster = dba.rebootClusterFromCompleteOutage();
                                         
                                        發表評論
                                        所有評論
                                        還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
                                        相關文章