掘金 后端 ( ) • 2022-08-05 13:57

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第7天,点击查看活动详情

单节点数据库瓶颈

我们知道,单节点数据库通常存在如下弊端:

  • 大型互联网程序用户群体庞大,所以架构必须要特殊设计
  • 单节点的数据库无法满足性能上的需求
  • 单节点数据库没有冗余的设计,无法满足高可用特性

例如,在2016年春节,微信红包的业务量巨大:共有142亿个红包,比平时的业务量增加了75%,且每秒76万个红包。同时,产生了2900万张红包张片,5.16亿人参与,每秒的支付峰值达到20.8万。 如果这是一个单节点的MySQL数据库,则将带来性能上巨大的瓶颈。

那么,你一定会问,有没有MySQL集群方案,来处理这件事呢? 答案是肯定的!

MySQL集群方案

常见的MySQL集群方案有:

image.png

Replication

  • 1、存储速度快;
  • 2、弱一致性:在A节点写入的数据,无法保证把这条数据分发到集群的其他节点上,这就有可能出现在A节点写入的数据,在B节点上查不到这条数据。 由于弱一致性的特点,我们不能在Replication上保存高价值的数据,而是适合保存低价值的数据,如日志数据、新闻、论坛帖子数据等。

PXC(Percona XtraDB Cluster)

  • 1、存储速度稍慢
  • 2、强一致性:能保证数据同步的强一致性;在集群的A节点写入的数据,PXC方案一定会保证这条数据成功的同步到数据库集群的其他节点上。所以,PXC方案适合保存高价值的数据,如订单、账户、财务数据等等。

PXC原理

PXC 基于Mysql的Galera技术实现的数据库集群方案。在PXC集群中,任何一个数据库的节点都是可读可写的。可以在第一个节点中写入数据,在其他节点中就可以成功的读取这条数据,这体现了强一致性。 另外,在PXC集群中,集群上节点的数据库都是Mysql,我们可以使用Mysql官方的版本或Mysql的衍生版。但是,建议的是,使用的数据库实例可以用PerconaServer,它是Mysql的改进版,性能提升很大。所以,建议使用PerconaServer去搭建Mysql集群。

image.png

PCX方案与Replication方案对比

PXC集群,数据同步是双向的。即,在任何一个Mysql节点上都是能够同时读写数据的。如下图:

而,Replication方案的数据读写是单向的。例如,在Master节点上写入数据,在Slave节点上能读到这条数据,但是在Slave上写入数据,Master节点上就会读不到这条数据。因为,Replication的方案是单向的。所以,Replication方案导致集群里面的节点不是同时可以进行读写。

image.png

PCX方案的数据强一致性

image.png

由上图可知,PXC采用同步复制机制,即事务在所有集群节点要么同时提交,要么不提交。 而Replication采用异步赋值机制,无法保证数据的一致性。

  • 同步复制机制:同步机制要求必须在其他节点中也要成功的写入数据,才能算是一次写入的成功;

所以,把数据写入到第一个Mysql节点上后,还需要通过同步机制,把这个数据同步到其他节点,并且在其他节点成功的提交事务后,最后才算是写入成功。这个时候,第1个Mysql节点,才会把成功的节点告诉给Mysql 的客户端。如果有一个节点写入失败,那么这次写入就会算失败,不会同步到其他节点,客户端得到的反馈也是写入失败。

Replication数据弱一致性

在这里插入图片描述

Replication的异步复制机制,例如在第一个Mysql节点中写入数据,如果这个节点成功提交事务,就会直接返回写入成功的结果。但是,如果同步失败了,那么第二个节点可能就无法读到数据。这就好比你在淘宝上买东西,下了订单,付了款后,可是你却在订单列表中没有发现你的订单。这事就严重了。 所以,对于高价值数据,采用PXC集群式很有必要的!

PXC 集群实例与Replication集群实例对比

  • Replication 集群实例:

image.png

  • PXC集群实例:

image.png

把第二个节点的同步机制关闭,那么就会造成写入失败。这验证了PXC的强一致性原则。 在这里插入图片描述

PXC集群安装

首先,下载PXC集群,下载地址: https://hub.docker.com/r/percona/percona-xtradb-cluster

在这里插入图片描述

安装PXC镜像

下载:docker pull percona/percona-xtradb-cluster 导入:docker load < /home/soft/pxc.tar.gz>

下载完成后: 在这里插入图片描述

由于percona-xtradb-cluster名字较长,所以,可以进行修改:

docker tag docker.io/percona/percona-xtradb-cluster pxc

在这里插入图片描述

我们可以把原来的删除: docker rmi docker.io/percona/percona-xtradb-cluster

在这里插入图片描述

现在假设我们要创建5个节点的PXC集群,那么我们就需要创建5个PXC容器: 创建出来的PXC容器,不要对接Docker以外的网络,否则不安全。 出于安全考虑,我们要先给PXC集群在Docker虚拟机内部单独划分一个网段,这个网段外部是无法直接访问的,可以通过Docker开放的端口供外部访问。

创建内部网络

出于安全考虑,需要给PXC集群实例创建Docker内部网络:

docker network create net1//net1表示创建的网段名字 docker network inspect net1//查看net1网段的信息 docker network rm net1//删除net1网段

docker虚拟机自带的网段是172.17.0.xx,那么net1的ip 就是172.18.0.xx ,以此类推,当你创建第二个网段的时候,第二个网段的Ip就是172.19.0.xx 。。。

如果你想创建的网段不是172.18.0.xx,那么你可以自己规定: docker network create --subnet=172.18.0.0/24 net1 //创建了一个地址为172.18.0.0 ,端口为24的,名称为net1的网段。

image.png

Docker容器的使用原则:

一旦创建容器,不要把业务数据保存在容器中,而要保存在宿主机中。 那,怎么做呢?——> 使用的技术就是“目录映射”! 可以把宿主机上的一个目录映射到容器内。在运行容器的时候,把业务数据保存到这个映射目录里面,即存储到了宿主机的目录里面。 这样,一旦容器发生故障,只需要把这个容器停掉或删除掉,然后重新启动一个新的容器,然后把宿主机的目录映射给新的容器,那么新的容器启动后,就自带了这些业务数据。

但是,PXC这种方案,无法直接使用映射目录的方式,那么就需要采用另外一种目录映射的技术:“Docker卷”。

创建Docker卷

docker volume create --name v1 //创建一个名称为v1的Docker卷

创建的这个Docker卷,在宿主机中能够看得见。因为这是在宿主机上的Docker创建的一个卷,而这个卷在宿主机上是能看到目录的。然后,把这个卷映射给容器,这样,当PXC容器启动后,就可以把数据映射到卷的目录中。我们通过宿主机可以看到通过映射出来的数据。

image.png

现在我们创建的这个卷在宿主机上的真实路径是:/var/lib/docker/volumes/v1/_data 有了这个路径,那么,当创建PXC容容器时,我们就可以把这个数据卷v1 映射到容器的Mysql目录中。

同时,你可以删除这个数据卷: docker volume rm v1

创建PXC容器

  • 只需要向PXC镜像传入运行参数就能创建出PXC容器
[root @ localhost / ] docker run -d -p 3306:3306
-v v1:/var/lib/mysql
-e MYSQL_ROOT_PASSWORD=abc123456
-e CLUSTER_NAME=PXC
-e XTRABACKUP_PASSWORD=abc123456
--privileged --name=node1 --net=net1 --ip 172.18.0.2
pxc

解释:

  • docker run -d -p 3306:3306//-d:创建出的PXC容器,需要在后台运行; -p 端口映射,把容器的3306端口映射到宿主机的3306端口上;
  • 路径映射:-v v1:/var/lib/mysql//v1数据卷映射到容器中的Mysql的数据目录
  • 启动参数:-e MySQL_ROOT_PASSWORD=abc123456 创建出的数据库实例,对应的密码(这里是abc123456)
  • 创建出来的PXC集群名字 : -e CLUSTER_NAME=PXC (这里是PXC)
  • 数据库节点之间同步时要用到的密码: -e XTRABACKUP_PASSWORD=abc123456(这里是abc123456)
  • 权限:--privileged (最高权限,可读可写可执行)
  • 给创建出来的容器起名字:--name=node1
  • 使用的内部网段:--net=net1
  • 使用的内部网段的IP地址: --ip 172.18.0.2
  • 镜像的指令:pxc 执行指令后一个PXC的容器就会创建出来

image.png

端口参数需要错开

image.png

CLUSTER_JOIN=node1 : 与node1节点进行同步

image.png

分配ip地址,需要错开

实际操作: 在这里插入图片描述

docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v1:/var/lib/mysql --privileged --name=node1 --net=net1 --ip 172.18.0.2 pxc

注意:虽然上面语句一下子就执行了,但是实际上Mysql数据库的初始化不会这么快就完成,至少需要2分钟才能完成。所以,你需要等待。因为,如果第一个容器的Mysql没有初始化成功,就创建第二个PXC容器时,这第二个PXC容器启动时,会发生闪退。因为,第二个容器的MYSQL与第一个容器的MYsql做同步的时候,它会发现第一个容器的Mysql没有成功启动,那么第二个容器就会发生故障,导致第二个容器闪退。 所以,请你耐心等待第一个容器里的Mysql成功初始化,并且你通过客户端能连接到这个Mysql实例,你再去创建第二个、第三个.....PXC实例。

接着,我们创建数据库的连接:

这里我们使用在navicat Mysql上创建: 新建一个连接,取名为DB1,IP地址填宿主机的IP端口号也是填宿主机的端口号,用户名是root,密码我这里填abc123456。 注意:在这之前,你的centOs7上先要安装mysql。具体安装过程请参考: https://www.cnblogs.com/starof/p/4680083.html https://blog.csdn.net/paullinjie/article/details/80340145 https://blog.csdn.net/wzhedward/article/details/71036689

安装完成后,请在centos7上开放防火墙的3306端口。命令:

firewall-cmd --permanent --add-port=3306/tcp
firewall-cmd --reload

image.png

image.png

同样,创建DB1节点成功后,我们可以陆续创建其他4个节点:DB2、DB3、DB4。

创建完成后,先启动docker: service docker restart

然后,创建五个volume:

docker volume create v1
docker volume create v2
docker volume create v3
docker volume create v4
docker volume create v5

创建PXC容器

我们就可以接在在centos7上创建PXC容器:

docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v1:/var/lib/mysql --privileged --name=node1 --net=net1 --ip 172.18.0.2 pxc
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v2:/var/lib/mysql --privileged --name=node2 --net=net1 --ip 172.18.0.3 pxc
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v2:/var/lib/mysql --privileged --name=node3 --net=net1 --ip 172.18.0.4 pxc
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v4:/var/lib/mysql --privileged --name=node4 --net=net1 --ip 172.18.0.5 pxc
docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=abc123456 -e CLUSTER_NAME=PXC -e XTRABACKUP_PASSWORD=abc123456 -v v5:/var/lib/mysql --privileged --name=node5 --net=net1 --ip 172.18.0.6 pxc

然后我们在,DB1上新建一个数据库test:

image.png

创建成功后,我们去创新DB2、DB3、DB4、DB5,可以看到这几个节点也同步了test数据库:

在这里插入图片描述

OK,接着我们在test数据库上创建一张数据表,命名为student:执行之后,表结构如下:

在这里插入图片描述

我们再刷新一下其他节点,可以看到其他节点的test数据库,也进行了同步:

在这里插入图片描述

同样,当你在其他节点上更新,也会进行同步。 这样,我们的PXC集群就成功的搭建了!