王 艳
(河南经贸职业学院计算机工程学院 河南 郑州 450046)
随着互联网的高速发展,互联网上的业务随之增多,从而也会产生大量的数据。 面对高并发的场景,往往都是读数据操作远多于写数据操作,如果所有的读写操作都在同一台数据库主机上,势必会造成该主机负荷过重,同时也对数据安全造成极大威胁。 将数据存放在多台数据库主机上,部署数据库主从架构[1]。 在从数据库上进行查询操作,降低主数据库的访问压力,如果主数据库出现问题,可以快速切换到从数据库中提供服务,在很大程度上增强了数据库的安全性[1]。
本文将基于开源的应用容器引擎(docker container,Docker)用来部署关系型数据库管理系统(my structured query language,MySQL)的主从架构,相较于基于传统虚拟化架构的数据库主从同步来说,该部署模式具有快速交付和部署、更简单的运行维护、更便捷的升级和扩容、更高效的资源利用等一系列优点[2]。
MySQL 是目前国内最流行的关系型数据库之一,在各企事业单位应用广泛,针对MySQL 数据主从同步的需求也日益复杂,自3.25 版本开始,MySQL 开始提供复制的功能,通过设置主机服务器和从机认证服务器来实现数据库主从同步。
根据主机和从机的数量不同,主从服务架构可以分为一主一从、一主多从、双主机、联级复制、多主一从的模式。在一主一从服务模式下,从机不仅作为备机使用,还要提供读数据的数据源,当数据发生增删改操作时,在主机上执行,并自动同步到从机,如果仅读数据,则会到从机上执行,从而降低主机的压力;一主多从的服务模式是对一主一从服务模式的扩展,在实际应用中,单一的从节点在支撑业务查询数据时存在很大的性能瓶颈,因此,将从机进行水平扩展,实现一主多从,提高查询效率;双主机模式即设置两台主机,两台主机互为对方的从机,共同分担读写压力;联级复制与一主多从的服务模式类似,不同的是,联级复制会设置从机的级别,低级别的从机的数据来源于高级别的从机,从而降低由于从机量增加,对主机造成的性能影响;多主一从的服务模式多应用在写操作远远多于读操作的业务中,通过设置多台主机来分担主机的压力,同时通过一个特定从机来完成读操作和数据备份的功能。
本文将采用一主一从的服务模式进行实验,在该服务模式下,设置主数据库启用二进制日志,并设置服务器编号。 当主数据库发生数据更改时,更新数据的同时还会将该事件写入主数据库二进制日志里,从数据库上的特定输入/输出(input/output,I/O)进程会监听主数据库上的二进制日志,一旦发生更新,会自动同步到自己的中继日志中。 此时,从数据库特定的结构化查询语言(structured query language,SQL)进程监听自己的中继日志,一旦发生改变,自动根据中继日志中的数据更改操作更新自身数据库数据。 从而实现将主数据库的数据库定义语言(data definition language, DDL) 和数据库操纵语言( data manipulation language,DML)操作传输到从数据库所在的服务器上,达到主从一致的状态[3]。
Docker 是基于开源编程语言实现的云开源项目。 它的主要目标是“Build,Ship and Run Any App, Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户APP 运行环境能够做到一次封装,随处运行[4]。
传统虚拟机资源占用多、冗余步骤多、启动慢。 针对以上缺点,Linux 容器虚拟化技术应运而生。 从架构上来说,容器技术并不是模拟一个完整的操作系统,而是对进程进行隔离。 借助容器技术,将软件运行过程中所需的所有依赖环境进行打包,系统因此而变得高效轻量,并保证部署在任何环境中的软件都能始终如一地运行[5]。
相较于传统的虚拟化技术,Docker 容器虚拟化技术具有更快速的应用交付和部署、更便捷的升级和扩缩容、更简单的系统运维和更高效的计算资源利用4 大优势[4]。
(1)更快速的应用交付和部署:传统模式下,应用程序开发完成后,需要提供一系列安装程序、环境依赖包和配置说明文档,并且运维人员需要根据配置文档进行复杂的配置才能正常运行软件。 如果使用Docker 容器虚拟化技术,只需要交付少量容器镜像文件,运维人员在测试或部署时,仅加载镜像并运行即可,和应用程序相关的一系列配置已经提前在镜像里内置,可以提高应用程序部署测试的效率。
(2)更便捷的升级和扩缩容:随着微服务架构和Docker的应用和发展,大量的应用会基于微服务的方式进行开发,类似于搭积木,每个Docker 容器将变成一块“积木”,因此,应用的升级将变得非常容易。 当业务需要升级时,只需要通过镜像运行新的容器即可进行业务升级或者扩容,使应用系统的更新升级从原先的天级变成分秒级。
(3)更简单的系统运维:应用软件使用容器虚拟化技术部署后,可保持开发、测试环境与生产环境的高度一致,容器会将与应用程序有关的依赖库打包封装,不会因为依赖环境版本等问题给应用带来影响。 当程序发生异常时,可以通过测试环境的相同容器进行快速定位和修复。
(4)更高效的计算资源利用:相较于传统的虚拟化技术来说,Docker 是内核级虚拟化,不需要额外的Hypervisor支持,在一台物理机上可以运行多个相互隔离的容器实例,能够提升物理服务器CPU 和内存的利用率。
安装一台Host 主机,本文中的主机选用了CentOS 7(64-bit)操作系统,Docker 运行在CentOS 7 上,要求系统为64 位、系统内核版本为3.10 以上,并且配置好该主机的网络,确保主机可以联通互联网。
3.1.1 Docker 安装
使用阿里云镜像网站上的Docker 社区版提供的前端软件包管理器源文件安装Docker,安装完成后启动Docker,并查看Docker 版本,本实验采用的Docker 版本为24.0.4,安装完成后,设置开机自启动,并查验Docker 的运行状态为激活(Active)状态,执行以下命令。
# yum install -y docker-ce
# systemctl start docker
# systemctl enable docker
# systemctl status docker
# docker info
3.1.2 Docker 镜像加速器配置
使用Docker 需要下载镜像,镜像默认在Docker 官方的公共仓库里下载,由于国内访问Docker Hub 的速度很不稳定,甚至会出现连接不上的情况,所以需要配置镜像加速器,本文选取阿里云镜像加速器。
在阿里云开发网站(https:/ /developer.aliyun.com)进行账号注册并登录,找到容器镜像服务选项下面的镜像加速器,根据网站提示,通过修改配置文件/etc/docker/daemon.json 来使用加速器,设置完毕后重启Docker 使其生效。
Docker 采用数据卷技术来解决数据持久化和数据共享的问题,将宿主机的目录或者文件与容器中的目录或者文件进行绑定,一方修改,另一方会立即同步,并且一个数据卷可以被多个容器同时挂载,一个容器也可以被挂载多个数据卷。
本实验采用mysql:5.7 版本的数据库,当MySQL 服务启动时会以/etc/mysql/my. cnf 为配置文件,该文件会导入/etc/mysql/conf. d 目录中所有以cnf 为结尾的文件。这些文件会拓展或覆盖/etc/mysql/my. cnf 文件中的配置。 因此需要创建自己需要的配置文件并挂载至MySQL容器中的/etc/mysql/conf.d 目录。
(1)拉取并运行MySQL:5.7 镜像,进入容器查看配置目录/etc/mysql/conf.d ,该目录下存在3 个配置文件,分别是docker.cnf,mysql.cnf 和mysqldump.cnf,执行以下命令。
[root@ localhost ~]# docker run -itd -e MYSQL_ROOT_PASSWORD=123456--name test mysql:5.7
[root@localhost ~]# docker exec -it 9f43c06b57 bash
root@9f43c06b57c0:/# cd /etc/mysql/conf.d/
(2)将配置目录/etc/mysql/conf.d 下的3 个配置文件拷贝至宿主机自定义目录/my/custom01/中,并自定义配置文件/my/custom/config-file. cnf,通过添加log_bin =mysql-bin 设置开启binlog 日志,并定义sever_id =20,从而实现主从同步功能,执行以下命令。
[root@localhost custom01]#docker cp 9f43c06b57c0:/etc/mysql/conf.d/∗.cnf /my/custom01/
[root@localhost custom01]# vim config-file.cnf
(3)自定义/my/custom02/作为从服务器,同样拷贝配置目录/etc/mysql/conf.d 下的所有内容,并自定义配置文件/my/custom/config-file. cnf, 与主服务器不同的是,config-file.cnf 中设置server_id=30,其余步骤皆一致。
(4)重新运行MySQL:5.7 镜像,设置端口映射、目录映射,将主数据库容器命名为mysql01,端口映射为3305,从数据库命名为mysql02,端口映射为3307,执行以下命令。
[root@localhost ~]# docker run -itd --name mysql01-v /my/custom01:/etc/mysql/conf. d -e MYSQL_ROOT_PASSWORD="123456" -p 3305 ∶3306 mysql:5.7
[root@localhost ~]# docker run -itd --name mysql02-v /my/custom02:/etc/mysql/conf. d -e MYSQL_ROOT_PASSWORD="123456" -p 3307 ∶3306 mysql:5.7
(5)通过docker inspect 容器id 命令查看mysql01 和mysql02 两个容器的id 和ip 地址分别为f52147f7230a,172.17.0.4 和d8df6c775697,172.17.0.6。 进入主数据库mysql01 容器中,查看配置目录/etc/mysql/conf. d 下的文件是否正确,查看无误后,登录数据库,创建用户,设置从数据库的复制权限,执行以下命令。
root@f52147f7230a:~# cd /etc/mysql/conf.d/
root@f52147f7230a:/etc/mysql/conf.d# ls
config-file.cnf docker.cnf mysql.cnf mysqldump.cnf
root@f52147f7230a:~# mysql -uroot -p123456
mysql>grant all privileges on ∗.∗ to root@'%'
identified by '123456';
mysql>grant replication slave on ∗.∗ to 'user'@'172.17.0.6' identified by '123456';
(6)进入从数据库mysql02 容器中,查看配置目录/etc/mysql/conf.d 下的文件是否正确,查看无误后,登录数据库,创建用户,设置主数据库,执行以下命令,使用show slave status\G 命令,查看Slave_IO_Running 和Slave_SQL_Running 都为Yes,说明两个同步线程都正常运行。
root@d8df6c775697:~# mysql -uroot -p123456
mysql>grant all privileges on ∗. ∗ to root@'%' identified by "123456";
mysql>change master to master_host ='172.17.0.4',master_user='user', master_password='123456';
mysql> start slave;
mysql>show slave status\G
在mysql01 容器中创建数据库test,在该数据库中创建表company,插入一条记录,在mysql02 容器中查看数据同步情况。
在主数据库所在的主机中进行如下操作:
mysql>show databases;
mysql> use test;
mysql> create table company (id int not null primary key, name varchar(50), addr varchar(255));
mysql> insert into company values (1, "xiaohong", "HenanZhengZhou");
mysql> select ∗from company;
再从数据库所在的主机中查看数据是否自动进行了同步,结果如图1 所示。
图1 从数据库数据同步验证
综上所述,利用Docker 容器来部署MySQL 数据库主从同步比在传统的虚拟机中部署速度更快,且能够将部署好的容器打包成新的镜像。 当现有的容器不足以支撑业务处理时,可通过镜像运行新的容器进行快速扩容,极大地提高了运维管理效率,能更高效地利用计算机中的资源。
由于实验环境有限,本实验部署在一台主机上,在实际生产环境中,需要设置两台主机,并设置在同一局域网内,确保可以网络互联,分别启动运行mysql:5.7 镜像,设置主从数据库,主数据库负责写数据的业务,从数据库负责查询操作,能够真正实现将数据放在不同的两台服务器上,实现数据的互为备份,并能够更好地面对高并发业务,极大地提高工作效率。