MySQL InnoDB Cluster


InnoDB Cluster 基本概述

InnoDB Cluster是MySQL官方實現高可用+讀寫分離的架構方案,其中包含以下組件

  • MySQL Group Replication,簡稱MGR,是MySQL的主從同步高可用方案,包括數據同步及角色選舉
  • mysqlshell 是InnoDB Cluster的管理工具,用來創建和管理集群
  • mysqlrouter 是業務流量入口,支持對MGR的主從角色判斷,可以配置不同的端口分別對外提供讀寫服務,實現讀寫分離

InnoDB Cluster 基礎信息

IP地址 端口 角色 版本
10.186.63.179 6000/6001 mysqlrouter/mysqlshell MySQL Enterprise 8.0.22
10.186.63.65 3310 MGR/mysqlshell MySQL Enterprise 8.0.22
10.186.63.66 3310 MGR/mysqlshell MySQL Enterprise 8.0.22
10.186.63.66 3310 MGR/mysqlshell MySQL Enterprise 8.0.22

InnoDB Cluster 安裝配置

1. 安裝mysqlshell/mysqlrouter

mysqlshell和mysqlrouter可直接從官方網站下載對應操作系統版本軟件包即可,以RHEL7系統為例安裝

rpm -ivh mysql-router-commercial-8.0.22-1.1.el7.x86_64.rpm
rpm -ivh mysql-shell-commercial-8.0.22-1.1.el7.x86_64.rpm

2. 安裝MySQL數據庫

安裝過程省略,只需要按照配置列表初始化生成3個數據庫實例,由於默認root只允許本地登錄,為方便管理,需要額外在每個實例下創建一個擁有遠程訪問的權限用戶,如下為例:

-- 關閉會話級別binlog日志
set session sql_log_bin=off;

-- 創建遠程管理用戶並授權
create user root identified by 'root';
grant all on *.* to root with grant option;

3. InnoDB Cluster 初始化

3.1 參數及權限配置預需求檢測

mysqlsh root@10.186.63.65:3310 --js
// 檢查實例是否符合InnoDB Cluster的參數及權限配置要求
dba.checkInstanceConfiguration('root@10.186.63.65:3310')
dba.checkInstanceConfiguration('root@10.186.63.66:3310')
dba.checkInstanceConfiguration('root@10.186.63.67:3310')

如果不滿足要求則會報錯,如當權限不足時報錯並提升授予以下權限

3.2 初始化InnoDB Cluster相關配置

mysqlsh root@10.186.63.65:3310 --js
// 對實例配置InnoDB Cluster相關參數
dba.configureInstance('root@10.186.63.65:3310',{clusterAdmin: "'mgr_admin'@'%'",clusterAdminPassword:"mgr_admin"})
dba.configureInstance('root@10.186.63.66:3310',{clusterAdmin: "'mgr_admin'@'%'",clusterAdminPassword:"mgr_admin"})
dba.configureInstance('root@10.186.63.67:3310',{clusterAdmin: "'mgr_admin'@'%'",clusterAdminPassword:"mgr_admin"})

3.3 創建集群/添加節點

需使用mysqlsh連接到任意一個節點后操作
初始化會執行以下操作

  • 創建一個集群管理用戶,包含Replication slave和backup admin權限
  • 設置MGR相關配置
  • 再次校驗MySQL配置是否符合要求
// 初始化集群(第一個節點)
mysqlsh root@10.186.63.65:3310 --js
dba.createCluster('zhenxing',{memberWeight:90})

// 查看創建的集群狀態
var cluster = dba.getCluster()
cluster.status()

// 添加第二個節點
var cluster = dba.getCluster()
// 執行命令后新節點默認采用全量克隆方式添加到集群
cluster.addInstance('10.186.63.66:3310',{memberWeight:50})
cluster.addInstance('10.186.63.67:3310',{memberWeight:25})

// 也可以明確指定用增量方式加入新節點(確保各節點數據均一致或存在binlog日志可同步)
cluster.addInstance('10.186.63.66:3310',{memberWeight:50,recoveryMethod:'incremental'})
cluster.addInstance('10.186.63.67:3310',{memberWeight:25,recoveryMethod:'incremental'})

cluster.addInstance('10.186.63.66:3310',{memberWeight:50,recoveryMethod:'clone'})

// 查看集群的參數配置(包括memberWeight優先級配置)
cluster.status()
cluster.options().defaultReplicaSet.topology

4. mysqlrouter配置

mysqlrouter 是一個輕量級的中間件,無狀態的,建議和應用部署在一塊,mysqlrouter有兩種配置方式

  • 手工填寫后端 MGR 節點的地址,但是這樣就沒法感知 Primary 節點的變化,手工創建 MGR 時只能這么配置
  • 引導模式自動進行配置,通過 mysql_innodb_cluster_metadata 元數據庫動態感知 Primary 節點的變化,實現對應用的透明,這也是 InnoDB Cluster 的標准配置方法。
  • mysqlrouter 必須通過配置兩個端口來實現讀寫分離,沒有解析 SQL 的功能。
## 創建一個非root用戶來引導mysqlrouter
useradd mysql

## 初始化mysqlrouter
## 配置文件保存在/data/mysqlrouter/目錄下,包含啟停腳本
mysqlrouter --bootstrap root@10.186.63.65:3310 --directory=/data/mysqlrouter/ --conf-use-sockets --user=mysql --force

## 啟動mysqlrouter
cd /data/mysqlrouter/
./start.sh

4.1 使用mysqlrouter訪問

------ 通過讀寫端口 6446 訪問數據庫
mysqlsh root@10.186.63.179:6446
mysqlsh root@10.186.63.179:64460

-- 驗證主從角色
select @@hostname,@@port,@@server_uuid;
select * from performance_schema.replication_group_members;

-- 驗證寫入操作正常
create database demo;
use demo;
create table t1(id int primary key auto_increment);
insert into t1 select 1;
select * from t1;
------ 通過讀端口 6447 訪問數據庫
mysqlsh root@10.186.63.179:6447
mysqlsh root@10.186.63.179:64470

-- 驗證讀取操作正常
select @@hostname,@@port,@@server_uuid;
select * from performance_schema.replication_group_members;
select * from demo.t1;

-- 只讀端口無法寫入數據
MySQL  10.186.63.179:6447 ssl  SQL > insert into demo.t1 select 1;
ERROR: 1290 (HY000): The MySQL server is running with the --super-read-only option so it cannot execute this statement

InnoDB Cluster 常用操作

1. 查看集群狀態

 MySQL  10.186.63.179:6446 ssl  JS > var cluster = dba.getCluster()
 MySQL  10.186.63.179:6446 ssl  JS > cluster.status()
{
    "clusterName": "zhenxing",
    "defaultReplicaSet": {
        "name": "default",
        "primary": "10.186.63.65:3310",
        "ssl": "REQUIRED",
        "status": "OK",
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.",
        "topology": {
            "10.186.63.65:3310": {
                "address": "10.186.63.65:3310",
                "mode": "R/W",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.22"
            },
            "10.186.63.66:3310": {
                "address": "10.186.63.66:3310",
                "mode": "R/O",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.22"
            },
            "10.186.63.67:3310": {
                "address": "10.186.63.67:3310",
                "mode": "R/O",
                "readReplicas": {},
                "replicationLag": null,
                "role": "HA",
                "status": "ONLINE",
                "version": "8.0.22"
            }
        },
        "topologyMode": "Single-Primary"
    },
    "groupInformationSourceMember": "10.186.63.65:3310"
}

2. 配置節點權重

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

// 在集群創建完成后修改權重
var cluster = dba.getCluster()
cluster.setInstanceOption('10.186.63.65:3310','memberWeight',100)
cluster.setInstanceOption('10.186.63.66:3310','memberWeight',50)
cluster.setInstanceOption('10.186.63.67:3310','memberWeight',25)

// 查看集群的參數配置(包括memberWeight優先級配置)
cluster.options()

// 在集群創建時配置
dba.createCluster('zhenxing', {memberWeight:75}) // 第一個節點配置方式
var cluster = dba.getCluster() 
cluster.addInstance('10.186.63.66:3310',{memberWeight:50})
cluster.addInstance('10.186.63.67:3310',{memberWeight:25})

3. 將節點重新加入集群

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

3.1 rejoinInstance

cluster.status().defaultReplicaSet.topology
{
    "10.186.63.65:3310": {
        "address": "10.186.63.65:3310",
        "mode": "R/W",
        "readReplicas": {},
        "replicationLag": null,
        "role": "HA",
        "status": "ONLINE",
        "version": "8.0.22"
    },
    "10.186.63.66:3310": {
        "address": "10.186.63.66:3310",
        "mode": "R/O",
        "readReplicas": {},
        "role": "HA",
        "status": "(MISSING)"  // MISSING
    },
    "10.186.63.67:3310": {
        "address": "10.186.63.67:3310",
        "mode": "R/O",
        "readReplicas": {},
        "replicationLag": null,
        "role": "HA",
        "status": "ONLINE",
        "version": "8.0.22"
    }
}

// 重新加入集群
cluster.rejoinInstance("root@10.186.63.66:3310")

3.2 removeInstance && addInstance

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

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

4. 集群多數節點異常,恢復

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

// 將集群剝離為單節點運行
JS > cluster.forceQuorumUsingPartitionOf("root@10.186.63.67:3310")

// 重新加另外2個節點加入
JS > cluster.rejoinInstance("root@10.186.63.65:3310")
JS > cluster.rejoinInstance("root@10.186.63.66:3310")

5. 完整關閉的集群如何恢復

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

  1. 判斷哪個節點的GTID最新
  2. 將最新的GTID節點group_replication_bootstrap_group設置為on表示以這個節點為基礎啟動組復制
  3. 再將其他節點的組復制啟動,集群恢復

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

// 通過65節點觸發命令
MySQL  10.186.63.65:3310 ssl  JS > dba.rebootClusterFromCompleteOutage()
Restoring the default cluster from complete outage...

// 檢測到66服務器也包含在集群中,確認添加
The instance '10.186.63.66:3310' was part of the cluster configuration.
Would you like to rejoin it to the cluster? [y/N]: y

// 檢測到67服務器也包含在集群中,確認添加
The instance '10.186.63.67:3310' was part of the cluster configuration.
Would you like to rejoin it to the cluster? [y/N]: y

// 檢測到65不是最新的節點,66才是
Dba.rebootClusterFromCompleteOutage: The active session instance (10.186.63.65:3310) isn't the most updated in comparison with the ONLINE instances of the Cluster's metadata. Please use the most up to date instance: '10.186.63.66:3310'. (RuntimeError)

// 重新連接到66上執行相同操作
MySQL  10.186.63.65:3310 ssl  JS > \connect "root@10.186.63.66:3310"
MySQL  10.186.63.65:3310 ssl  JS > dba.rebootClusterFromCompleteOutage()

// 完成后查看集群狀態是否正常
var cluster = dba.getCluster()
cluster.status()

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()

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

var cluster = dba.getCluster()
cluster.setPrimaryInstance('10.186.63.66:3310')
cluster.status()

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

// 切換為多主模式
var cluster = dba.getCluster()
cluster.switchToMultiPrimaryMode()

// 指定明確的主節點將多主模式切換為單主模式
cluster.switchToSinglePrimaryMode("10.186.63.65:3310")

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("10.186.63.65:3310","memberWeight",75)
cluster.setInstanceOption("10.186.63.65:3310","autoRejoinTries",10)

8. 銷毀集群

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

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

錯誤記錄

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_applier
     MEMBER_ID: 67c08e33-92c4-11eb-803d-02000aba3f41
   MEMBER_HOST: 10.186.63.65
   MEMBER_PORT: 3310
  MEMBER_STATE: OFFLINE
   MEMBER_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_applier
     MEMBER_ID: 67c08e33-92c4-11eb-803d-02000aba3f41
   MEMBER_HOST: 10.186.63.65
   MEMBER_PORT: 3310
  MEMBER_STATE: ONLINE
   MEMBER_ROLE: PRIMARY
MEMBER_VERSION: 8.0.22
1 row in set (0.0016 sec)

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)",
                

清理殘留的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)

克隆插件不能設置為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)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM