前言:
学习之前需要了解docker相关概念,移步 Docker官网
此处不再赘述虚拟化技术和docker VS 虚拟机 的一些内容,有条件的建议直接移步 度娘
笔记全程操作在华为云务器,CentOS7系统。需要自行准备操作环境。
一. 安装mysql
1.1 简单安装
一步步演示,为什么叫简单安装呢,就是我们这个mysql能用,能跑,但是存在问题
直接开始搞啦!
[root@local ~]# docker pull mysql:5.7
5.7: Pulling from library/mysql
Digest: sha256:f2ad209efe9c67104167fc609cca6973c8422939491c9345270175a300419f94
Status: Image is up to date for mysql:5.7
docker.io/library/mysql:5.7
[root@local ~]# docker run -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 -d mysql:5.7
4bff44ae22afdc56b2dbcdc24077974cda6813471ad2d9c4743173c364769b11
[root@local ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4bff44ae22af mysql:5.7 "docker-entrypoint.s…" 4 seconds ago Up 2 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp gracious_kare
[root@local ~]# docker exec -it 4bff44ae22af bash
root@4bff44ae22af:/# mysql -uroot -proot
搞定,连接、建库建表、插入数据、查询等等都没问题~ 但是...
问题1:可以看到,插入中文报错。=》查询可知是字符集的问题,这个问题稍后解决。
问题2:此处删除容器实例,数据会同步删除,这是一个致命的问题...
所以,我们通过接下来的案例解决 中文报错问题以及数据备份问题 -> 挂载数据卷
1.2 实战安装
[root@local ~]# docker run -d -p 3306:3306 --privileged=true \
> -v/fzjuse/mysql/log:/var/log/mysql \
> -v /fzjuse/mysql/data:/var/lib/mysql \
> -v /fzjuse/mysql/conf:/etc/mysql/conf.d \
> -e MYSQL_ROOT_PASSWORD=123456 --name mysql mysql:5.7
54936e666e0a47d0044c9cce4ae1c523d7117065ce3c41de6ed6dfd72abd3563
[root@local ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
54936e666e0a mysql:5.7 "docker-entrypoint.s…" 3 seconds ago Up 2 seconds 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp mysql
解决上述问题
切换到配置文件目录下,新建 my.cnf ,通过容器卷同步给mysql容器实例
// 这个目录是我们创建的容器数据库卷的配置文件目录,
// 在目录下添加配置文件解决中文问题
vim /fzjuse/mysql/conf/my.cnf
[client]
default_character_set = utf8
[mysqld]
collation_server = utf8_general_ci
character_set_server = utf8
# 重新启动容器
docker restart mysql
重复建库建表假数据的操作,发现乱码问题已经解决。
此处如果有创建好数据库不识别中文的问题,创建时制定数据库字符,后面添加命令:
--character-set-server=utf8mb4 --collation-server=utf8mb4_unicode_ci
然后创建容器数据卷保证了数据的持久化,不用再担心数据的问题。(自行测试删除容器重新创建之后的数据问题。)
1.3 主从复制的mysql
1.3.1 主服务器配置
新建主服务器实例3307
docker run -p 3307:3306 --name mysql-master \
-v /mydata/mysql-master/log:/var/log/mysql \
-v /mydata/mysql-master/data:/var/lib/mysql \
-v /mydata/mysql-master/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
-d --privileged=true 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
修改完成后重启master实例
docker restart mysql-master
进入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'@'%';
1.3.2 从服务器配置
新建从服务器实例3308
docker run -p 3308:3306 --name mysql-slave \
-v /mydata/mysql-slave/log:/var/log/mysql \
-v /mydata/mysql-slave/data:/var/lib/mysql \
-v /mydata/mysql-slave/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root \
--privileged=true -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
修改完配置后重启slave实例
docker restart mysql-slave
在主数据库中查看主从同步状态
show master status;
进入mysql-slave容器
docker exec -it mysql-slave /bin/bash
mysql -uroot -proot
在从数据库中配置主从复制
change master to master_host='121.36.54.248', 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;
主从同步配置完成~
1.3 测试
主库新建库、新建表、插入数据,从库查看库、查看记录,看主从同步是否成功
二. 安装redis
2.1 Redis安装
首先Redis需要配置文件的指定运行
我们先在CentOS宿主机目录下新建目录/app/redis
mkdir -p /app/redis
然后将一个redis.conf文件 模板拷贝进/app/redis目录下(配置文件不兼容会报错 )
修改配置文件:
注释掉:#bind 127.0.0.1 允许redis外地连接,大概69行
#daemonize no 将daemonize yes 注释或者改成 daemonize no,大概136行
运行容器
docker run -p 6379:6379 --name myr3 --privileged=true -v /app/redis/redis.conf:/etc/redis/redis.conf -v /app/redis/data:/data -d redis:6.0.8 redis-server /etc/redis/redis.conf
自行测试~
2.2 安装redis集群
2.2.1集群搭建和配置
此处搭建3主3从的redis集群,进行redis集群的扩容缩容操作
1. 新建6个docker容器实例
docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6381
docker run -d --name redis-node-2 --net host --privileged=true -v /data/redis/share/redis-node-2:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6382
docker run -d --name redis-node-3 --net host --privileged=true -v /data/redis/share/redis-node-3:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6383
docker run -d --name redis-node-4 --net host --privileged=true -v /data/redis/share/redis-node-4:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6384
docker run -d --name redis-node-5 --net host --privileged=true -v /data/redis/share/redis-node-5:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6385
docker run -d --name redis-node-6 --net host --privileged=true -v /data/redis/share/redis-node-6:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6386
# 相关参数说明:
docker run -> 创建并运行docker容器实例
--name redis-node-1 -> 容器名称
--net host -> 使用宿主机IP和端口,默认
--privileged=true -> 获取宿主机root用户权限
-v /data/redis/share/redis-node-1:/data -> 容器卷,宿主机地址:docker内部地址
redis:6.0.8 -> redis镜像和版本号
--cluster-enabled yes -> 开启redis集群
--appendonly yes -> 开启持久化
--port 6381 -> redis端口号配置
2. 进入容器redis-node-1并为6台机器构建集群关系
docker exec -it redis-node-1 /bin/bash
// --cluster-replicas 1 表示为每个master创建一个slave节点
redis-cli --cluster create 121.36.54.248:6381 121.36.54.248:6382 121.36.54.248:6383 121.36.54.248:6384 121.36.54.248:6385 121.36.54.248:6386 --cluster-replicas 1
3. 连接进入6381作为切入点,查看集群状态
redis-cli -p 6381
cluster info
cluster nodes
2.2.2 主从容错切换迁移
1. 数据的读写存储
此时如果我们进入6381进行set操作,会发现报了一个错,显示MOVED 6383,但是set 其他值就可以,这是因为key1经过计算槽位属于12706,而12706槽位属于6383的范围,所以连接单机6381存储就会失败。因为我们现在是集群模式,所以应该集群模式连接客户端,这样就不会出现上面问题,接下来集群连接客户端:
docker exec -it redis-node-1 /bin/bash
redis-cli -p 6381 -c
2. 查看集群信息命令:
redis-cli --cluster check 121.36.54.248:6381
可以看到集群内有4个key分布在3个主节点上
3. 容错切换迁移
此处停止node1:
docker stop redis-node-1
4. 进入node2查看集群状态
docker exec -it redis-node-2 /bin/bash
redis-cli -p 6382 -c
cluster nodes
可以查看到从机6386已经切换为主机,上位成功。重启6381查看,6381变为salve。
2.2.3 主从扩容案例
1. 增加两台redis服务器,6387 master,6388 salve
docker run -d --name redis-node-7 --net host --privileged=true -v /data/redis/share/redis-node-7:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6387
docker run -d --name redis-node-8 --net host --privileged=true -v /data/redis/share/redis-node-8:/data redis:6.0.8 --cluster-enabled yes --appendonly yes --port 6388
2. 创建完成之后检查
docker ps
3. 进入6387容器实例内部
docker exec -it redis-node-7 /bin/bash
4. 将新增的6387节点(空槽号)作为master节点加入原集群
redis-cli --cluster add-node 121.36.54.248:6387 121.36.54.248:6381
5. 检查集群状况第一次
redis-cli --cluster check 121.36.54.248:6381
6. 重新分配槽位
redis-cli --cluster reshard 121.36.54.248:6381
# 此处的各项选择如下:
How many slots do you want to move (from 1 to 16384) ? 4096
What is the receiving node ID ? 6387对应ID
Source node #1 : all
Do you want to proceed with the proposed reshard plan (yes/no) ? yes
7. 检查集群情况第二次
redis-cli --cluster check 121.36.54.248:6381
此时可以看到:6387的4096个槽位是其他三家每一家都匀出来一些给凑成的,原因是重新分配成本太高,所以前3家各自匀出来一部分,从6381/6382/6383三个旧节点分别匀出1364个坑位给新节点6387。
8. 为主节点6387分配从节点6388
redis-cli --cluster add-node 121.36.54.248:6388 121.36.54.248:6387 --cluster-slave --cluster-master-id d4def00c31d11b7c0895eb144220a202687173be
9. 检查集群情况第三次
redis-cli --cluster check 121.36.54.248:6381
至此,扩容完成~
2.2.4 主从缩容案例
缩容,删除6387和6388,恢复三主三从
1. 检查集群情况,获得6388从节点的ID
redis-cli --cluster check 121.36.54.248:6381
2. 从集群中将6388删除
redis-cli --cluster del-node 121.36.54.248:6388 fbe6d5c747ad9105701f1a1482fa4ccb1c9267e0
3. 检查集群情况第一次
4. 将6387的槽号清空,重新分配,本例将清出来的槽号都给6381
redis-cli --cluster reshard 121.36.54.248:6381
How many slots do you want to move (from 1 to 16384) ? 4096
What is the receiving node ID ? 6381对应ID接受槽位
Source node #1 : 6387节点ID,告知删除哪一个
Source node #2 : done
Do you want to proceed with the proposed reshard plan (yes/no) ? yes
5. 检查集群情况第二次
redis-cli --cluster check 121.36.54.248:6381
6. 将6387节点从集群中删除
redis-cli --cluster del-node 121.36.54.248:6387 67166075bb0792ba2df985a608a0569a630a2ccb
7.检查集群情况第三次
redis-cli --cluster check 121.36.54.248:6381
可以发现,6387节点已经没有了,而且6381节点一共8192个槽位。
至此,redis集群下主从架构的缩容完成~
唠唠叨叨:
mysql主从复制,redis集群配置、扩缩容操作,看着内容挺多,其实细心按着步骤来基本没什么问题搭建成功,只要耐心细心就好了。
还是得多试几次,看看不痛的报错信息,然后踩坑、排错,记得才更牢吧。一起学呀~