文章目录
- 项目背景
- 读写分离
- 读写分离简介
- 环境准备
- 配置虚拟机环境
- 部署主从同步
- master主机
- slave主机
- MaxScale简介
- 部署MaxScale服务器
- 授权用户
- master主机操作
- slave主机操作
- 启动服务
- 测试读写分离服务
- 总结
项目背景
- 之前无论是Wordpress博客项目还是HIS医疗项目,我们都只是考虑到前端架构方面的,动态页面产生的数据都存在了单点数据库中,然后单点数据库容易出现故障,由于单点故障问题导致整个架构或业务瘫痪,是致命的,所以必须要考虑数据库安全的问题。
- 通过架构分析得知,用户通过网站访问页面,无非两种情况,静态页面与动态页面,动态页面需要代码连接数据库,进行增删改查等操作,在数据库上的操作可以分为两类,即读操作和写操作
- 就上方架构而言,用户的查询请求和写入请求都是有单个数据库服务器来完成,这样容易使数据库服务器压力过载,可以使用读写分离技术解决该问题。
- 架构可演变为下方拓扑
- web站点如果调用数据库做查询操作,则该请求交给从服务器。
- web站点如果调用数据库做写入操作,则该请求交给主服务器,主服务器存储完毕后,从服务器可以自动同步该数据。
- 在工作中连接数据库的是Java/Python/php等代码,为了简单且让本地虚拟机正常运行,故本实验制作读写分离,测试的时候使用客户端直接连接管理节点测试。
读写分离
读写分离简介
- MySQL的读写分离服务是指将读操作和写操作分别分配给不同的数据库服务器,从而缓解单点服务器负载压力的问题,提高架构可靠性
- 读写分离常见解决方案
- MaxScale
- MyCAT
环境准备
- 本实验需要用到4台主机,全部使用模板机器链接克隆(VMware克隆功能之前用过很多次,这里不在演示)
- 将4台虚拟机全部调整至1024M即可(当然资源不够的同学client主机和maxscale主机可以使用同一台)
- 注意:IP地址采用自动分配,在这里不做强制要求
主机名 | IP地址 | 角色 |
---|---|---|
client | 192.168.8.200 | 客户端 |
maxscale | 192.168.8.100 | 管理节点 |
master | 192.168.8.101 | 主服务器 |
slave | 192.168.8.102 | 从服务器 |
配置虚拟机环境
- 注意4台主机网卡名不要照抄
- 保证四台主机阿里镜像站点可用
[root@localhost ~]# hostnamectl set-hostname client #配置主机名
[root@client ~]# nmcli connection modify ens33 ipv4.method auto \
connection.autoconnect yes
[root@client ~]# rm -rf /etc/yum.repos.d/*.repo #删除自带的repo文件
[root@client ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo \ https://mirrors.aliyun.com/repo/Centos-7.repo #下载阿里镜像源
[root@client ~]# yum clean all #清空缓存
[root@client ~]# yum repolist #查看yum
配置maxscale主机
[root@localhost ~]# hostnamectl set-hostname maxscale #配置主机名
[root@maxscale ~]# nmcli connection modify ens33 ipv4.method auto \
connection.autoconnect yes
[root@maxscale ~]# rm -rf /etc/yum.repos.d/*.repo #删除自带的repo文件
[root@maxscale ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo \ https://mirrors.aliyun.com/repo/Centos-7.repo #下载阿里镜像源
[root@maxscale ~]# yum clean all #清空缓存
[root@maxscale ~]# yum repolist #查看yum
配置master主机
[root@localhost ~]# hostnamectl set-hostname master #配置主机名
[root@master ~]# nmcli connection modify ens33 ipv4.method auto \
connection.autoconnect yes
[root@master ~]# rm -rf /etc/yum.repos.d/*.repo #删除自带的repo文件
[root@master ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo \ https://mirrors.aliyun.com/repo/Centos-7.repo #下载阿里镜像源
[root@master ~]# yum clean all #清空缓存
[root@master ~]# yum repolist #查看yum
配置slave主机
[root@localhost ~]# hostnamectl set-hostname slave #配置主机名
[root@slave ~]# nmcli connection modify ens33 ipv4.method auto \
connection.autoconnect yes
[root@slave ~]# rm -rf /etc/yum.repos.d/*.repo #删除自带的repo文件
[root@slave ~]# wget -O /etc/yum.repos.d/CentOS-Base.repo \ https://mirrors.aliyun.com/repo/Centos-7.repo #下载阿里镜像源
[root@slave ~]# yum clean all #清空缓存
[root@slave ~]# yum repolist #查看yum
4台主机均使用MobaXterm远程链接
部署主从同步
master主机
- 将学习环境中的mysql8-centos7目录上传至master主机的/root/
- 运行数据库服务
- 启用binlog日志
- 用户授权
- 查看日志信息
master主机安装数据库
[root@master ~]# cd mysql8-centos7/
[root@master mysql8-centos7]# yum -y localinstall *.rpm
master主机指定server_id,开启binlog日志
[root@master ~]# vim /etc/my.cnf
...此处省略1万字,在第4行下方写入,不要写行号!...
4 [mysqld]
5 server_id=101 #指定server_id,每台主机都不一样,可以使用IP地址主机位区分
6 log_bin=master #指定binlog日志名
...此处省略1万字...
[root@master ~]# systemctl restart mysqld #重启动mysqld服务
[root@master ~]# ls /var/lib/mysql/master* #验证是否成功
/var/lib/mysql/master.000001 /var/lib/mysql/master.000002 /var/lib/mysql/master.index
[root@master ~]# grep -i password /var/log/mysqld.log #过滤初始密码(每个人都不一样)
2023-07-16T13:04:50.381204Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: (wgrk:_s(7yQ
[root@master ~]# mysql -uroot -p'(wgrk:_s(7yQ' #连接数据库
mysql> ALTER USER root@"localhost" IDENTIFIED BY '123tedu.CN'; #修改root密码
mysql> SET GLOBAL validate_password.policy=LOW; #设置密码策略
mysql> SET GLOBAL validate_password.length=4; #设置密码长度为4
mysql> SET GLOBAL validate_password.check_user_name=OFF; #关闭用户名检测可以用用户名作为密码
用户授权(用户slave1,密码为slavepwd,这个用户用于从服务器连接主服务器同步数据)
mysql> CREATE USER 'slave1'@'%' IDENTIFIED with mysql_native_password BY 'slavepwd';
mysql> GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'%';
查看日志信息
mysql> SHOW MASTER STATUS ;
+---------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+---------------+----------+--------------+------------------+-------------------+
| master.000002 | 983 | | | |
+---------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)
slave主机
- 运行数据库服务
- 指定 server_id
- 指定主服务器信息
- 启动 slave 进程
- 查看状态
- 由于master和slave主机都使用的是新机器,主服务器没有多余的数据,所以可以不用做数据备份与还原
- 如果master上有数据,则需要先将master上的数据手动还原至slave主机
- 确保master主机和slave主机UUID是不相同的,因为都是从模板克隆的裸机,所以这里可以不用考虑该问题
slave主机安装mysql
[root@slave ~]# cd mysql8-centos7/
[root@slave mysql8-centos7]# yum -y localinstall *.rpm
slave主机修改server_id
[root@slave ~]# vim /etc/my.cnf
......
4 [mysqld]
5 server_id=102 #指定id号,默认与IP地址的主机位相同
......
[root@slave ~]# systemctl restart mysqld #重启服务
slave主机设置密码
[root@slave ~]# grep -i password /var/log/mysqld.log #过滤初始密码(每个人都不一样)
2023-07-16T13:33:20.939066Z 6 [Note] [MY-010454] [Server] A temporary password is generated for root@localhost: (f190mI%onK%
[root@slave ~]# mysql -uroot -p'(f190mI%onK%'
修改密码
mysql> ALTER USER root@"localhost" IDENTIFIED BY '123tedu.CN'; #修改root密码
mysql> SET GLOBAL validate_password.policy=LOW; #设置密码策略
mysql> SET GLOBAL validate_password.length=4; #设置密码长度为4
mysql> SET GLOBAL validate_password.check_user_name=OFF; #关闭用户名检测可以用用户名作为密码
指定主服务器信息
####指定主服务器信息
#MASTER_HOST= 指定主服务器的IP地址
#MASTER_USER= 指定主服务器授权用户
#MASTER_PASSWORD= 指定授权用户的密码
#MASTER_LOG_FILE= 指定主服务器binlog日志文件(到master上查看)
#MASTER_LOG_POS= 指定主服务器binlog日志偏移量(去master上查看)
mysql> CHANGE MASTER TO
-> MASTER_HOST="192.168.8.101", #指定自己主服务器master的IP地址
-> MASTER_USER="slave1",
-> MASTER_PASSWORD="slavepwd",
-> MASTER_LOG_FILE="master.000002",
-> MASTER_LOG_POS=983;
Query OK, 0 rows affected, 2 warnings (0.01 sec)
mysql> START SLAVE; #启动SLAVE进程
mysql> SHOW SLAVE STATUS \G; #查看主从同步状态
主服务器master写入数据验证
mysql> CREATE DATABASE som; #新建som库
从服务器slave写入数据验证
mysql> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| som |
| sys |
+--------------------+
5 rows in set (0.00 sec)
MaxScale简介
- MaxScale 代理软件
- 由 MySQL 的兄弟公司 MariaDB 开发
- 下载地址 https://downloads.mariadb.com/files/MaxScale
- 将maxscale-23.02.2-1.rhel.7.x86_64.rpm 上传至maxscale主机的/root
部署MaxScale服务器
maxscale主机安装maxscale
[root@maxscale ~]# yum -y localinstall maxscale-23.02.2-1.rhel.7.x86_64.rpm
maxscale主机修改修改读写分离服务配置文件
[root@host57 ~]# cp /etc/maxscale.cnf /etc/maxscale.cnf.bak #先备份,以防改错
[root@host57 ~]# vim /etc/maxscale.cnf #修改主配置文件
...
9 [maxscale]
10 threads=auto
...
#指定要代理的数据库服务器,[server2]部分需要自己手工定义
18 [server1]
19 type=server
20 address=192.168.8.101 #指定master服务器(IP地址不要照抄)
21 port=3306
22 protocol=MariaDBBackend
23 [server2]
24 type=server
25 address=192.168.8.102 #指定slave服务器(IP地址不要照抄)
26 port=3306
27 protocol=MariaDBBackend
...
#指定监控用户maxscalemon,用于登录后端服务器,检查服务器的运行状态和主从状态
41 [MariaDB-Monitor]
42 type=monitor
43 module=mariadbmon
44 servers=server1,server2 #数据库服务器信息已经在上面已经定义
45 user=maxscalemon #指定监控用户
46 password=123qqq...A #监控用户密码
47 monitor_interval=2s
...
70 #[Read-Only-Service] #只读服务不需要,这段全部注释
71 #type=service
72 #router=readconnroute
73 #servers=server1
74 #user=service_user
75 #password=service_pw
76 #router_options=slave
...
#定义读写分离服务器配置
81 [Read-Write-Service]
82 type=service
83 router=readwritesplit
84 servers=server1,server2 #指定读写分离服务器
85 user=maxscalerouter #指定路由用户
86 password=123qqq...A #指定路由用户密码
...
#只读服务配置信息加上注释
94 #[Read-Only-Listener]
95 #type=listener
96 #service=Read-Only-Service
97 #protocol=MariaDBClient
98 #port=4008
...
#读写分离配置信息,默认端口号为4006
100 [Read-Write-Listener]
101 type=listener
102 service=Read-Write-Service
103 protocol=MariaDBClient
104 port=4006
授权用户
- 根据/etc/maxscale.cnf配置要求,需要在master主机和slave主机授权用户
- maxscalemon用户,密码为123qqq…A
- maxscalerouter用户,密码为123qqq…A
- 创建监控用户maxscalemon,用于登录后端服务器,检查服务器的状态
- 创建路由用户maxscalerouter,检测客户端的用户名和密码在后端数据库中是否存在
- REPLICATION SLAVE:该权限能够同步数据,查看从服务器上slave的状态;
- REPLICATION CLIENT:该权限可以获取数据库服务的状态(数据库服务是否允许,主从是否正常)
master主机操作
授权maxscalemon用户
[root@master ~]# mysql -uroot -p'123tedu.CN'
mysql> CREATE USER 'maxscalemon'@'%' IDENTIFIED WITH mysql_native_password BY '123qqq...A';
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'maxscalemon'@'%';
授权maxscalerouter用户
- 只是检查用户是否存在,所以此用户只需对mysql库下表有查询权限即可
mysql> CREATE USER 'maxscalerouter'@'%' IDENTIFIED WITH mysql_native_password BY '123qqq...A';
mysql> GRANT SELECT ON mysql.* TO 'maxscalerouter'@'%';
slave主机操作
- 由于已经设置了主从同步,所slave主机也可以不用操作,因为已经自动同步,如果未同步则手工创建
授权maxscalemon用户
[root@slave ~]# mysql -uroot -p'123tedu.CN'
mysql> CREATE USER 'maxscalemon'@'%' IDENTIFIED WITH mysql_native_password BY '123qqq...A';
mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'maxscalemon'@'%';
授权maxscalerouter用户
- 只是检查用户是否存在,所以此用户只需对mysql库下表有查询权限即可
mysql> CREATE USER 'maxscalerouter'@'%' IDENTIFIED WITH mysql_native_password BY '123qqq...A';
mysql> GRANT SELECT ON mysql.* TO 'maxscalerouter'@'%';
启动服务
maxscale主机操作
[root@maxscale ~]# systemctl restart maxscale
[root@maxscale ~]# systemctl enable maxscale
测试读写分离服务
master主机授权测试用户
[root@master ~]# mysql -uroot -p'123tedu.CN'
mysql> CREATE USER 'sam'@'%' IDENTIFIED WITH mysql_native_password BY '123qqq...A';
mysql> GRANT ALL ON *.* TO 'sam'@'%';
客户端client访问读写分离服务器
[root@client ~]# yum -y install mariadb #安装mysql连接命令
[root@client ~]# mysql -h192.168.8.100 -P4006 -usam -p"123qqq...A"
mysql> CREATE DATABASE game; #创建game库
mysql> CREATE TABLE game.t1(id INT,name VARCHAR(20)); #创建表
mysql> INSERT INTO game.t1 VALUES(1,'tom'); #插入数据
master主机验证查看数据
[root@master ~]# mysql -uroot -p'123tedu.CN'
mysql> SELECT * FROM game.t1;
+------+------+
| id | name |
+------+------+
| 1 | tom |
+------+------+
slave主机验证查看数据
[root@slave ~]# mysql -uroot -p'123tedu.CN'
mysql> SELECT * FROM game.t1;
+------+------+
| id | name |
+------+------+
| 1 | tom |
+------+------+
slave主机插入数据,主服务器不会同步;
使用client客户端访问验证,能看到slave插入的数据,代表查询操作是slave主机提供服务;
slave主机操作
mysql> INSERT INTO game.t1 VALUES(2,"jerry"); #插入数据
client主机访问验证
[root@maxscale ~]# mysql -h192.168.8.106 -P4006 -usam -p"123qqq...A"
mysql> SELECT * FROM game.t1 ; #能查询到代表读写分离成功
+------+-------+
| id | name |
+------+-------+
| 1 | tom |
| 2 | jerry |
+------+-------+
2 rows in set (0.00 sec)
总结
- 掌握读写分离的作用
- 掌握读写分离的应用场景
- 掌握MaxScale的部署方式