Docker复杂安装--最详细的MySQL主从复制与Redis集群安装、主从复制、主从扩容主从缩容实战版
目录
一、前言
二、MySQL的主从复制
MySQL主从复制原理
主从搭建
新建主服务器容器实例3307
配置文件
修改完配置重启容器
进入容器实例内
master容器实例内创建数据同步用户并授权
新建从服务器容器实例3308
配置文件
重启容器
在主数据库中查看主从同步状态
进入mysql-slave容器
在从数据库中配置主从复制
在从数据库中查看主从同步状态
在从数据库中开启主从同步
查看从数据库状态发现已经同步
主从复制测试
三、Redis集群搭建
面试题
3主3从redis集群扩缩容配置案例架构
分别启动6台redis容器
构建主从关系
查看集群状态
查看集群节点信息
Redis集群读写出错
集群信息检查
编辑主从扩容
启动两台新的容器节点
将6387作为master加入集群
检查当前集群状态
重新分配
分配从节点
检查集群当前状态
主从缩容
首先删除从节点6388
对6387哈希槽分走
删除节点6387
查看集群情况
一、前言
上篇文章中我们已经学习了基本的docker上的安装数据库,对于大部分的安装都是大差不差的,但是上文中我们主要针对的是单机版的数据库安装,在实际生产中我们往往需要的是多台服务器,如MySQL的主从复制和Redis的集群,在本文中我们就来看看多台服务器的安装是什么样子。
二、MySQL的主从复制
MySQL主从复制原理
MySQL主从复制原理
主从搭建
新建主服务器容器实例3307
docker run -p 3307:3306
--name mysql-master
--privileged=true
-v /mydata/mysql-master/log:/var/log/mysql
-v /mydata/mysql-master/data:/var/lib/mysql
-v /mydata/mysql-master/conf:/etc/mysql/conf.d
-e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
配置文件
进入 /mydata/mysql-master/conf 目录下新建my.cnf
[mysqld]
## 设置server_id, 同一个局域网中需要唯一
server_id=101
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能
log-bin=mall-mysql-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
修改完配置重启容器
docker restart mysql-master
进入容器实例内
docker exec -it mysql-master /bin/bash
mysql -uroot -proot
master容器实例内创建数据同步用户并授权
-- 创建数据同步用户
create user 'slave'@'%' identified by '123456';
-- 授权
grant replication slave, replication client on *.* to 'slave'@'%';
flush privileges;
- 第一条命令创建了一个名为slave的用户,允许从任何IP地址(用%表示)连接到数据库,并设置密码为123456。
- 第二条命令授予slave用户REPLICATION SLAVE和REPLICATION CLIENT权限。这些权限是进行主从复制所必需的:
- REPLICATION SLAVE:允许用户读取主服务器的二进制日志,这是实现数据复制的基础。
- REPLICATION CLIENT:允许用户查询主服务器的状态,例如查看二进制日志文件和位置。
新建从服务器容器实例3308
docker run -p 3308:3306
--name mysql-slave
--privileged=true
-v /mydata/mysql-slave/log:/var/log/mysql
-v /mydata/mysql-slave/data:/var/lib/mysql
-v /mydata/mysql-slave/conf:/etc/mysql/conf.d
-e MYSQL_ROOT_PASSWORD=root -d mysql:5.7
配置文件
进入/mydata/mysql-slave/conf目录下新建my.cnf
[mysqld]
## 设置server_id, 同一个局域网内需要唯一
server_id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql
## 开启二进制日志功能,以备slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed
## 二进制日志过期清理时间。默认值为0,表示不自动清理
expire_logs_days=7
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断
## 如:1062错误是指一些主键重复,1032是因为主从数据库数据不一致
slave_skip_errors=1062
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1
## slave设置只读(具有super权限的用户除外)
read_only=1
重启容器
docker restart mysql-slave
在主数据库中查看主从同步状态
show master status;
进入mysql-slave容器
docker exec -it mysql-slave /bin/bash
mysql -uroot -proot
在从数据库中配置主从复制
change master to master_host='宿主机ip', master_user='slave', master_password='123456',
master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;
- master_host:主数据库的IP地址;
- master_port:主数据库的运行端口;
- master_user:在主数据库创建的用于同步数据的用户账号;
- master_password:在主数据库创建的用于同步数据的用户密码;
- master_log_file:指定从数据库要复制数据的日志文件,通过查看主数据的状态,获取File参数;
- master_log_pos:指定从数据库从哪个位置开始复制数据,通过查看主数据的状态,获取Position参数;
- master_connect_retry:连接失败重试的时间间隔,单位为秒。
在从数据库中查看主从同步状态
show slave status \G;
在从数据库中开启主从同步
start slave;
查看从数据库状态发现已经同步
主从复制测试
- 主机新建库-使用库-新建表-插入数据,ok
- 从机使用库-查看记录,ok
三、Redis集群搭建
面试题
1~2亿条数据需要缓存,请问如何设计这个存储案例?
回答:单机单台100%不可能,肯定是分布式存储,用redis如何落地?
上述问题阿里P6~P7工程案例和场景设计类必考题目, 一般业界有3种解决方案
- 哈希取余分区
- 一致性哈希算法分区
- 哈希槽分区
这三个分区的原理及其优缺点详见Redis集群https://blog.csdn.net/newbie5277/article/details/150447281?spm=1001.2014.3001.5502
3主3从redis集群扩缩容配置案例架构
本文的集群搭建为三主三从,并演示它的扩容和缩容案例
关闭防火墙,打开docker
systemctl stop firewalld
systemctl start docker
分别启动6台redis容器
# 启动第1台节点
# --net host 使用宿主机的IP和端口,默认
# --cluster-enabled yes 开启redis集群
# --appendonly yes 开启redis持久化
# --port 6381 配置redis端口号
docker run -d --name redis-node-1 --net host --privileged=true -v /app/redis-cluster/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381# 启动第2台节点
docker run -d --name redis-node-2 --net host --privileged=true -v /app/redis-cluster/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382# 启动第3台节点
docker run -d --name redis-node-3 --net host --privileged=true -v /app/redis-cluster/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383# 启动第4台节点
docker run -d --name redis-node-4 --net host --privileged=true -v /app/redis-cluster/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384# 启动第5台节点
docker run -d --name redis-node-5 --net host --privileged=true -v /app/redis-cluster/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385# 启动第6台节点
docker run -d --name redis-node-6 --net host --privileged=true -v /app/redis-cluster/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
构建主从关系
随便进入一个节点,此次为节点1
docker exec -it redis-node-1 /bin/bash
构建主从关系
# 宿主机IP:端口
redis-cli --cluster create 192.168.xxx.xxx:6381 192.168.xxx.xxx:6382 192.168.xxx.xxx:6383 192.168.xxx.xxx:6384 192.168.xxx.xxx:6385 192.168.xxx.xxx:6386 --cluster-replicas 1
如果这里不成功,可以使用本地回环地址 127.0.0.1 来代替
查看集群状态
//进入容器节点1(或集群中其他节点)
docker exec -it redis-node-1 /bin/bash
//使用redis-cli连接到6381节点:
redis-cli -p 6381
//使用redis的相关命令查看集群状态:
cluster info
其中分配的哈希槽数量 cluster_slots_assigned为16384,集群节点数量cluster_known_nodes为6
查看集群节点信息
到这里我们的三主三从的Redis架构就配置完成了。
Redis集群读写出错
接下来进入容器节点1 并使用使用客户端连接
docker exec -it redis-node-1 /bin/bash
redis-cli -p 6381
接下来我们尝试向redis中添加键值对,如下
发现有时候插入成功,有时候报错,这是什么原因呢?
k1经过计算得到的哈希槽为12706,但是当前连接的redis-server为6381(即节点1),它的哈希槽为:[0,5460](在创建构建主从关系时redis有提示,也可以通过 cluster nodes查看),所以会因为存不进去而报错。
执行 set k2 v2可以成功,因为k2计算出的哈希槽在[0-5460]区间中。
这时候我们只需要在连接客户端的时候带上选项 -c,插入的时候,它会自动路由到对应哈希槽
集群信息检查
docker exec -it redis-node-1 /bin/bash
# 输入任意一台主节点地址都可以进行集群检查
redis-cli --cluster check 192.168.xxx.xxx:6381
主从扩容
假如因为业务量激增,需要向当前3主3从的集群中再加入1主1从两个节点。
启动两台新的容器节点
进入6387(节点7)容器内部
docker exec -it redis-node-7 /bin/bash
将6387作为master加入集群
检查当前集群状态
可以发现,6371节点已经作为master加入了集群,但是该节点没有被分配槽位。
重新分配
完成后,可以进行集群信息检查,查看分配结果:
redis经过槽位检查后,会提示需要分配的槽位数量:
例如,我们现在是4台master,我们想要给node7分配4096个槽位,这样每个节点都是4096个槽位。
输入4096后,会让输入要接收这些哈希槽的节点ID,填入node7的节点ID即可。(就是节点信息中很长的一串十六进制串)。
然后会提示,询问要从哪些节点中拨出一部分槽位凑足4096个分给Node7。一般选择 all,即将之前的3个主节点的槽位都均一些给Node7,这样可以使得每个节点的槽位数相等均衡。
输入all之后,redis会列出一个计划,内容是自动从前面的3台master中拨出一部分槽位分给Node7的槽位,需要确认一下分配的计划。
输入yes确认后,redis便会自动重新洗牌,给Node7分配槽位。
可以发现重新洗牌后的槽位分配为:
因为可能有些槽位中已经存储了key
,完全的重新洗牌重新分配的成本过高,所以redis选择从前3个节点中匀出来一部分给节点7
分配从节点
为主节点6387分配从节点6388:redis便会向6388发送消息,使其加入集群并成为6387的从节点。
redis-cli --cluster add-node 192.168.xxx.xxx:6388 192.168.xxx.xxx:6387 --cluster-slave --cluster-master-id node7节点的十六进制编号字符串
检查集群当前状态
主从缩容
假如业务高峰期过去,需要将4主4从重新缩容到3主3从。即从集群中移除node8和node7.
首先删除从节点6388
//进入容器节点1
docker exec -it redis-node-1 /bin/bash
// 检查容器状态,获取6388的节点编号
redis-cli --cluster check 192.168.xxx.xxx:6381
// 将6388从集群中移除
redis-cli --cluster del-node 192.168.xxx.xxx:6388 6388节点编号
对6387哈希槽分走
如果我们想直接把node7的4096个哈希槽全部分给某个节点,可以直接输入4096。
输入4096后,会让输入要接收这些哈希槽的节点ID。假如我们想把这4096个槽都分给Node1,直接输入node1节点的编号即可。
然后会提示,询问要从哪些节点中拨出一部分槽位凑足4096个分给Node1。这里我们输入node7的节点编号,回车后输入done。
删除节点6387
查看集群情况
可以看到6387和6388已经没有了,集群又恢复到了三主三从。
感谢阅读!