innodb cluster,顾名思义只有innodb引擎可以使用。服务器内存尽量4g,2g完全不够。本文是单主模式,用到的mysql请自行安装
地址 | 名称 | 说明 |
---|---|---|
192.168.157.114:3306 | mysql_master | 主数据库 |
192.168.157.115:3306 | mysql_slave1 | 从库1 |
192.168.157.116:3306 | mysql_slave2 | 从库2 |
1、配置hosts解析(所有服务器都要执行)
vim /etc/hosts #输入以下内容 192.168.157.114 mysql_master 192.168.157.115 mysql_slave1 192.168.157.116 mysql_slave2
2、安装mysql shell(所有服务器都要执行)
下载地址:https://downloads.mysql.com/archives/shell/ 需要注意linux系统版本和mysql的版本
3、安装mysql shell(所有服务器都要执行)
#使用命令下载 mkdir -p /etc/mysql/shell cd /etc/mysql/shell #这个版本号根据mysql的版本来,我mysql是8.0.43,但是没找到shell的8.0.43版本 wget https://downloads.mysql.com/archives/get/p/43/file/mysql-shell-8.0.42-1.el7.x86_64.rpm #安装 rpm -ivh mysql-shell-8.0.42-1.el7.x86_64.rpm #验证是否安装成功 mysqlsh --version
4、修改mysql配置文件(所有服务器都要执行)
1、下面配置项的前缀loose-是mysql官方推荐的写法,所有属于可动态加载插件(plugin)的参数,而不是mysql服务器核心(server core)的参数,都需要加 loose- 前缀。具体有哪些内容是插件请自行百度
2、可以使用openssl 命令生成证书文件,生成命令在文末补充
# vim /etc/my.cnf 打开文件进入编辑模式,配置下面的内容,注意不要把你自己的配置替换了 [mysqld] #设置binlog文件名称 log-bin=mysql-log-bin #设置数据库唯一id(每个节点都不一样) server-id=1 #禁用除innodb引擎外的所有引擎。不然group_replication一直不成功 disabled_storage_engines="myisam,blackhole,federated,archive,memory,csv" #mysql 插件地址,这个地址必须配置,不然找不到组复制插件。 #通常为 /usr/local/mysql/lib64/mysql/plugin/(官方二进制安装)或 /usr/lib64/mysql/plugin/(包管理器安装,如 yum/dnf) #实在是不知道地址在哪,就登录mysql执行 show variables like 'plugin_dir'; plugin_dir = '/usr/lib64/mysql/plugin' #加载组复制插件,完整路径是/usr/lib64/mysql/plugin/group_replication.so plugin_load_add = 'group_replication.so' #ssl加密方式。required 强制加密,disabled禁用加密(生产环境慎用) loose-group_replication_ssl_mode = required #组复制集群名称,可以任意定义。 推荐自己生成uuid loose-group_replication_group_name='ce492252-9ae0-11ed-94c7-00163e0c22d4' #指定 binlog 的记录格式为row。 #statement:每一次更改生成sql,从库直接执行sql,文件最小但数据一致性可能无法保证 #row:将主库的行级变动保存到binlog,从库直接更改数据而非执行sql。文件大,但数据一致性最好。一般使用row(多主模式必用) #mixed:优先使用statement模式,出现了不安全的sql(随机数、自增主键等)自动切换到row。 binlog_format = row #开启gtid。gtid格式:数据库唯一id:事务id gtid_mode = on # 强制所有事务使用 gtid enforce-gtid-consistency = on #开启mysql重启时快速恢复 gtid 状态。 #比如一个自动处理快递单号的程序,执行到id=1000的时候崩溃了,设置为on的时候在重启之后自动从1000开始,而不是1-1000再处理一次 binlog_gtid_simple_recovery = on #控制每隔多少事务清理一次gtid数据。 #数据存放于mysql.gtid_executed表,默认的是1000,可以自行调整或者不要此参数 #如果每秒1万的事务,可以设置大一点,比如10000,如果每秒就一两百,则可以设小一点,比如100。很多项目都没达到每秒100的事务,除非抢购这种 gtid_executed_compression_period = 1000 #组复制中控制新节点引导过程的“宽松开关”(第一个节点必须是on,后续节点必须是off) #on:简化扩容和恢复操作,自动选择引导源并容忍短暂不一致,保证最终一致 #off:严格依赖手动配置引导源,适用于初始组形成或需要强一致性的场景。 loose-group_replication_bootstrap_group = off #mysql 启动时自动加入组复制集群(一般都需要设置on,设置off只有手动加入集群,生产环境on) loose-group_replication_start_on_boot = on #禁用组复制自动获取安全证书(生产环境推荐off),设置为on则加入新节点之后自动从集群中获取公钥文件 #如果设置on则必须保证已经生成了证书文件,可以使用openssl 命令生成。生成命令在文末补充 loose-group_replication_recovery_get_public_key = off # 配置ssl/tls,用于常规客户端连接和组复制通信(group_replication_recovery_get_public_key=off必须配置) ssl_ca = /etc/mysql/ssl/ca.pem ssl_cert = /etc/mysql/ssl/server-cert.pem ssl_key = /etc/mysql/ssl/server-key.pem # 配置恢复通道专用的ssl认证(group_replication_recovery_get_public_key=off必须配置) # 指定恢复通道信任的ca(与上面用的同一个ca) loose-group_replication_recovery_ssl_ca = /etc/mysql/ssl/ca.pem # 指定恢复用户(repl)使用的客户端证书和私钥(group_replication_recovery_get_public_key=off必须配置) loose-group_replication_recovery_ssl_cert = /etc/mysql/ssl/client-cert.pem loose-group_replication_recovery_ssl_key = /etc/mysql/ssl/client-key.pem # 强制恢复通道使用ssl(group_replication_recovery_get_public_key=off必须配置) loose-group_replication_recovery_use_ssl = on # 允许加入集群的 ip 地址段 loose-group_replication_ip_whitelist = 192.168.157.0/24 # 本机ip地址+组复制端口(每个节点都不一样) loose-group_replication_local_address = "192.168.157.114:33061" # 所有参与主从复制的mysql ip地址+组复制端口。如果有新的节点加入就会先从他自己的配置文件查找集群中的主机,然后加入,并不依赖于他的静态配置。他找到的这个主机就像一个介绍者一样,引导新的节点加入 loose-group_replication_group_seeds = "192.168.157.114:33061,192.168.157.115:33061,192.168.157.116:33061" #是否启用 单主模式(默认是单主模式) #单主模式会由节点自动选举出一个主节点,这也是为什么节点集群数量必须是奇数的原因,因为如果是偶数可能存在1对1或2对2的情况 loose-group_replication_single_primary_mode = on # 控制数据一致性检查,多主模式时开启 loose-group_replication_enforce_update_everywhere_checks = off #组复制节点数量。在mysql 8.0.16仅版本之前仅当group_replication_single_primary_mode = off时使用,最好是奇数。 #8.0.16+这个字段就是只读的,系统自动维护,但是可以查询show global variables like 'group_replication_group_size'; #loose-group_replication_group_size = 3 #消息缓存大小,根据服务器配置设置。 #组复制中,节点需要频繁交换事务日志(binlog)、心跳包、元数据(如 gtid 集合)等消息。 #为了避免频繁读写磁盘(降低性能),节点会将部分消息暂存到内存缓存中,待合适时机再写入磁盘或发送给其他节点。 loose-group_replication_message_cache_size = 1073741824 # 1gb(1024 * 1024 * 1024 字节) #消息压缩阈值。当节点间传输的消息大小超过该阈值时,mysql 会自动对消息进行压缩,减少网络带宽消耗,会额外占用cpu #如果系统内部大多是一般的insert 语句,可以设置小一点。可以减少压缩时候cpu消耗,因为可能达不到压缩的阈值 loose-group_replication_compression_threshold = 1048576 # 1mb(1024 * 1024 字节)
修改完之后重启master、slave1、slave2:systemctl restart mysqld
5、设置证书文件权限(所有服务器都要执行)
# 确保证书文件所有权为 mysql 用户(或 mysql 运行用户) sudo chown mysql:mysql /etc/mysql/ssl/ca.pem sudo chown mysql:mysql /etc/mysql/ssl/server-cert.pem sudo chown mysql:mysql /etc/mysql/ssl/server-key.pem # 私钥文件权限需严格限制(仅 mysql 用户可读) sudo chmod 600 /etc/mysql/ssl/server-key.pem # 公钥和 ca 证书可读(644) sudo chmod 644 /etc/mysql/ssl/ca.pem sudo chmod 644 /etc/mysql/ssl/server-cert.pem
6、设置root账户具有组复制的权限(所有服务器都要执行)
#登录mysql之后执行,root是用户名,%代表允许所有地址连接,localhost代表允许本地连接,ip代表允许特定ip连接 grant clone_admin, connection_admin, group_replication_admin, persist_ro_variables_admin, replication_applier, replication_slave_admin, role_admin, system_variables_admin on *.* to 'root'@'%' with grant option; flush privileges;
7、创建集群(master操作)
#1、登录mysql shell mysqlsh root@192.168.157.114:3306 #然后输入密码 #2、进入mysql shell命令行之后执行 dba.configureinstance() #会有一个确认框,输入y回车 #输出如下就代表成功 mysql 192.168.157.114:3306 ssl js > dba.configureinstance() configuring local mysql instance listening at port 3306 for use in an innodb cluster... this instance reports its own address as mysql_master: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. the instance 'mysql_master:3306' is valid to be used in an innodb cluster. the instance 'mysql_master:3306' is already ready to be used in an innodb cluster. successfully enabled parallel appliers. #3、创建集群,mysql_group_replication_cluster_0001是集群的名称,任意输入 var cluster = dba.createcluster('mysql_group_replication_cluster_0001'); #输出以下内容就是成功。 #如果退出了mysql shell,再次进入就需要var cluster = dba.getcluster("集群名称");才能获取到对应的集群,然后才可以使用cluster.status();查看集群状态 mysql 192.168.157.114:3306 ssl js > var cluster = dba.createcluster('mysql_group_replication_cluster_0001') a new innodb cluster will be created on instance 'mysql_master:3306'. validating instance configuration at 192.168.157.114:3306... this instance reports its own address as mysql_master:3306 instance configuration is suitable. note: group replication will communicate with other members using 'mysql_master:3306'. use the localaddress option to override. * checking connectivity and ssl configuration... creating innodb cluster 'mysql_group_replication_cluster_0001' on 'mysql_master: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.
创建完主节点之后,必须进入mysql命令行执行set global group_replication_bootstrap_group=off;(不能直接改配置文件)。接下来配置slave1和slave2
8、配置从库(slave1和slave2操作)
#1、确保loose-group_replication_local_address=ip:端口 # 1.1、slave1的配置 loose-group_replication_local_address = "192.168.157.115:33061" # 1.2、slave2的配置 loose-group_replication_local_address = "192.168.157.116:33061" #2、确保service-id是唯一的 # 2.1、slave1的配置 server-id=2 # 2.2、slave2的配置 server-id=3 #3、确保loose-group_replication_bootstrap_group = off loose-group_replication_bootstrap_group = off #如果更改了配置,记得重启mysql systemctl restart mysqld #检查配置是否正确(mysql shell命令行执行),如果输出有错误,按照提示修改就行,一定要确保slave1和slave2的 dba.configureinstance();输出是正常的 dba.configureinstance();#可能会输出warning,实际是已经成功了 #正常输出如下 configuring local mysql instance listening at port 3306 for use in an innodb cluster... this instance reports its own address as mysql_master: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. the instance 'mysql_master:3306' is valid to be used in an innodb cluster. the instance 'mysql_master:3306' is already ready to be used in an innodb cluster. successfully enabled parallel appliers.
9、slave1和slave2加入集群(master操作)
#mysql shell命令行执行 var cluster = dba.getcluster('mysql_group_replication_cluster_0001') #检查新节点的状态,出现"reason": "new", "state": "ok" 就是可以加入集群 cluster.checkinstancestate('root@192.168.157.115:3306'); #节点加入集群。recoverymethod:定义如何从主节点获取数据,官方推荐clone;label:当前实例的别名;interactive:禁用交互式反馈,自动执行命令 #输出:the instance 'mysql_slave1:3306' was successfully added to the cluster.就代表成功 cluster.addinstance("root@192.168.157.115:3306",{recoverymethod:"clone",label:"mysql_group_replication_slave1",interactive:false}) ; #再查看当前集群的状态 cluster.status() #输出如下 { "clustername": "mysql_group_replication_cluster_0001", "defaultreplicaset": { "name": "default", "primary": "mysql_master:3306", "ssl": "required", "status": "ok_no_tolerance", "statustext": "cluster is not tolerant to any failures.", "topology": { "mysql_group_replication_slave1": { "address": "mysql_slave1:3306", "memberrole": "secondary", "mode": "r/o", "readreplicas": {}, "replicationlag": "applier_queue_applied", "role": "ha", "status": "online", "version": "8.0.43" }, "mysql_master:3306": { "address": "mysql_master:3306", "memberrole": "primary", "mode": "r/w", "readreplicas": {}, "replicationlag": "applier_queue_applied", "role": "ha", "status": "online", "version": "8.0.43" } }, "topologymode": "single-primary" }, "groupinformationsourcemember": "mysql_master:3306" }
到此slave1的配置就完成了,接下来只需要按照slave1的步骤把slave2配置好就行,最终在master节点使用cluster.status()命令输出如下,“memberrole”: "primary"就是写入节点。
mysql 192.168.157.114:3306 ssl js > cluster.status() { "clustername": "mysql_group_replication_cluster_0001", "defaultreplicaset": { "name": "default", "primary": "mysql_master:3306", "ssl": "required", "status": "ok", "statustext": "cluster is online and can tolerate up to one failure.", "topology": { "mysql_group_replication_slave1": { "address": "mysql_slave1:3306", "memberrole": "secondary", "mode": "r/o", "readreplicas": {}, "replicationlag": "applier_queue_applied", "role": "ha", "status": "online", "version": "8.0.43" }, "mysql_group_replication_slave2": { "address": "mysql_slave2:3306", "memberrole": "secondary", "mode": "r/o", "readreplicas": {}, "replicationlag": "applier_queue_applied", "role": "ha", "status": "online", "version": "8.0.43" }, "mysql_master:3306": { "address": "mysql_master:3306", "memberrole": "primary", "mode": "r/w", "readreplicas": {}, "replicationlag": "applier_queue_applied", "role": "ha", "status": "online", "version": "8.0.43" } }, "topologymode": "single-primary" }, "groupinformationsourcemember": "mysql_master:3306" }
测试是否完成了主从同步:
1、在master节点新建数据库my_test,看是否会同步到另外两个节点去。
2、把slave2节点关机,然后在主节点的my_test数据库加一个test表,观察是否同步到了slave1。
3、把slave2开机,观察是否同步了test表
注意:从属节点禁止写入数据,可能会脑裂(主节点写入数据,从节点也写入了数据,就不知道到底哪个是真的),现在很多orm框架都支持读写分离
补充内容
1、生成ssl证书
#创建文件保存生成证书的脚本 mkdir -p /etc/mysql/ssl cd /etc/mysql/ssl vim generate_mgr_ssl.sh
复制粘贴以下内容并保存
#!/bin/bash set -e # 设置脚本遇到任何错误就立即退出,避免产生不一致的中间状态 # ==================== 【第一部分:核心节点定义 - 必须修改】 ==================== # 定义mysql集群节点主机名称 nodes=("mysql_master" "mysql_slave1" "mysql_slave2") # 定义与节点主机名对应的ip地址。主机名和ip地址必须对应 node_ips=("192.168.157.114" "192.168.157.115" "192.168.157.116") # ==================== 【第二部分:证书主题信息 - 建议修改】 ==================== # 设置证书的国家代码。cn表示中国,us表示美国,jp表示日本等 country_code="cn" # 设置证书的省 state_name="chongqing" # 设置证书的城市名称 city_name="chongqing" # 设置证书的组织名称 organization_name="mysql_group_replication_test" # 设置ca证书的通用名称(ca的标识名) ca_common_name="mysql_group_replication_test_ca" # 设置客户端证书的通用名称 client_common_name="mysql_group_replication_test_client" # ==================== 【第三部分:证书有效期和加密强度 - 按需修改】 ==================== # 设置证书的有效期(天) cert_valid_days=3650 # 设置rsa密钥的强度(位数)。4096是当前的安全标准,2048也可用但安全性较低 rsa_key_bits=4096 # ==================== 【第四部分:san扩展配置 - 按需修改】 ==================== # 是否在服务器证书中包含环回地址127.0.0.1。本地连接测试,设置为true include_localhost=true # 是否在服务器证书中包含主机名的dns记录。如果集群之间使用主机名进行连接,设置为true include_dns=true # 是否在服务器证书中包含ip地址。如果集群之间使用ip进行连接,设置为true include_ip=true # ==================== 【脚本主体部分(通常不需要修改)】 ==================== echo "生成ca证书..." openssl genrsa ${rsa_key_bits} > ca-key.pem openssl req -new -x509 -nodes -days ${cert_valid_days} -key ca-key.pem -out ca.pem \ -subj "/c=${country_code}/st=${state_name}/l=${city_name}/o=${organization_name}/cn=${ca_common_name}" # 创建初始序列号文件 echo "01" > ca.srl # 循环为每个节点生成服务器证书 for i in "${!nodes[@]}"; do node=${nodes[$i]} ip=${node_ips[$i]} echo "为 $node ($ip) 生成服务器证书..." # 生成服务器私钥 openssl genrsa ${rsa_key_bits} > server-${node}-key.pem # 创建证书签名请求(csr) openssl req -new -key server-${node}-key.pem -out server-${node}-req.pem \ -subj "/c=${country_code}/st=${state_name}/l=${city_name}/o=${organization_name}/cn=${node}" # 创建san扩展配置文件 san_content="" if [ "$include_dns" = true ]; then san_content="dns:${node}" fi if [ "$include_ip" = true ]; then if [ -n "$san_content" ]; then san_content="${san_content}, ip:${ip}" else san_content="ip:${ip}" fi fi if [ "$include_localhost" = true ]; then if [ -n "$san_content" ]; then san_content="${san_content}, ip:127.0.0.1" else san_content="ip:127.0.0.1" fi fi # 写入扩展配置文件 cat > server-${node}-ext.cnf << eof subjectaltname = ${san_content} extendedkeyusage = serverauth, clientauth eof # 使用ca签署服务器证书 - 添加 -cacreateserial 参数 openssl x509 -req -in server-${node}-req.pem -days ${cert_valid_days} -ca ca.pem -cakey ca-key.pem \ -cacreateserial -out server-${node}-cert.pem -extfile server-${node}-ext.cnf done echo "生成客户端证书..." # 生成客户端私钥 openssl genrsa ${rsa_key_bits} > client-key.pem # 创建客户端证书签名请求 openssl req -new -key client-key.pem -out client-req.pem \ -subj "/c=${country_code}/st=${state_name}/l=${city_name}/o=${organization_name}/cn=${client_common_name}" # 创建客户端证书扩展配置文件 cat > client-ext.cnf << eof extendedkeyusage = clientauth eof # 签署客户端证书 - 使用配置文件而不是命令行扩展 openssl x509 -req -in client-req.pem -days ${cert_valid_days} -ca ca.pem -cakey ca-key.pem \ -cacreateserial -out client-cert.pem -extfile client-ext.cnf echo "清理临时文件..." rm -f *.cnf *.req echo "证书生成完成!" echo "生成的文件清单:" ls -la *.pem # ==================== 【后续操作提示】 ==================== echo "" echo "下一步需要手动执行的操作:" echo "1. 将 ca.pem 分发到所有节点的 /etc/mysql/ssl/ 目录" echo "2. 将 server-<node>-key.pem 和 server-<node>-cert.pem 分发到对应节点,并重命名为 server-key.pem 和 server-cert.pem" echo "3. 将 client-key.pem 和 client-cert.pem 分发到所有节点" echo "4. 设置文件权限:" echo " chown mysql:mysql /etc/mysql/ssl/*" echo " chmod 600 /etc/mysql/ssl/*.pem" echo " chmod 644 /etc/mysql/ssl/ca.pem"
执行命令生成证书。 再次说明:这里生成的证书不是直接使用,需要按照服务器名称复制对应的文件到/etc/mysql/ssl,并修改文件名称
chmod +x generate_mgr_ssl.sh ./generate_mgr_ssl.sh
2、常用命令
#在mysql shell命令模式的时候,输入\q按回车退出 \q #使用root账号登录3306端口的mysql mysqlsh root@192.168.157.114:3306 #自动化检查mysql配置信息,以满足innodb cluster运行 dba.configureinstance() #检查mysql配置文件是否正确,如有不正确的内容会输出。非常有用! mysqld --validate-config #查看集群状态 cluster.status();
3、常见问题
只要是出现 authentication plugin 'caching_sha2_password' reported error: authentication requires secure connection.就代表没有使用ssl去连接。要么在my.cnf配置好ssl相关的文件路径,并确保能有权限读取文件。要么更改账户的密码校验插件为mysql_native_password。修改配置文件和修改的文件夹的权限都需要重启mysql。
如果退出了mysql shell,再次进入就需要var cluster = dba.getcluster("集群名称");才能获取到对应的集群,然后才可以使用cluster.status();查看集群状态。
dba.configureinstance();执行可能报错dba.configureinstance: this function is not available through a session to an instance belonging to an unmanaged asynchronous replication topology (runtimeerror)可能是因为之前配置了主从复制导致的,我这个slave1和slave2都是之前做的普通主从复制。出现这个问题,需要登录mysql然后执行。
stop slave; – 停止复制(如果是从节点)
reset slave all; – 清除复制配置(包括主从关系)
reset master; – 重置二进制日志(确保gtid干净)
var cluster = dba.getcluster('mysql_group_replication_cluster_0001')
提示错误: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) (mysqlsh 51314)。需要确认配置是否正确group_replication_bootstrap_group=on;group_replication_bootstrap_group=on (第一个节点是on,后续节点是off)
到此这篇关于mysql8.0.43使用innodb cluster配置主从复制的文章就介绍到这了,更多相关mysql innodb cluster主从复制内容请搜索代码网以前的文章或继续浏览下面的相关文章希望大家以后多多支持代码网!
发表评论