日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

MySQL InnoDB Cluster部署方案与实践

發布時間:2023/12/18 数据库 41 豆豆
生活随笔 收集整理的這篇文章主要介紹了 MySQL InnoDB Cluster部署方案与实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

MySQL InnoDB Cluster

一、InnoDB Cluster 基本概述

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的第三方負載均衡器了)。

基于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 等等。

二、重點知識

2.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 已經被集群中的其他實例使用,那么該操作將失敗并報錯。
  • 從8.0.23版開始,應將MySQL實例配置為使用并行復制申請者(applier)。
  • 在配置 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 文件中的選項覆蓋。

2.2 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 版本的實例。但是對這些實例會有一些限制,并且有一些功能在這版本上不支持。
  • 使用多主模式時,不支持針對同一對象但在不同服務器上發出的并發DDL語句和DML語句。在某個對象上發出數據定義語句(DDL)期間,在同一對象上但從不同服務器實例發出并發數據操作語句(DML),可能會導致在不同實例上執行的DDL沖突風險而未被檢測到。(參考組復制的限制)

2.3 InnoDB集群的用戶賬戶

InnoDB集群中的成員服務器使用三種類型的用戶帳戶。一個 InnoDB 集群服務器配置帳戶用于為集群配置服務器實例。可以為管理員創建一個或多個 InnoDB 集群管理員帳戶,以便在集群安裝后管理服務器實例。可以為 MySQL Router 實例創建一個或多個 MySQL Router 帳戶,用于連接到集群。這些用戶帳戶必須存在 InnoDB 集群中的所有成員服務器上都存在,并且使用相同的用戶名和密碼。

2.3.1 InnoDB 集群服務器配置帳戶

此帳戶用于創建和配置 InnoDB 集群的成員服務器。每個成員服務器只有一個服務器配置帳戶。集群中的每個成員服務器必須使用相同的用戶帳戶名和密碼。為此,你可以在服務器上使用 root 帳戶,但如果這樣做,集群中每個成員服務器上的 root 帳戶必須具有相同的密碼。出于安全原因,不建議這樣做。

首選方法是使用 clusterAdmin 選項中的 dba.configureInstance()命令創建一個 InnoDB集群服務器配置賬號。為提高安全性,請在交互提示下指定密碼,也可以使用 clusterAdminPassword 選項指定密碼。在將成為 InnoDB 集群一部分的每個服務器實例上以相同的方式創建相同的帳戶,使用相同的用戶名和密碼——包括你連接以創建集群的實例,以及之后將加入集群的實例。

dba.configureInstance()命令會自動授予帳戶所需的權限(你也可以手動設置該帳戶并授權,但不建議這么做)。除了完整的 MySQL 管理員權限外,該帳戶還需要對 InnoDB 集群元數據表擁有完整的讀寫權限。

使用 dba.configureInstance()命令創建一個 InnoDB集群服務器配置賬號不會復制到集群內的其他服務器上。MySQL Shell 禁用了 dba.configureInstance()命令的二進制日志記錄。這意味著你必須在每個 MySQL 服務器實例上單獨創建該帳戶。

2.3.2 InnoDB 集群管理員帳戶

這些帳戶在你完成集群配置之后,可用于管理 InnoDB 集群。你可以設置多個,每個帳戶必須存在于 InnoDB 集群中的每個成員服務器上,并具有相同的用戶名和密碼。

為了給 InnoDB ClusterSet 創建 InnoDB 集群管理員賬號,你需要在將所有實例添加到集群后執行 cluster.setupAdminAccount()命令。該命令將使用你給定的用戶名和密碼創建賬號,并賦予必要的權限。使用cluster.setupAdminAccount()創建一個賬號的事務將被寫入到二進制日志,并發送到集群內所有其他服務器實例上,用于在這些服務器上創建相同的賬號。(備注:如果主InnoDB 集群是在MySQL Shell 8.0.20之前版本部署的,cluster.setupAdminAccount()命令可能與 update 選項一起使用,以更新 InnoDB集群服務器配置帳戶的權限,這是未寫入二進制日志的命令的特殊用法)

2.3.3 MySQL Router 帳戶

這些賬號被 MySQL Router 用于連接到 InnoDB 集群中的MySQL服務器實例。你可以設置多個此類賬號,每個帳戶必須存在于InnoDB 集群中的每個成員服務器上,并具有相同的用戶名和密碼。創建 MySQL Router 帳戶的過程與創建 InnoDB 群集管理員帳戶相同,但使用的是 cluster.setupRouterAccount() 命令。(也會寫binary log 進行同步創建)

2.3.4 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()命令移除老的內部用戶并生成新的用戶,而不是重用它們。

2.3.5 重置恢復帳戶密碼

從8.0.18版開始,你可以使用 Cluster.resetRecoveryAccountsPassword()命令重置InnoDB群集創建的內部恢復帳戶的密碼,例如為了遵循自定義密碼生存期策略。使用 Cluster.resetRecoveryAccountsPassword()命令重置群集使用的所有內部恢復帳戶的密碼。該命令為每個聯機實例的內部恢復帳戶設置一個新的隨機密碼,如果無法訪問實例,則操作失敗。你可以使用 force 選項忽略此類脫機的實例,但不建議這樣做,在使用此命令之前將實例重新聯機更安全。此命令僅適用于InnoDB Cluster創建的密碼,不能用于更新手動創建的密碼。

備注:執行此操作的用戶必須具有所有必需的管理權限,尤其是創建用戶權限CREATE USER,以確保無論所需的密碼驗證策略如何,都可以更改恢復帳戶的密碼。換句話說,這與系統變量 password_require_current 是否啟用無關。

三、生產環境部署

在生產環境中,組成 InnoDB 集群的MySQL服務器實例運行在以網絡鏈接的多個主機上,而不是一臺機器上。在組建 InnoDB 集群之前,我們必須將所需的軟件安裝到要作為集群服務器實例的每臺機器上。

下圖說明了將組建的 InnoDB 集群的邏輯架構(IP只是做示例作用):

注意:對于生產部署,必須持久化實例上的任何配置變更,如何做到這一點取決于實例上運行的MySQL版本。

為了將服務器的連接信息傳遞給 AdminAPI,可以使用類似 URI 的連接字符串或數據字典,本例中我們將使用類似 URI 的連接字符串。

3.1 環境規劃

IP地址主機名角色操作系統MySQL版本
192.168.10.51node1MGR/mysqlshellCentOS 7.9mysql 8.0.31
192.168.10.52node2MGR/mysqlshellCentOS 7.9mysql 8.0.31
192.168.10.53node3MGR/mysqlshellCentOS 7.9mysql 8.0.31
192.168.10.54node0mysqlrouter/mysqlshellCentOS 7.9mysql 8.0.31

3.1.1基礎環境準備

  • 關閉防火墻
#在每個節點執行 systemctl disable firewalld systemctl stop firewalld
  • 永久關閉selinux
#在每個節點執行 sed -i 's/^ *SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config
  • 設置主機名
#在node1執行 hostnamectl set-hostname node1 #在node2執行 hostnamectl set-hostname node2 #在node3執行 hostnamectl set-hostname node3 #在node0執行 hostnamectl set-hostname node0#沒每個節點執行 cat >> /etc/hosts << EOF 192.168.10.51 node1 192.168.10.52 node2 192.168.10.53 node3 192.168.10.54 node0 EOF
  • 配置SSH互信
#在每個節點分別生成私鑰對 ssh-keygen -t rsa #在node1,根據提示完成操作 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.52 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.53 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.54#在node2,根據提示完成操作 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.51 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.53 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.54#在node3,根據提示完成操作 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.51 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.52 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.54#在node0,根據提示完成操作 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.51 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.52 ssh-copy-id -i /root/.ssh/id_rsa.pub 192.168.10.53
  • yum配置

離線環境下,需要為每個節點配置本地yum源。

#將鏡像文件mount至/media [root@node1 ~]# mount -o loop -t iso9660 CentOS-7-x86_64-DVD-2009.iso /media [root@node1 ~]# cat /etc/yum.repos.d/local.repo [local] name=local baseurl=file:///media gpgcheck=0 enabled=1 gpgkey=file:///media/RPM-GPG-KEY-CentOS-7 #校驗yum [root@node1 ~]# yum clean all

3.2 安裝mysql

前往mysql官方下載地址:https://dev.mysql.com/downloads/。下載操作系統適配的MySQL Shell安裝包,MySQL Router安裝包以及MySQL Server。以下以8.0.31為例:

將以上文件上傳至各個服務器臨時安裝目錄,準備進行下一步安裝。

3.2.1 安裝3個數據庫實例

安裝并初始化3個數據庫實例,這里步驟省略,跟安裝部署MySQL步驟一樣,以node1為例進行說明。

#清理操作系統自帶的 MySQL或者 Mariadb rpm -qa | grep mariadb | xargs rpm -e --nodeps rpm -qa | grep mysql | xargs rpm -e --nodeps#解壓mysql安裝壓縮包 tar -xvf mysql-8.0.31-1.el7.x86_64.rpm-bundle.tar #yum安裝mysql server相關的安裝包,可以自動處理依賴關系 yum install -y mysql-community-* #改命令安裝mysql全部包 yum install -y mysql-community-{server,client,common,libs}-*#亦有此命令安裝mysql基礎包 #以上兩種安裝方式都可以,一個是安裝全部安裝包,一個是安裝基本安裝包。建議全部安裝。

3.2.2 初始化3個數據庫實例

在第一次啟動的/var/log/mysqld.log中找到初始密碼,并使用該密碼進行登錄。而后分別在每個數據庫節點執行以下操作。

#啟動mysql [root@node1 ~]# systemctl start mysqld [root@node1 ~]# cat /var/log/mysqld.log | grep 'temporary password' 2022-11-13T09:54:43.615664Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: oVdjq0vrAd/C #登錄并修改root用戶初始密碼 [root@node1 ~]# mysql -u root -p mysql> alter user 'root'@'localhost' identified with mysql_native_password by 'Abcd@1234'; #修改root訪問權限 mysql> use mysql; mysql> update user set host='%' where user='root'; mysql> grant all on *.* to 'root'@'%' with grant option;

3.2.3 在所有節點安裝MySQL Shell

yum install -y mysql-shell-8.0.31-1.el7.x86_64.rpm

3.3 InnoDB Cluster 配置及初始化

因root用戶權限較大,不建議將其作為集群配置用戶。可以參考以下權限,新建用戶。

CREATE USER 'ic_admin'@'%' IDENTIFIED BY 'Abcd@1234'; GRANT SELECT,INSERT,UPDATE,DELETE,CREATE,ALTER,DROP ON *.* TO 'ic_admin'@'%' WITH GRANT OPTION; GRANT CREATE USER, FILE, PROCESS, RELOAD, REPLICATION CLIENT, REPLICATION SLAVE, SHUTDOWN, SUPER ON *.* TO 'ic_admin'@'%' WITH GRANT OPTION; 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 'ic_admin'@'%' WITH GRANT OPTION; 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 'ic_admin'@'%' WITH GRANT OPTION; 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 'ic_admin'@'%' WITH GRANT OPTION; GRANT CLONE_ADMIN, CONNECTION_ADMIN, EXECUTE, GROUP_REPLICATION_ADMIN, PERSIST_RO_VARIABLES_ADMIN, REPLICATION_APPLIER, REPLICATION_SLAVE_ADMIN, ROLE_ADMIN, SYSTEM_VARIABLES_ADMIN ON *.* TO 'ic_admin'@'%' WITH GRANT OPTION; flush privileges;

在三個MySQL Server所在虛擬機上用mysqlsh命令打開MySQL Shell,并分執行以下命令將其上的MySQL實例配置為用于InnoDB集群的實例(實際上這些命令會查找MySQL的配置文件my.cnf,將集群需要的配置寫入其中,當然還有其他些方面的配置變更),同時指定 InnoDB 集群管理員賬號——icadmin,必須是相同的賬號名稱和密碼(注意:MySQL 5.7用的是configureLocalInstance(),不是configureInstance()):

3.3.1 節點配置檢查

  • 檢查

執行每個節點的參數及權限配置預需求檢測。

mysqlsh ic_admin@node1 MySQL node1:33060+ ssl JS > dba.checkInstanceConfiguration('ic_admin@node1') MySQL node1:33060+ ssl JS > dba.checkInstanceConfiguration('ic_admin@node2') MySQL node1:33060+ ssl JS > dba.checkInstanceConfiguration('ic_admin@node3')

檢測通過會顯示如下:
檢測失敗會顯示如下:

  • 配置

對每個節點,通過dba.configureInstance()進行集群相關信息配置。

MySQL node1:33060+ ssl JS > dba.configureInstance('ic_admin@node1') MySQL node1:33060+ ssl JS > dba.configureInstance('ic_admin@node2') MySQL node1:33060+ ssl JS > dba.configureInstance('ic_admin@node3')

以下為對node1節點的配置,在交互式窗口中輸入’y’進行確認。執行完成后,再次通過上面的檢測命令進行每個節點檢測,直到所有節點狀態都是ok為止。

MySQL node1:33060+ ssl JS > dba.configureInstance('ic_admin@node1') Configuring local MySQL instance listening at port 3306 for use in an InnoDB cluster...This instance reports its own address as node1:3306 Clients and other cluster members will communicate with it through this address by default. If this is not correct, the report_host MySQL system variable should be changed.applierWorkerThreads will be set to the default value of 4.NOTE: Some configuration options need to be fixed: +----------------------------------------+---------------+----------------+--------------------------------------------------+ | Variable | Current Value | Required Value | Note | +----------------------------------------+---------------+----------------+--------------------------------------------------+ | binlog_transaction_dependency_tracking | COMMIT_ORDER | WRITESET | Update the server variable | | enforce_gtid_consistency | OFF | ON | Update read-only variable and restart the server | | gtid_mode | OFF | ON | Update read-only variable and restart the server | | server_id | 1 | <unique ID> | Update read-only variable and restart the server | +----------------------------------------+---------------+----------------+--------------------------------------------------+Some variables need to be changed, but cannot be done dynamically on the server. Do you want to perform the required configuration changes? [y/n]: y Do you want to restart the instance after configuring it? [y/n]: y Configuring instance... The instance 'node1:3306' was configured to be used in an InnoDB cluster. Restarting MySQL... NOTE: MySQL server at node1:3306 was restarted.

3.3.2 創建集群

  • 創建集群

將node1規劃為創建集群的種子節點,在node1上使用集群管理員賬號重新進入MySQL Shell中,執行以下命令創建一個名為 "myCluster"的集群:

[root@node1 software]# mysqlsh --uri ic_admin@node1 MySQL Shell 8.0.31Copyright (c) 2016, 2022, Oracle and/or its affiliates. Oracle is a registered trademark of Oracle Corporation and/or its affiliates. Other names may be trademarks of their respective owners.Type '\help' or '\?' for help; '\quit' to exit. Creating a session to 'ic_admin@node1' Fetching schema names for auto-completion... Press ^C to stop. Your MySQL connection id is 22 (X protocol) Server version: 8.0.31 MySQL Community Server - GPL No default schema selected; type \use <schema> to set one. #在創建集群添加Seed Instance的過程中可能會報錯,這個時候要 cat /var/log/mysqld.log 打開日志看看具體報錯,比如我的就是由于防火器阻止了端口33061上的連接所致:MySQL node1:33060+ ssl JS > var cluster=dba.createCluster('myCluster') A new InnoDB Cluster will be created on instance 'node1:3306'.Validating instance configuration at node1:3306...This instance reports its own address as node1:3306Instance configuration is suitable. NOTE: Group Replication will communicate with other members using 'node1:3306'. Use the localAddress option to override.Creating InnoDB Cluster 'myCluster' on 'node1:3306'...Adding Seed Instance... Cluster successfully created. Use Cluster.addInstance() to add MySQL instances. At least 3 instances are needed for the cluster to be able to withstand up to one server failure.
  • 添加節點

如果你前面使用 dba.createCluster(‘myCluster’);創建集群時,沒用 var cluster來承接,或者你創建完集群后重新進入MySQL Shell的,那么你可以通過下面命令來獲取的目標集群對象(舊時代叫【句柄】):

MySQL node1:33060+ ssl JS > var cluster=dba.getCluster('myCluster') #添加節點MySQL node1:33060+ ssl JS > cluster.addInstance('ic_admin@node2')MySQL node1:33060+ ssl JS > cluster.addInstance('ic_admin@node3')

添加節點顯示如下:

3.3.3 查看集群

#查看集群狀態MySQL node1:33060+ ssl JS > cluster.status()

至此,集群配置完成。查看集群狀態,正常顯示如下,所有節點ONLINE。

3.4 安裝mysql router

3.4.1 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賬號(例如myapp@192.168.0.254)來連接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版本。

3.4.2 安裝mysql router

在node4安裝mysql router

yum install -y mysql-router-community-8.0.31-1.el7.x86_64.rpm

3.4.3 配置mysql router

  • 配置MySQL Router,實現InnoDB集群讀寫分離和故障自動轉移:

MySQL Router通過使用–bootstrap和其他命令行選項為現有的InnoDB集群自動配置MySQL Router。在引導過程中,MySQL Route連接到目標集群,獲取其元數據來實現自我配置(如果對應的InnoDB集群重新創建了,使用它的MySQL Router需要刪除舊引導生成的配置文件(/etc/mysqlrouter/mysqlrouter.conf),并重新初始化引導)。

mysqlrouter --bootstrap ic_admin@node1:3306 --user root # ic_admin 是InnoDB集群管理員賬號,node1:3306是集群主節點或成員節點,如果給的是成員節點引導模塊會自動轉發到主節點(PRIMARY); # --user root指定的是操作系統賬號,不MySQL Router用于連接到 InnoDB 集群的賬號,該賬號你可以重新建一個專用的,也可以直接用了root賬號;

可以看到配置完成后顯示:MySQL經典協議讀寫操作走的是6446端口,而只讀協議走的是6647端口,有興趣的話你可以進一步查看一下生成的MySQL Router配置文件 /etc/mysqlrouter/mysqlrouter.conf。后面啟動MySQL Router時,如不做特殊指定的話將使用這個生成的默認配置文件!

如果開啟了防火墻,要第一時間記得對它們進行防火墻例外設置,并重新載入防火墻。

  • 為集群配置 MySQL Router 帳戶:

在安裝有MySQL Shell的主機上連接上集群,使用MySQL Shell AdminAPI為集群添加MySQL Router專用賬號(可以多個,但實際上可以不添加MySQL Router賬號,直接使用分配給應用程序的MySQL賬號即可,否則你還得為這個新添加的專用賬號到MySQL服務器上做授權操作,默認權限很少)。

[root@node4 software]# mysqlsh --uri ic_admin@node1MySQL node1:33060+ ssl JS > var cluster =dba.getCluster('myCluster')MySQL node1:33060+ ssl JS > cluster.setupRouterAccount('myrouter') #以上命令為集群創建了一個可以在任意位置向集群發起連接的MySQL Router賬號——myrouter@%。如果要限制在某個IP或域名下才能發起連接,可以這樣做:MySQL node1:33060+ ssl JS > cluster.setupRouterAccount('myrouter@192.168.10.%')

輸入密碼和再次確認密碼后,賬戶創建成功,顯示如下:

注意:該命令創建的myrouter用戶只有基礎權限,在實際應用中,應當秉承最小權限原則,在主節點對myrouter用戶進行正確的授權。

3.4.4 啟動mysql router

mysqlrouter -c /etc/mysqlrouter/mysqlrouter.conf &

3.4.5 驗證

在只裝有mysql client的服務器或者其他客戶端上面進行登錄、數據操作等驗證。以windows端navicat客戶端為例進行驗證。

以上配置中,主機地址為mysql routher服務器的ip地址,端口為讀寫端口,用戶名和密碼為3.4.3中配置的MySQL Router 帳戶。同樣的方式進行只讀端口驗證。

應用程序通過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服務器建立連接。

3.5 驗證

3.5.1 讀寫分離

通過Mysql命令show variables like ‘server_id’; 先查看一下InnoDB集群中三臺MySQL Server實例的server_id是多少,并將它們記下來:

node1:2861026507

node2:770008088

node3:1770854672

可以看到,讀寫請求被分發到node1,只讀請求分別被分發到node2和node3:

3.5.2 故障轉移

在上一步的基礎上,保持上一步的各個會話連接不要斷開,直接停掉當前的主節點(node1上的MySQL Server實例),我們看看會發生什么:

登錄node2節點,查看集群狀態:

我們看到故障轉移在上一步實驗的客戶端會話連接未關閉的情況下就自動發生了,但卻有一個只讀(RO)端口的連接連在了當前的新主節點上!這是為什么呢?不是說只讀(RO)端口建立連接時只會選擇從節點嗎?其實原因是:我們是在沒有關閉上一步的會話連接的情況下做的本次實驗,這次關掉舊主節點時,其它節點上原先保持住的會話連接并不會重新建立,只有原來建立在舊的主節點上的連接會重新進行連接!當然后續新發起的連接還是會根據端口類型:讀寫(RW)端口發給主節點,只讀(RO)端口會進行負載均衡選取從節點!

四、集群相關操作

4.1 查看集群狀態

cluster.status()

MySQL node1:33060+ ssl JS > var cluster=dba.getCluster('myCluster')MySQL node1:33060+ ssl JS > cluster.status() {"clusterName": "myCluster", "defaultReplicaSet": {"name": "default", "primary": "node1:3306", "ssl": "REQUIRED", "status": "OK", "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", "topology": {"node1:3306": {"address": "node1:3306", "memberRole": "PRIMARY", "mode": "R/W", "readReplicas": {}, "replicationLag": "applier_queue_applied", "role": "HA", "status": "ONLINE", "version": "8.0.31"}, "node2:3306": {"address": "node2:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": "applier_queue_applied", "role": "HA", "status": "ONLINE", "version": "8.0.31"}, "node3:3306": {"address": "node3:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": "applier_queue_applied", "role": "HA", "status": "ONLINE", "version": "8.0.31"}}, "topologyMode": "Single-Primary"}, "groupInformationSourceMember": "node1:3306" }MySQL node1:33060+ ssl JS >

4.2 配置節點權重

memberWeight選項的值域為0到100之間的整數,缺省值為50。該值是故障轉移時自動選舉主節點的百分比權重,具有較高memberWeight值的實例更有可能在單主群集中被選為主節點

// 在集群創建完成后修改權重 var cluster = dba.getCluster() cluster.setInstanceOption('node1:3306','memberWeight',100) cluster.setInstanceOption('node2:3306','memberWeight',50) cluster.setInstanceOption('node3:3306','memberWeight',25)// 查看集群的參數配置(包括memberWeight優先級配置) cluster.options()// 在集群創建時配置 dba.createCluster('myCluster', {memberWeight:75}) // 第一個節點配置方式 var cluster = dba.getCluster() cluster.addInstance('node2:3306',{memberWeight:50}) cluster.addInstance('node3:3306',{memberWeight:25})

4.3 將節點重新加入集群

狀態為mssing的節點,通常是組復制關閉或中斷狀態,可以用cluster.rejoinInstance()重新加入集群,會重新對該節點設置MGR相關參數(持久化到mysqld-auto.conf中)

4.3.1 rejoinInstance

{"node1:3306": {"address": "node1:3306", "memberRole": "PRIMARY", "mode": "R/W", "readReplicas": {}, "replicationLag": "applier_queue_applied", "role": "HA", "status": "ONLINE", "version": "8.0.31"}, "node2:3306": {"address": "node2:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": "applier_queue_applied", "role": "HA", "status": "(MISSING)", "version": "8.0.31"}, "node3:3306": {"address": "node3:3306", "memberRole": "SECONDARY", "mode": "R/O", "readReplicas": {}, "replicationLag": "applier_queue_applied", "role": "HA", "status": "ONLINE", "version": "8.0.31"} }// 重新加入集群 cluster.rejoinInstance("ic_admin@node2:3306")

4.3.2 removeInstance && addInstance

如果一些參數做了修改,如server_uuid變更,導致rejoin失敗,則需要將節點從集群中刪除后重新加入

cluster.removeInstance("root@node2:3306",{force:true}) cluster.rescan() cluster.addInstance("root@node2:3306")

4.4 集群多數節點異?;謴?/h3>

當集群多個節點異常,則失去了仲裁機制,剩下的一個節點

// 將集群剝離為單節點運行 JS > cluster.forceQuorumUsingPartitionOf("ic_admin@node3:3306")// 重新加另外2個節點加入 JS > cluster.rejoinInstance("ic_admin@node1:3306") JS > cluster.rejoinInstance("ic_admin@node2:3306")

4.5 完整關閉的集群如何恢復

每個節點都是正常的停止且正常的觸發stop group_replication停止的,當重新啟動時如果手工我們需要做以下操作才可拉起集群

  • 判斷哪個節點的GTID最新

  • 將最新的GTID節點group_replication_bootstrap_group設置為on表示以這個節點為基礎啟動組復制

  • 再將其他節點的組復制啟動,集群恢復

我們也可以用mysqlsh的功能來讓其自行判斷最新數據的節點,再采用dba.rebootClusterFromCompleteOutage()方式啟動集群

// 通過node1節點觸發命令 MySQL node1:3306 ssl JS > dba.rebootClusterFromCompleteOutage() Restoring the default cluster from complete outage...// 檢測到node2服務器也包含在集群中,確認添加 The instance 'node2:3306' was part of the cluster configuration. Would you like to rejoin it to the cluster? [y/N]: y// 檢測到node3服務器也包含在集群中,確認添加 The instance 'node3:3306' was part of the cluster configuration. Would you like to rejoin it to the cluster? [y/N]: y// 檢測到node1不是最新的節點,node2才是 Dba.rebootClusterFromCompleteOutage: The active session instance (node1: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: 'node2:3306'. (RuntimeError)// 重新連接到node2上執行相同操作 MySQL node1:3306 ssl JS > \connect "ic_admin@node2:3306" MySQL node1:3306 ssl JS > dba.rebootClusterFromCompleteOutage()// 完成后查看集群狀態是否正常 var cluster = dba.getCluster() cluster.status()

4.6 集群節點角色切換

在MGR的管理下提供了一下3中方式進行角色切換,mysqlsh對其進行了封裝調用

  • group_replication_set_as_primary(member_uuid);
    • cluster.setPrimaryInstance("IP:PORT")
  • group_replication_switch_to_single_primary_mode()
    • cluster.switchToSinglePrimaryMode("IP:PORT")
  • group_replication_switch_to_multi_primary_mode()
    • cluster.switchToMultiPrimaryMode()

4.6.1 單主模式-指定主節點切換

var cluster = dba.getCluster() cluster.setPrimaryInstance('node2:3306') cluster.status()

切換結果如下:

4.6.2 單主模式和多主模式相互切換

// 切換為多主模式 var cluster = dba.getCluster() cluster.switchToMultiPrimaryMode()// 指定明確的主節點將多主模式切換為單主模式 cluster.switchToSinglePrimaryMode("node1:3306")

4.7 參數配置

可以用cluster.options()查看當前集群的配置屬性,集群參數配置分為兩種方式:

  • cluster.setOption() 用來設置所有節點的參數
  • cluster.setInstanceOption() 用來對指定節點配置屬性
// 將所有節點的權重都改為50/重新加入集群重試次數改為5次 var cluster = dba.getCluster() cluster.setOption("memberWeight",50) cluster.setOption("autoRejoinTries",5)// 將其中一個節點的權重改為75/重新加入集群重試次數改為10次 cluster.setInstanceOption("node1:3306","memberWeight",75) cluster.setInstanceOption("node1:3306","autoRejoinTries",10)

4.8 銷毀集群

刪除與群集關聯的所有元數據和配置,并禁用實例上的組復制,但不會刪除在實例之間復制的任何數據。要再次創建集群,使用,dba.createCluster()

var cluster = dba.getCluster() cluster.dissolve()

4.9 常見錯誤

4.9.1 getCluster() 報錯

// 獲取集群報錯,集群中的該節點MGR功能未啟動MySQL 10.186.63.65:3310 ssl JS > var cluster = dba.getCluster() Dba.getCluster: This function is not available through a session to a standalone instance (metadata exists, instance belongs to that metadata, but GR is not active) (RuntimeError)// 可以切換到sql模式查看集群當前狀態 // 可以看到當前集群只有一個節點且處于OFFLINE狀態MySQL 10.186.63.65:3310 ssl SQL > \sql select * from performance_schema.replication_group_members\G *************************** 1. row ***************************CHANNEL_NAME: group_replication_applierMEMBER_ID: 67c08e33-92c4-11eb-803d-02000aba3f41MEMBER_HOST: 10.186.63.65MEMBER_PORT: 3310MEMBER_STATE: OFFLINEMEMBER_ROLE: MEMBER_VERSION: 1 row in set (0.0038 sec)-- 可以將該節點作為引導節點啟動集群 set global group_replication_bootstrap_group=on; start group_replication;-- 啟動完畢后需關閉該參數 set global group_replication_bootstrap_group=off;-- 再次查看可看到第一個節點恢復正常MySQL 10.186.63.65:3310 ssl SQL > select * from performance_schema.replication_group_members\G *************************** 1. row ***************************CHANNEL_NAME: group_replication_applierMEMBER_ID: 67c08e33-92c4-11eb-803d-02000aba3f41MEMBER_HOST: 10.186.63.65MEMBER_PORT: 3310MEMBER_STATE: ONLINEMEMBER_ROLE: PRIMARY MEMBER_VERSION: 8.0.22 1 row in set (0.0016 sec)

4.9.2 addInstance 報錯 Unknown MySQL server host

報這個錯誤需要配置/etc/hosts將主機名和IP對應關系配置上

Cluster.addInstance: Unknown MySQL server host '10-186-63-65' (2) (MySQL Error 2005)// cluster.status() 命令也會有如下顯示 "shellConnectError": "MySQL Error 2005 (HY000): Unknown MySQL server host '10-186-63-65' (2)",

4.9.3 清理殘留的mgr信息

dba.dropMetadataSchema()

Dba.checkInstanceConfiguration: Dba.checkInstanceConfiguration: This function is not available through a session to a standalone instance (metadata exists, instance belongs to that metadata, but GR is not active) (RuntimeError)

4.9.4 克隆插件不能設置為force_plus_permanent

在多次對同一個實例做集群初始化時,不管是全量還是增量都會對克隆插件做一次重新加載,會如果對克隆插件開啟了force_plus_permanent屬性,則無法卸載。

Cluster.addInstance: error uninstalling plugin 'clone': 10.186.63.67:3310: Plugin 'clone' is force_plus_permanent and can not be unloaded (RuntimeError)

總結

以上是生活随笔為你收集整理的MySQL InnoDB Cluster部署方案与实践的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。