mysql集群搭建与总结_mysql 不同端口组成集群-程序员宅基地

技术标签: mysql  数据库  集群  分布式  docker  

好久没写博客了,最近做了分布式的项目,调查和搭建了mysql集群,踩坑无数,特此记录。

1. 主从复制集群

主从复制是选取一个mysql数据库作为主库,然后一个或者多个mysql数据库作为从库。将主库的数据单向异步的复制到从库中,使得主库和从库的数据一致.

1.1 搭建主从复制

这里使用docker,通过映射不同的mysql端口来模拟搭建mysql主从复制(一主一从)

  • 下载mysql镜像,并且启动两个mysql

    Master:3000 Slave:3001

docker pull mysql:5.7
docker run -itd -p 3000:3306  --name mysql-master -e MYSQL_ROOT_PASSWORD=123456  mysql:5.7
docker run -itd -p 3001:3306  --name mysql-slave -e MYSQL_ROOT_PASSWORD=123456  mysql:5.7
  • 配置Master(3000)
  1. 进入容器,安装vim
apt-get update 
apt-get install vim
  1. 修改my.cnf配置文件,开启binlog,重启容器使得配置生效
#vim /etc/mysql/my.cnf
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[mysqld]
server-id=100 #局域网内唯一
log-bin=master-bin #开启binlog
binlog-format=ROW
  1. 重新进入进入容器,创建slave用户(Slave容器用此用户访问binlog,进行数据同步),并授权
mysql -uroot -p123456
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE,REPLICATION CLIENT ON *.* TO 'slave'@'%';
  1. 查看并记录Master状态,用于Slave进行同步

    记录下Position后就不要对Master进行操作了,不然Position可能会发生变化

show master status

在这里插入图片描述

  • 配置Slave(3001)
  1. 进入容器,安装vim
apt-get update 
apt-get install vim
  1. 修改my.cnf配置文件,开启binlog,relay log,重启容器使得配置生效
#vim /etc/mysql/my.cnf
!includedir /etc/mysql/conf.d/
!includedir /etc/mysql/mysql.conf.d/
[mysqld]
server-id=101 #局域网内唯一
log-bin=slave-bin #开启binlog,以备Slave作为Master
relay_log=mysql-relay-bin #开启relay log
#read_only=1  #设置Slave只读,不设置则可读写
  1. 进行主从复制

首先查看Master和Slave容器ip

docker inspect --format='{
    {.NetworkSettings.IPAddress}}' mysql-master
docker inspect --format='{
    {.NetworkSettings.IPAddress}}' mysql-slave

在这里插入图片描述
进入容器,Slave连接Master,进行主从复制

mysql -uroot -p123456
#Slave连接Master
change master to master_host='172.17.0.2', master_user='slave', master_password='123456', master_port=3306, master_log_file='master-bin.000001', master_log_pos=617, master_connect_retry=30;
#开始主从复制
start slave;

查看主从复制状态

show slave status \G;

Slave_IO_Running和Slave_SQL_Running都为Yes,代表主从复制搭建成功
在这里插入图片描述
如果不都为Yes,则看Last_IO_Error与Last_SQL_Error的报错。

报错:
Got fatal error 1236 from master when reading data from binary log: 'Could not find first log file name in binary log index file

解决办法:
重置主从复制,在Slave的mysql内执行

stop slave;
reset slave;
start slave

报错:
Error ‘Operation CREATE USER failed for ‘slave’@’%’’ on query. Default database: ‘’. Query: ‘CREATE USER ‘slave’@’%’ IDENTIFIED WITH ‘mysql_native_password’ AS ‘*6BB4837EB74329105EE4568DDA7DC67ED2CA2AD9’’

解决办法:
删除此用户,刷新权限后重新开启主从复制

stop slave;
drop user 'slave'@'%';
flush privileges;
start slave;
1.2 主从复制验证

进入Master容器的mysql,建库建表并插入一条数据。

create database test;
use test;
create table user(id int primary key,name varchar(255));
insert into user values(1,'selenium');
select * from user;

然后进入Slave容器的mysql查看,发现也能看到Master容器的mysql中刚刚新建的表和数据,证明主从复制有效。
在这里插入图片描述

1.3 主从数据不一致的解决方案(pt-table-sync)

虽然理想的情况下,Master与Slave上的数据都是一致的,但是由于Slave网络等原因,可能会出现Master与Slave上的数据不一致。

最简单的方法,是删掉从库数据,重新建立主从复制,但是这样从库需要进行全量复制,性能很差,并且只能将Master上的数据同步到Slave上,无法将Slave上的数据同步到Master上。

而比较好的方法是利用pt-table-sync工具进行数据同步,它可以将Master与Slave上的数据互相进行同步。

pt-table-sync官方文档

以Master同步Slave数据为例:

insert into user values(2,'sakura');

在slave上插入一条数据,由于主从复制是单向复制的,Master无法查看到Slave上刚刚插入的数据.
在这里插入图片描述

  1. 下载并解压pt-table-sync
apt-get install libdbd-mysql-perl
wget https://downloads.percona.com/downloads/percona-toolkit/3.2.1/source/debian/percona-toolkit_3.2.1-1.tar.gz
tar -xvf percona-toolkit_3.2.1-1.tar.gz
  1. 进入解压后目录的bin目录,执行下面命令进行同步
 ./pt-table-sync --execute h=192.168.56.103,P=3001,u=root,p=123456 --databases test  h=192.168.56.103,P=3000 --print

再次查看,发现Master与Slave数据已经一致
在这里插入图片描述
pt-table-sync不仅能够将Master同步为Slave的数据,也能将Slave同步为Master数据哦~

1.4 主从复制的原理

在这里插入图片描述

  1. Master 数据库数据发生改变,将改变的数据写入到binlog日志中
  2. Master的Dump Thread与Slave的IO Thread建立连接,从库根据change to master时的binlog文件名和position信息向Dump Thread请求,IO Thread接收到binlog event后写入到Relay log
  3. Slave的Sql Thread从Relay log中读取后,往Slave数据库中写入数据

2. 主主复制集群

之前说过主从复制只能Master往Slave单向异步复制数据,而主主复制则是Master与Slave互相进行数据复制。

主主复制是基于主从复制的,实际上就是在之前的Slave与Master角色互换,在原Master上执行Slave的操作,在原Slave上执行Master的操作。

在这里插入图片描述

3.pxc集群

pxc集群官方文档

之前我们提过很多次mysql主从复制是异步提交的,一个事务提交到了Master,可能还没有同步到Slave,事务就已经返回了,可能导致Master与Slave数据不一致,数据被丢失.
在这里插入图片描述

由于主从复制的弱一致性,所以主从复制不适用于数据可靠性要求比较高的系统,如订单系统。

这类系统适合采用基于同步复制,数据强一致性的pxc集群。

pxc集群主要特点:

  • 同步复制
  • 任何节点都可以读写
  • 数据同步的强一致性

pxc集群使用的端口:

  • 3306: mysql服务端口
  • 4444: 请求全量同步(SST)端口
  • 4567: 数据库节点之间通信端口
  • 4568 :请求增量同步(IST)端口
3.1 搭建pxc集群

PXC1: 3002 PXC2:3003 PXC3: 3004

#下载pxc集群镜像
docker pull percona/percona-xtradb-cluster:5.7.31
# 创建容器网络
docker network create pxc
#创建数据卷,持久化mysql数据
docker volume create --name v1
docker volume create --name v2
docker volume create --name v3
docker run -itd --net=pxc --name=pxc1 -p 3002:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -v v1:/var/lib/mysql percona/percona-xtradb-cluster:5.7.31
docker run -itd --net=pxc --name=pxc2 -p 3003:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc1 -v v2:/var/lib/mysql percona/percona-xtradb-cluster:5.7.31
docker run -itd --net=pxc --name=pxc3 -p 3004:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc1 -v v3:/var/lib/mysql percona/percona-xtradb-cluster:5.7.31

注意: 不要启动的太快,pxc1完全启动后再启动pxc2和pxc3

3.2 pxc集群验证
# 1.确保容器都是up状态
docker ps

在这里插入图片描述

# 2.进入任意一个容器查看集群状态
docker exec -it pxc1 /bin/bash
mysql -uroot -p123456
show status like '%wsrep%';

在这里插入图片描述
主要参数说明:

变量名 说明
wsrep_cluster_size 3 集群中有三个节点
wsrep_cluster_status Primary Primary 集群状态正常
Non-Primary 集群出现异常,如脑裂
Disconnected 集群无法连接

全部详细参数可见: https://www.percona.com/doc/percona-xtradb-cluster/5.7/wsrep-status-index.html

因为pxc集群中的每一个节点都是可读写的,所以在任何一个节点进行修改,都会同步到其他节点.

3.3 pxc集群实战总结

因为pxc集群搭建起来很简单,所以公司的项目mysql集群最终选择的方案是搭建pxc集群。但是由于第一次使用,很多pxc集群的特性与自己预计的不符合,也算是踩了很多的坑。

1.pxc集群停掉一个Slave节点(pxc2)后,集群仍然可用

docker stop pxc2后可以看到集群节点数变为2,但仍然是Primary状态,代表节点可用
在这里插入图片描述

2.pxc集群Slave节点(pxc2)恢复后,自动加入集群,集群可用

docker start pxc2后可以看到集群节点数变为3,仍然是Primary状态.
在这里插入图片描述
3.pxc集群停掉Master节点(pxc1)后,集群仍然可用

docker stop pxc1后可以看到集群节点数变为2,但仍然是Primary状态,代表节点可用
在这里插入图片描述
4.pxc集群Master节点(pxc1)恢复后,无法自动加入集群

docker start pxc1后,发现pxc容器启动后很快自动退出。

docker logs pxc1查看启动日志,发现报错:

2021-02-27T14:13:55.876477Z 0 [ERROR] WSREP: It may not be safe to bootstrap the cluster from this node. It was not the last one to leave the cluster and may not contain all the updates. To force cluster bootstrap with this node, edit the grastate.dat file manually and set safe_to_bootstrap to 1 .
2021-02-27T14:13:55.876582Z 0 [ERROR] WSREP: Provider/Node (gcomm://) failed to establish connection with cluster (reason: 7)
2021-02-27T14:13:55.876677Z 0 [ERROR] Aborting

原因:

pxc通过grastate.dat文件中的safe_to_bootstrap的值区分该节点是Master节点还是Slave节点。
safe_to_bootstrap为1代表为Master节点,safe_to_bootstrap为0代表为Slave节点。

pxc集群Master节点Down掉后,safe_to_bootstrap会变为0,集群会从剩下的结点中推选出来新的Master.但是原节点的配置信息仍然是作为Master的,所以无法启动。只是简单的将safe_to_bootstrap强制修改为1,那么将会脑裂,也是毫无意义的。

解决方案:

方案一(推荐):

将原Master(px1)作为Slave重新加入集群.

# 找到v1数据卷在宿主机上的位置
docker inspect v1
cd /var/lib/docker/volumes/v1/_data
# 删除grastate.dat文件
rm -rf grastate.dat
# 删掉pxc1重启,复用数据卷,选择剩下的结点作为Master,重新加入集群
docker rm pxc1
docker run -itd --net=pxc --name=pxc1 -p 3002:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc2 -v v1:/var/lib/mysql percona/percona-xtradb-cluster:5.7.31

在这里插入图片描述
方案二:

新建节点px4作为Slave加入集群.

docker volume create --name=v4
docker run -itd --net=pxc --name=pxc4 -p 3005:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc2 -v v4:/var/lib/mysql percona/percona-xtradb-cluster:5.7.31

方案一和方案二都是将剩下的节点中的pxc2节点作为新Master,唯一的区别就是,方案一的数据卷还在,所以集群恢复后,只用做增量同步,而方案二要做全量同步。

方案三(不推荐):

将原Master仍然作为Master,恢复集群

# 找到v1数据卷在宿主机上的位置
docker inspect v1
cd /var/lib/docker/volumes/v1/_data
# 删除grastate.dat文件
rm -rf grastate.dat
# 停止和删除pxc2和pxc3容器
docker stop pxc2 && docker rm pxc2 && docker stop pxc3 && docker rm pxc3
# 删除v2和v3数据卷
docker volume rm v2 && docker volume rm v3
# 重启pxc1容器和创建pxc2和pxc3容器
docker start pxc1
docker volume create --name=v2
docker volume create --name=v3
docker run -itd --net=pxc --name=pxc2 -p 3003:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc1 -v v2:/var/lib/mysql percona/percona-xtradb-cluster:5.7.31
docker run -itd --net=pxc --name=pxc3 -p 3004:3306 -e MYSQL_ROOT_PASSWORD=123456 -e CLUSTER_NAME=pxc -e XTRABACKUP_PASSWORD=123456 -e CLUSTER_JOIN=pxc1 -v v3:/var/lib/mysql percona/percona-xtradb-cluster:5.7.31

很明显,这个方案会丢失一部分数据(Master节点停掉后,插入到剩下节点的数据),而且两个剩下的节点都要做全量同步…唯一的优点就是,机器间的关系比较清楚,哪个机器是Master,它就一直是Master,不会发生变化

5.pxc集群节点超过半数退出后,集群不可用

在此次单机通过端口模拟pxc集群中,停掉pxc2和pxc3,pxc1仍然能够可用,没有出现集群节点超过半数退出后,集群不可用的现象。(不理解为什么)

但是在实际三台主机的开发环境中,停掉了两台Slave,Master仍然不可用,查看集群状态为Non-Primary,即出现了脑裂的现象。并且此时访问Master,会发现报错log:WSREP has not yet prepared node for application use,这时只要恢复节点到半数以上就好了.

其实pxc这样子设计,也是为了避免异地机房部署PXC集群,因为网络故障,导致一个PXC集群分裂成两个集群。

6.pxc集群的启动顺序与停止顺序相反

pxc集群每次肯定最先启动Master,再启动Slave,这样才能够选择Master,加入集群。

但是为了避免各种奇奇怪怪的错误,在停止集群的时候,一定要停掉Slave再停掉Master。

因为最后停掉的一定是存储数据最多的结点,只有下次首先启动,别的节点才方便去做增量同步.

4. InnoDB Cluster集群

虽然我们项目最终选用了pxc集群的方案,但是和我们对接的项目组却选用了InnoDB Cluster集群方案,暂时还未了解,等以后了解了,再来补上这块内容…

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/qq_45453266/article/details/113871739

智能推荐

自适应滤波算法(LMS算法)-程序员宅基地

文章浏览阅读9.7k次,点赞6次,收藏68次。引言 LMS学习算法是由Widrow和Hoff于1960年提出的,该算法也称为Δ\DeltaΔ规则,该算法与感知器网络的学习算法在权值调整上都基于纠错学习规则,但LMS算法那更容易实现,因此得到了广泛应用。   注意:LMS算法只能训练单层网络,但这并不影响其功能,从理论上讲,多层线性网络并不比单层网络强大,它们具有同样的能力,即对于每一个多层线性网络,都具有一个等效的单层..._lms算法

【文末福利】为什么我们要掌握Linux系统编程?_学习了linux系统编程可以结合什么用-程序员宅基地

文章浏览阅读9.1k次,点赞9次,收藏14次。作为一个嵌入式开发者,我觉得基于Linux的系统编程,这个应该是绕不开的话题。本文将围绕,为何要掌握Linux系统编程这个问题,给出一些观点,希望对各位有所帮助。_学习了linux系统编程可以结合什么用

LoRaAN终端OTAA入网方式的详细介绍_join_devnonce_err-程序员宅基地

文章浏览阅读1k次。在之前的文章中向大家介绍了“该如何选择LoRaWAN终端入的网方式”,本文主要介绍了OTAA节点是如何入网的。此文来自微信公众号“小七说LoRa”,内容已获小七老师授权,小七老师是腾讯云在线课程讲师,点击链接https://mp.weixin.qq.com/s/WvGmi81zBMzbAX8OUb-DpA可以观看课程视频。OTAA的全称是Over The Air Activation。它的入网步骤是这样的:节点发出的Join Request请求通过网关转发到服务器,也就是NS;NS会对该请求做一些判断处_join_devnonce_err

0.96寸OLED使用IIC接口和SPI接口arduino连接方式的说明_spi的dc怎么接-程序员宅基地

文章浏览阅读6.4k次,点赞2次,收藏15次。7pin0.96寸 OLED模块支持SPI和 IIC接口;默认是SPI接口;如果想用 IIC接口;操作如下几步骤:1.将模块背面的电阻R3换到R1 位置,此时将模块切换为IIC接口;电阻 R8 可以用0 欧姆电阻或是用焊锡短接电阻两端。2.CS脚接地。3.DC脚的处理:在 IIC 通信中 DC的高低电平是用来选择IIC通信地址的;当 DC接地时 IIC从机地址为:0x..._spi的dc怎么接

Writing Solaris Device Driver: Basic_9、device driver basic-程序员宅基地

文章浏览阅读828次。Device Driver BasicsThis section introduces you to device drivers and their entry points on the Solaris platform.What Is a Device Driver? A device driver is a kernel module that is responsible_9、device driver basic

Spring Boot整合Shiro完成认证,权限管理,MD5+salt加密_shiro整合md5+权限-程序员宅基地

文章浏览阅读786次。Spring Boot整合Shiro完成认证,权限管理,MD5+salt加密整合代码如下Pom.xml后端代码配置文件application.properties前台代码整合代码如下Pom.xml<?xml version="1.0" encoding="UTF-8"?><project xmlns="http://maven.apache.org/POM/4.0.0"..._shiro整合md5+权限

随便推点

Android系统属性值设置和使用_property_value_max-程序员宅基地

文章浏览阅读2.8k次。转载:https://blog.csdn.net/qq_30624591/article/details/102679377每个属性都有一个名称和值,他们都是字符串格式。属性被大量使用在Android系统中,用来记录系统设置或进程之间的信息交换。属性是在整个系统中全局可见的。每个进程可以get/set属性。属性服务在“init”守护进程中运行。每一个客户端想要设置属性时,必须连接属性服务..._property_value_max

SAS学习6(freq过程、tabulate过程、univariate过程、plot过程、chart过程)_sas中vbar什么意思-程序员宅基地

文章浏览阅读1.4k次。SAS学习6(freq过程、tabulate过程、univariate过程、plot过程、chart过程)_sas中vbar什么意思

xxl-job手动触发报错 xxl-rpc remoting error(no protocol: ip/run_xxl-job remoting error(no protocol: 10.200.7.184:9-程序员宅基地

文章浏览阅读1.9k次。今日在xxl-job任务调度中心,指定定时任务执行的机器地址时,报了xxl-rpc remoting error(no protocol: [指定ip]/run), for url : [指定ip]/run 错误。2、最后发现指定机器地址:http://127.0.0.1:9999/就可正常运行定时任务了。但是手动执行任务时却还是报错,根本就没有进入,猜测是地址问题。1、将执行器节点ip改为:http://127.0.0.1:9999。2、状态码 200 表明请求已经成功,服务器已成功处理了请求。_xxl-job remoting error(no protocol: 10.200.7.184:9999/run), for url : 10.200

openGauss企业版安装_opengauss_3.0.5 企业版安装-程序员宅基地

文章浏览阅读8.3k次,点赞40次,收藏44次。目录安装前准备服务器数据库安装包依赖的软件修改操作系统配置配置文件准备预安装安装及验证安装前准备这里要准备三个部分,服务器(OS已安装好)+数据库安装包+依赖的软件。服务器首先找小伙伴申请了华为云服务器安装好了OS,这里使用的是x86_64+openEuler 20.03LTS。你要是没有这么给力的小伙伴就自己亲力亲为吧~ 华为云服务器现在可是很划算呢,安装也很方便。[root@pekphisprb70593 ~]# cat /etc/os-_opengauss_3.0.5 企业版安装

java 从1到30中随机取出7个数_随机七个数-程序员宅基地

文章浏览阅读6.9k次。package com.abcchina;import java.util.ArrayList;import java.util.Collections;import java.util.LinkedList;import java.util.List;public class Suijishu {/*** @param args*/public static void main..._随机七个数

(四)在Navicat中,利用Query对表进行查询_navict查询1988年的学生-程序员宅基地

文章浏览阅读2.4k次。1.查询所有班级代码如下:select * from TB_Class;2.查询班级编号是1的班级信息代码如下:select ClassID,className,descript from TB_Class where ClassID=1;3.查询班级编号是2,并且学历是bachelor的学员信息代码如下:select * from TB_St..._navict查询1988年的学生

推荐文章

热门文章

相关标签