Docker进阶:mysql 主从复制、redis集群3主3从【扩缩容案例】

Docker进阶:mysql 主从复制、redis集群3主3从【扩缩容案例】

  • 一、Docker常规软件安装
    • [1.1 docker 安装 tomcat(默认最新版)](#1.1 docker 安装 tomcat(默认最新版))
    • [1.2 docker 指定安装 tomcat8.0](#1.2 docker 指定安装 tomcat8.0)
    • [1.3 docker 安装 mysql 5.7(数据卷配置)](#1.3 docker 安装 mysql 5.7(数据卷配置))
    • [1.4 演示--删除mysql容器,里面的数据是否能正常恢复](#1.4 演示--删除mysql容器,里面的数据是否能正常恢复)
    • [1.5 docker 安装 redis7.0.9 (数据卷配置)](#1.5 docker 安装 redis7.0.9 (数据卷配置))
    • [1.6 宿主机修改redis.conf配置文件,验证redis 容器内生效](#1.6 宿主机修改redis.conf配置文件,验证redis 容器内生效)
  • [二、Docker复杂软件安装(mysql 主从复制)](#二、Docker复杂软件安装(mysql 主从复制))
    • [2.1 启动主节点容器mysql-master(3306)](#2.1 启动主节点容器mysql-master(3306))
    • [2.2 启动从节点容器mysql-slave(3307)](#2.2 启动从节点容器mysql-slave(3307))
    • [2.3 主数据库建库测试](#2.3 主数据库建库测试)
    • [2.4 从数据库验证](#2.4 从数据库验证)
  • 三、Docker复杂软件安装(redis集群--3主3从--分布式存储案例)
    • [3.1 前言--数据库分区技术](#3.1 前言--数据库分区技术)
    • [3.2 redis集群--3主3从搭建](#3.2 redis集群--3主3从搭建)
    • [3.3 redis集群--主从容错切换迁移案例](#3.3 redis集群--主从容错切换迁移案例)
    • [3.4 redis集群--读写error](#3.4 redis集群--读写error)
    • [3.5 redis集群--主从扩容案例(4主4从)](#3.5 redis集群--主从扩容案例(4主4从))
    • [3.6 redis集群--主从缩容案例(4主4从--->3主3从)](#3.6 redis集群--主从缩容案例(4主4从--->3主3从))

|-----------------------------|
| 💖The Begin💖点点关注,收藏不迷路💖 |

首先,确保你已经安装了Docker。

一、Docker常规软件安装

1.1 docker 安装 tomcat(默认最新版)

python 复制代码
1、创建一个目录用于存放程序文件。
mkdir -p  /home/my-projects

2、在终端或命令行界面中执行以下命令来拉取Tomcat的Docker镜像:
[root@zyl-server ~]# docker pull tomcat


3、查看Docker中已下载的Tomcat镜像
[root@zyl-server ~]# docker images tomcat
REPOSITORY   TAG       IMAGE ID       CREATED         SIZE
tomcat       latest    fb5657adc892   20 months ago   680MB
tomcat       8.0       ef6a7c98d192   4 years ago     356MB
[root@zyl-server ~]#


4、下载完成后,通过以下命令启动Tomcat容器,将宿主机的8080端口映射到容器的8080端口:

[root@zyl-server ~]# docker run -d -p 8080:8080 -v /home/my-projects:/usr/local/tomcat/webapps --privileged=true --name my-tomcat tomcat
8419cf96aaa10b2b3590e12d7d0973343dd9ab18a066be96c07e9bfa0875f632
[root@zyl-server ~]#





参数说明:
-p 小写    主机端口:容器端口
-P 大写    随机分配端口
--name my-tomcat  指定容器的名称为my-tomcat
-it        交互式模式运行
-d         后台运行
-v /home/my-projects:/usr/local/tomcat/webapps:将宿主机当前目录下的/home/my-projects目录挂载到容器中Tomcat的webapps目录,以便可以在宿主机上访问到Tomcat中部署的应用程序。

5、查看正在运行的Docker容器列表,
该命令将列出当前正在运行的容器的详细信息,包括容器ID、镜像名称、创建时间、状态等。

如果希望查看所有包括已停止的容器,可以添加 -a 参数,即 docker ps -a

[root@zyl-server ~]# docker ps
CONTAINER ID   IMAGE     COMMAND             CREATED          STATUS          PORTS                                       NAMES
8419cf96aaa1   tomcat    "catalina.sh run"   16 seconds ago   Up 15 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   my-tomcat
[root@zyl-server ~]#



6、进入tomcat容器的命令行界面(拷贝webapps.dist下的文件到webapps---因为镜像是精简版的)

[root@zyl-server ~]# docker exec -it 8419cf96aaa1 /bin/bash
root@8419cf96aaa1:/usr/local/tomcat# cp -r webapps.dist/* webapps/
root@8419cf96aaa1:/usr/local/tomcat# ls
BUILDING.txt     LICENSE  README.md      RUNNING.txt  conf  logs            temp     webapps.dist
CONTRIBUTING.md  NOTICE   RELEASE-NOTES  bin          lib   native-jni-lib  webapps  work
root@8419cf96aaa1:/usr/local/tomcat# cd webapps
root@8419cf96aaa1:/usr/local/tomcat/webapps# ls
ROOT  docs  examples  host-manager  index.html  manager
root@8419cf96aaa1:/usr/local/tomcat/webapps#


7、容器启动后,你可以通过在浏览器中访问 http://ip:8080 来验证Tomcat是否成功安装。如果一切正常,你将看到Tomcat的欢迎页面。

[root@zyl-server home]# curl http://localhost:8080

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Apache Tomcat/10.0.14</title>
        <link href="favicon.ico" rel="icon" type="image/x-icon" />
        <link href="tomcat.css" rel="stylesheet" type="text/css" />
    </head>

。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
python 复制代码
8、发布项目只需在宿主机的/home/my-projects,配置即可,如:

[root@zyl-server my-projects]# mkdir myweb
[root@zyl-server my-projects]# cd myweb/
[root@zyl-server myweb]# vi index.html
[root@zyl-server myweb]#

写入内容:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>


<h1>醉颜凉的第一个web项目。</h1>
<p>Hello Apache Tomcat/10.0.14</p>


</body>
</html>

1.2 docker 指定安装 tomcat8.0

要下载特定版本的Tomcat镜像,可以在 docker pull 命令后面添加 <image_name>:<tag> 参数。其中 <tag> 制定了镜像的版本号。

python 复制代码
1、指定pull  tomcat8.0,下载Tomcat 8.0版本的镜像
[root@zyl-server ~]# docker pull tomcat:8.0


2、基于 Tomcat 8.0 版本的镜像启动一个容器,并将容器的 8080 端口映射到主机的 8081 端口上。
[root@zyl-server myweb]# docker run -d -p 8081:8080 --name tomcat tomcat:8.0
f71f3050a4af5fe02587a4f8f61c8af1e5d254be4ad9b1ae98309c7b46e61be4
[root@zyl-server myweb]#

解释:

-d 参数表示以后台模式运行容器。
-p 8081:8080 参数表示将容器的 8080 端口映射到主机的 8081 端口。这样,当你在浏览器中访问 http://localhost:8081 时,将会被转发到容器中的 Tomcat 服务器。
--name tomcat 参数指定容器的名称为 "tomcat"。

1.3 docker 安装 mysql 5.7(数据卷配置)

python 复制代码
1、拉取 MySQL 5.7 镜像:
docker pull mysql:5.7

2、在启动容器之前,创建一个目录来持久化 MySQL 数据()。使用以下命令创建一个目录,用于存储数据库文件:

创建一个目录作为 Docker 数据卷并将其挂载到 MySQL 容器中,可以确保 MySQL 数据在容器被删除或重启后仍然存在。

[root@zyl-server ~]# mkdir -p /mysql/data
[root@zyl-server ~]#

3、使用以下命令启动 MySQL 5.7 容器:
docker run -d -p 3306:3306 --name mysql-5.7 -e MYSQL_ROOT_PASSWORD=123456 -v /mysql/data:/var/lib/mysql mysql:5.7

4、查看正在运行的Docker容器列表:

[root@zyl-server ~]# docker run -d -p 3306:3306 --name mysql-5.7 -e MYSQL_ROOT_PASSWORD=123456 -v /mysql/data:/var/lib/mysql -v /mysql/log:/var/log/mysql -v /mysql/conf:/etc/mysql/conf.d mysql:5.7
ddba7f4cf1f89ea7627a3c3628d7479c31bfdb7d0b0dd82e78cb50ce5b4726d8
[root@zyl-server ~]#

[root@zyl-server ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
ddba7f4cf1f8   mysql:5.7    "docker-entrypoint.s..."   22 seconds ago   Up 21 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql-5.7
f71f3050a4af   tomcat:8.0   "catalina.sh run"        36 minutes ago   Up 36 minutes   0.0.0.0:8081->8080/tcp, :::8081->8080/tcp              tomcat
8419cf96aaa1   tomcat       "catalina.sh run"        48 minutes ago   Up 48 minutes   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp              my-tomcat
[root@zyl-server ~]#


5、进入mysql-5.7容器:
docker exec -it ddba7f4cf1f8 /bin/bash

6、以 root 用户身份登录到 MySQL 数据库(密码 123456 访问 MySQL 服务):

root@db84734dad6a:/# mysql -u root -p
Enter password:  //(123456)
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

7、例如,创建一个名为 "mydatabase" 的数据库:

CREATE DATABASE mydatabase;

8、使用 USE 命令切换到所需的数据库:
USE mydatabase;

9、例如,创建一个名为 "users" 的表,包含 id、name 和 email 列:

CREATE TABLE users (
  id INT,
  name VARCHAR(50),
  email VARCHAR(100)
);

10、使用 INSERT INTO 语句。向 "users" 表插入三条数据:

INSERT INTO users (id, name, email) VALUES
  (1, 'John', 'john@example.com'),
  (2, 'Jane', 'jane@example.com'),
  (3, 'Tom', 'tom@example.com');

11、本地使用数据库管理工具远程连接:

解决插入中文报错:

python 复制代码
INSERT INTO users (id, name, email) VALUES (4, '张三', 'zhangsan@example.com');

1、查看数据库的编码方式
SHOW VARIABLES LIKE 'character_set_database';
SHOW VARIABLES LIKE 'character%';
python 复制代码
2、修改数据库的字符集:
[root@zyl-server ~]# cd /mysql/conf
[root@zyl-server conf]# pwd
/mysql/conf
[root@zyl-server conf]#

vi my.cnf,写入下面内容,my.cnf 为前面挂载的数据卷:

[client]

default_character_set=utf8

[mysqld]
collation_server=utf8_general_ci
character_set_server=utf8


3、修改前面创建的数据库、表的字符集:

ALTER DATABASE mydatabase CHARACTER SET utf8;

ALTER TABLE users CONVERT TO CHARACTER SET utf8;
python 复制代码
3、重新启动mysql容器
[root@zyl-server conf]# docker restart mysql-5.7
mysql-5.7
[root@zyl-server conf]#


4、再次查看数据库编码方式:
mysql> SHOW VARIABLES LIKE 'character%';
+--------------------------+----------------------------+
| Variable_name            | Value                      |
+--------------------------+----------------------------+
| character_set_client     | utf8                       |
| character_set_connection | utf8                       |
| character_set_database   | utf8                       |
| character_set_filesystem | binary                     |
| character_set_results    | utf8                       |
| character_set_server     | utf8                       |
| character_set_system     | utf8                       |
| character_sets_dir       | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
8 rows in set (0.00 sec)

mysql>
python 复制代码
5、插入数据测试

INSERT INTO users (id, name, email) VALUES (4, '张三', 'zhangsan@example.com');

总结: docker安装完mysql,运行实例之后,建议先修改完字符集编码后再建库建表。

在创建 MySQL 数据库和表之前,先确保 MySQL 的字符集编码设置是正确的。如果你没有设置正确的字符集编码,就可能会在处理文本数据时出现乱码等问题,影响数据的完整性和可读性。


1.4 演示--删除mysql容器,里面的数据是否能正常恢复

python 复制代码
[root@zyl-server ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED             STATUS             PORTS                                                  NAMES
ddba7f4cf1f8   mysql:5.7    "docker-entrypoint.s..."   27 minutes ago      Up 20 minutes      0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql-5.7
[root@zyl-server ~]#


1、删除刚创建 MySQL 容器(线上环境慎用) docker rm -f mysql-5.7

[root@zyl-server ~]# docker rm -f mysql-5.7
mysql-5.7
[root@zyl-server ~]#

2、重新启动MySQL 容器

[root@zyl-server ~]# docker run -d -p 3306:3306 --name mysql-5.7 -e MYSQL_ROOT_PASSWORD=123456 -v /mysql/data:/var/lib/mysql -v /mysql/log:/var/log/mysql -v /mysql/conf:/etc/mysql/conf.d mysql:5.7
0f129eb516f74872334f3c46b9b57b0808de2441bfd0db3a54c564aca838ddff
[root@zyl-server ~]#
[root@zyl-server ~]# docker ps
CONTAINER ID   IMAGE        COMMAND                  CREATED             STATUS             PORTS                                                  NAMES
0f129eb516f7   mysql:5.7    "docker-entrypoint.s..."   5 seconds ago       Up 3 seconds       0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql-5.7
[root@zyl-server ~]#

3、进入重新启动的MySQL 容器
docker exec -it mysql-5.7 /bin/bash

或者
docker exec -it 0f129eb516f7 /bin/bash


4、验证,刚才创建的mydatabase库和users表数据

[root@zyl-server ~]# docker exec -it mysql-5.7 /bin/bash
root@0f129eb516f7:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36 MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydatabase         |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql>

mysql> use mydatabase;
Database changed
mysql> select * from users;
+------+--------+----------------------+
| id   | name   | email                |
+------+--------+----------------------+
|    1 | John   | john@example.com     |
|    2 | Jane   | jane@example.com     |
|    3 | Tom    | tom@example.com      |
|    4 | 张三   | zhangsan@example.com |
+------+--------+----------------------+
4 rows in set (0.00 sec)

mysql>

总结:使用 Docker 数据卷的方法来进行存储。保留 MySQL 数据库和表的持久化数据。容器实例删除,里面的数据在重启启动容器实例之后也能正常恢复

1.5 docker 安装 redis7.0.9 (数据卷配置)

redis.conf文件下载

python 复制代码
1、宿主机下/下创建 /apps/redis  目录
[root@zyl-server /]# mkdir -p /apps/redis

2、在/apps/redis  目录,创建redis.conf文件

3、修改redis.conf文件
## 开启redis验证,添加该行(可选)
requirepass 123456

## 允许redis远程连接,注释# bind 127.0.0.1
# bind 127.0.0.1

## 将 daemonize yes 改为 
daemonize no

因为该配置和docker run -d 参数冲突,会导致容器启动一直失败

## 开启redis 数据持久化 appendonly yes (可选)
appendonly yes

1、运行以下命令来下载并运行 Redis7.0.9  的 Docker 镜像:
docker run -d -p 6379:6379 --privileged=true --name my-redis -v /apps/redis/redis.conf:/etc/redis/redis.conf -v /apps/redis/data:/data -d redis:7.0.9 redis-server /etc/redis/redis.conf

这个命令将以后台方式运行Redis容器,并进行以下配置:

开放主机的6379端口并将其映射到容器的6379端口。
启用特权模式,以便在容器内部执行一些特殊操作(如修改文件权限)。
将容器的名称设置为my-redis。
将主机上的/apps/redis/redis.conf文件挂载到容器内的/etc/redis/redis.conf文件,以应用自定义的Redis配置。
将主机上的/apps/redis/data目录挂载到容器内的/data目录,以作为Redis数据的持久化存储。

2、检查容器的运行状态:
[root@zyl-server redis]# docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS              PORTS                                                  NAMES
6293c1f5fc5e   redis:7.0.9   "docker-entrypoint.s..."   About a minute ago   Up About a minute   0.0.0.0:6379->6379/tcp, :::6379->6379/tcp              my-redis

3、在 my-redis容器中打开交互式终端

docker exec -it my-redis /bin/bash

4、连接到Redis服务器:

[root@zyl-server redis.conf]# docker exec -it my-redis /bin/bash
root@508d58462ff3:/data# redis-cli

或者使用

docker exec -it my-redis redis-cli

在Docker容器中打开一个交互式终端,并直接进入Redis客户端。

127.0.0.1:6379> set k1 v1
(error) NOAUTH Authentication required.
127.0.0.1:6379>

这是因为redis设置了密码,我们需要使用密码来进行验证之后再来对redis客户端进行操作,否则我们没有操作redis缓存数据库的权限。

解决方法----> 我们使用命令:auth '123456'
127.0.0.1:6379> auth '123456'
OK
127.0.0.1:6379> set k1 v1
OK
127.0.0.1:6379> get k1
"v1"
127.0.0.1:6379>

1.6 宿主机修改redis.conf配置文件,验证redis 容器内生效

在Redis的配置文件redis.conf中,可以设置参数databases来指定Redis服务器的数据库数量。

默认情况下,Redis服务器的数据库数量为16,这意味着你可以在一个Redis实例中创建最多16个不同的数据库。每个数据库都是独立的,并且可以使用SELECT命令进行切换。

python 复制代码
1、redis.conf 服务器的数据库数量
databases 16

2、使用SELECT命令切换到指定的数据库。在命令行中输入的SELECT 18表示要切换到数据库18
127.0.0.1:6379> select 18
(error) ERR DB index is out of range
127.0.0.1:6379>

3、修改宿主机redis.conf,保存
databases 20

4、重启 my-redis 容器
docker restart my-redis

5、验证
[root@zyl-server redis.conf]# docker exec -it my-redis redis-cli
127.0.0.1:6379> auth '123456'
OK
127.0.0.1:6379> select 18
OK
127.0.0.1:6379[18]>

----结论---------修改宿主机redis.conf,容器内生效。。

二、Docker复杂软件安装(mysql 主从复制)

2.1 启动主节点容器mysql-master(3306)

python 复制代码
1、启动主节点容器mysql-master:

docker run -p 3306: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=123456 \
-d mysql:5.7

以后台模式运行MySQL 5.7容器作为主节点:
各个选项的含义:

-p 3306:3306:将主机的3306端口映射到容器的3306端口,这样可以从主机上访问MySQL服务。
--name mysql-master:给容器指定一个名称为"mysql-master"。
-v /mydata/mysql-master/log:/var/log/mysql:将主机上的"/mydata/mysql-master/log"目录挂载到容器中的"/var/log/mysql"目录,用于持久化存储MySQL的日志文件。
-v /mydata/mysql-master/data:/var/lib/mysql:将主机上的"/mydata/mysql-master/data"目录挂载到容器中的"/var/lib/mysql"目录,用于持久化存储MySQL的数据文件。
-v /mydata/mysql-master/conf:/etc/mysql:将主机上的"/mydata/mysql-master/conf"目录挂载到容器中的"/etc/mysql"目录,用于持久化存储MySQL的配置文件。
-e MYSQL_ROOT_PASSWORD=123456:设置MySQL的root用户密码为"123456"。
-d mysql:5.7:使用MySQL 5.7镜像启动一个后台运行的容器。

2、列出正在运行的Docker容器:

[root@zyl-server ~]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS         PORTS                                                  NAMES
5ea683a60e95   mysql:5.7   "docker-entrypoint.s..."   5 seconds ago   Up 4 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql-master
[root@zyl-server ~]#

3、cd /mydata/mysql-master/conf目录新建my.cnf文件

vi 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

##将MySQL容器的字符集和排序规则设置为UTF-8编码
collation_server=utf8_general_ci
character_set_server=utf8


4、修改后,重启mysql-master容器实例
[root@zyl-server conf]# docker restart mysql-master
mysql-master
[root@zyl-server conf]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED         STATUS          PORTS                                                  NAMES
5ea683a60e95   mysql:5.7   "docker-entrypoint.s..."   6 minutes ago   Up 16 seconds   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql-master
[root@zyl-server conf]#

5、进入到mysql-master容器
docker exec -it mysql-master /bin/bash

6、进入MySQL容器后以root用户身份登录到MySQL数据库


root@5ea683a60e95:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36-log MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>

7、创建数据同步用户,在MySQL数据库中创建一个名为'slave'的用户,并设置密码为'123456',该用户允许从任何主机连接:

CREATE USER 'slave'@'%' IDENTIFIED BY '123456';

mysql> CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
Query OK, 0 rows affected (0.00 sec)

mysql>


8、为'slave'用户授予复制(REPLICATION)相关的权限和客户端(CLIENT)权限:

GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

mysql> GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';
Query OK, 0 rows affected (0.00 sec)

mysql>

2.2 启动从节点容器mysql-slave(3307)

python 复制代码
1、启动从节点容器mysql-slave:
docker run -p 3307: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=123456 \
-d mysql:5.7

2、列出正在运行的Docker容器:

[root@zyl-server ~]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS         PORTS                                                  NAMES
77e48a50155d   mysql:5.7   "docker-entrypoint.s..."   5 seconds ago    Up 4 seconds   33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp   mysql-slave
5ea683a60e95   mysql:5.7   "docker-entrypoint.s..."   12 minutes ago   Up 6 minutes   0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql-master
[root@zyl-server ~]#

3、cd /mydata/mysql-slave/conf目录新建my.cnf文件
vi my.conf


[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

##将MySQL容器的字符集和排序规则设置为UTF-8编码
collation_server=utf8_general_ci
character_set_server=utf8


4、修改后,重启mysql-slave容器实例:
[root@zyl-server conf]# docker restart mysql-slave
mysql-slave
[root@zyl-server conf]#

[root@zyl-server conf]# docker ps
CONTAINER ID   IMAGE       COMMAND                  CREATED          STATUS          PORTS                                                  NAMES
77e48a50155d   mysql:5.7   "docker-entrypoint.s..."   2 minutes ago    Up 17 seconds   33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp   mysql-slave
5ea683a60e95   mysql:5.7   "docker-entrypoint.s..."   15 minutes ago   Up 9 minutes    0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   mysql-master
[root@zyl-server conf]#

5、在主数据mysql-master库查看主从同步状态

docker exec -it mysql-master /bin/bash

root@5ea683a60e95:/# mysql -u root -p

mysql> show master status;
+-----------------------+----------+--------------+------------------+-------------------+
| File                  | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------------+----------+--------------+------------------+-------------------+
| mall-mysql-bin.000001 |      617 |              | mysql            |                   |
+-----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

mysql>

6、进入mysql-slave 容器:

docker exec -it mysql-slave /bin/bash

mysql -u root -p

[root@zyl-server conf]# docker exec -it mysql-slave /bin/bash
root@77e48a50155d:/# mysql -u root -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36-log MySQL Community Server (GPL)

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql>


7、在从数据库mysql-slave中配置主从复制,配置MySQL复制的主服务器信息:

change master to master_host='192.168.234.10', master_user='slave', master_password='123456', master_port=3306, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;

mysql> change master to master_host='192.168.234.10', master_user='slave', master_password='123456', master_port=3306, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql>


其中master_log_file,master_log_pos为mysql-master中查到的结果:

mysql> show master status;
+-----------------------+----------+--------------+------------------+-------------------+
| File                  | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------------+----------+--------------+------------------+-------------------+
| mall-mysql-bin.000001 |      617 |              | mysql            |                   |
+-----------------------+----------+--------------+------------------+-------------------+
1 row in set (0.00 sec)

各个参数含义如下:

MASTER_HOST:指定主服务器的IP地址或主机名。
MASTER_USER:指定用于复制的用户(在之前创建的'slave'用户)。
MASTER_PASSWORD:指定复制用户的密码。
MASTER_PORT:指定主服务器的端口号。
MASTER_LOG_FILE:指定主服务器的二进制日志文件名。
MASTER_LOG_POS:指定要从哪个位置开始复制主服务器的二进制日志。
MASTER_CONNECT_RETRY:指定在连接失败后重试连接的时间间隔(以秒为单位)。


8、在从数据库mysql-master中查看主从同步状态:

mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State:
                  Master_Host: 192.168.234.10
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 30
              Master_Log_File: mall-mysql-bin.000001
          Read_Master_Log_Pos: 617
               Relay_Log_File: mall-mysql-relay-bin.000001
                Relay_Log_Pos: 4
        Relay_Master_Log_File: mall-mysql-bin.000001
             Slave_IO_Running: No
            Slave_SQL_Running: No
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 617
              Relay_Log_Space: 154
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 0
                  Master_UUID:
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State:
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
1 row in set (0.00 sec)

ERROR:
No query specified

mysql>

当Slave_IO_Running和Slave_SQL_Running状态为"No"时,表示MySQL复制的I/O线程和SQL线程都未在运行。

原因:从数据库未开启主从同步

解决:启动从服务器的复制进程

python 复制代码
9、在从数据库中开启主从同步

mysql> start slave;
Query OK, 0 rows affected (0.00 sec)

mysql>


10、再次在从数据库mysql-master中查看主从同步状态:
mysql> show slave status \G;
*************************** 1. row ***************************
               Slave_IO_State: Waiting for master to send event
                  Master_Host: 192.168.234.10
                  Master_User: slave
                  Master_Port: 3306
                Connect_Retry: 30
              Master_Log_File: mall-mysql-bin.000001
          Read_Master_Log_Pos: 617
               Relay_Log_File: mall-mysql-relay-bin.000002
                Relay_Log_Pos: 325
        Relay_Master_Log_File: mall-mysql-bin.000001
             Slave_IO_Running: Yes
            Slave_SQL_Running: Yes
              Replicate_Do_DB:
          Replicate_Ignore_DB:
           Replicate_Do_Table:
       Replicate_Ignore_Table:
      Replicate_Wild_Do_Table:
  Replicate_Wild_Ignore_Table:
                   Last_Errno: 0
                   Last_Error:
                 Skip_Counter: 0
          Exec_Master_Log_Pos: 617
              Relay_Log_Space: 537
              Until_Condition: None
               Until_Log_File:
                Until_Log_Pos: 0
           Master_SSL_Allowed: No
           Master_SSL_CA_File:
           Master_SSL_CA_Path:
              Master_SSL_Cert:
            Master_SSL_Cipher:
               Master_SSL_Key:
        Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
                Last_IO_Errno: 0
                Last_IO_Error:
               Last_SQL_Errno: 0
               Last_SQL_Error:
  Replicate_Ignore_Server_Ids:
             Master_Server_Id: 101
                  Master_UUID: 4dd5c496-49ba-11ee-a195-0242ac110002
             Master_Info_File: /var/lib/mysql/master.info
                    SQL_Delay: 0
          SQL_Remaining_Delay: NULL
      Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
           Master_Retry_Count: 86400
                  Master_Bind:
      Last_IO_Error_Timestamp:
     Last_SQL_Error_Timestamp:
               Master_SSL_Crl:
           Master_SSL_Crlpath:
           Retrieved_Gtid_Set:
            Executed_Gtid_Set:
                Auto_Position: 0
         Replicate_Rewrite_DB:
                 Channel_Name:
           Master_TLS_Version:
1 row in set (0.00 sec)

ERROR:
No query specified

mysql>

2.3 主数据库建库测试

python 复制代码
1、例如,创建一个名为 "mydatabase" 的数据库:

CREATE DATABASE mydatabase;

2、使用 USE 命令切换到所需的数据库:
USE mydatabase;

3、例如,创建一个名为 "users" 的表,包含 id、name 和 email 列:

CREATE TABLE users (
  id INT,
  name VARCHAR(50),
  email VARCHAR(100)
);

4、使用 INSERT INTO 语句。向 "users" 表插入三条数据:

INSERT INTO users (id, name, email) VALUES
  (1, 'John', 'john@example.com'),
  (2, 'Jane', 'jane@example.com'),
  (3, 'Tom', 'tom@example.com');

2.4 从数据库验证

python 复制代码
1、从数据库查看数据库列表:
mysql> show databases;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mydatabase         |
| mysql              |
| performance_schema |
| sys                |
+--------------------+
5 rows in set (0.00 sec)

mysql>
python 复制代码
2、切换到mydatabase数据库

USE mydatabase;

3、显示当前数据库中的所有表

SHOW TABLES;

4、查询"users"表中的所有记录:

select * from users;


mysql> select * from users;
+------+------+------------------+
| id   | name | email            |
+------+------+------------------+
|    1 | John | john@example.com |
|    2 | Jane | jane@example.com |
|    3 | Tom  | tom@example.com  |
+------+------+------------------+
3 rows in set (0.00 sec)

mysql>

三、Docker复杂软件安装(redis集群--3主3从--分布式存储案例)

3.1 前言--数据库分区技术

哈希取余分区:通过将数据的哈希值与分区数进行取余运算来确定数据所属的分区。例如,如果有4个分区,对数据的哈希值进行取余运算,将其分配到0至3之间的一个分区。这种方法简单且容易实现,但可能会导致数据分布不均衡。

一致性哈希算法分区:一致性哈希算法使用一个哈希环来表示分区的范围,数据的哈希值将映射到哈希环上的某个位置。在一致性哈希算法中,当分区发生变化时,只有少量的数据需要重新映射到新的分区,因此可以实现动态的分区扩展或缩减。这种方法能够提供较好的负载均衡和可扩展性。

哈希槽分区:哈希槽分区将数据均匀地分布在一组预定义的哈希槽中。每个分区被映射到一个哈希槽,数据的哈希值决定了它所属的哈希槽。这种方法可以随着分区数的增加或减少而调整哈希槽数量,从而实现动态的扩展和缩减。这种方法提供了良好的负载均衡和扩展性。

这些分区技术可以用于在数据库中水平划分数据以提高性能、灵活性和可伸缩性。每种分区技术都有其特定的优点和适用场景,选择合适的分区技术应根据具体需求和系统特点进行评估。

3.2 redis集群--3主3从搭建

python 复制代码
1、启动6个Redis节点

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

参数:

--name: 指定容器的名称,例如redis-node-1、redis-node-2等。
--net host: 使用主机网络模式,使容器可以使用主机的网络栈。
--privileged=true: 在容器内部提供特权访问,通常用于需要访问主机设备或文件系统的情况。
-v /data/redis/share/redis-node-X:/data: 将主机上的/data/redis/share/redis-node-X目录挂载到容器内的/data目录,用于持久化存储Redis数据。
redis:6.0.8: 指定使用的Redis镜像及版本号。
--cluster-enabled yes: 启用Redis集群功能。
--appendonly yes: 开启AOF(Append Only File)持久化方式。
--port XXXX: 指定Redis节点的端口号,例如6381、6382等。

2、列出当前正在运行的Docker容器

[root@zyl-server ~]# docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS         PORTS     NAMES
51fa09a6a3e6   redis:6.0.8   "docker-entrypoint.s..."   5 seconds ago   Up 4 seconds             redis-node-6
74faf0961119   redis:6.0.8   "docker-entrypoint.s..."   6 seconds ago   Up 5 seconds             redis-node-5
2bb58b50c70a   redis:6.0.8   "docker-entrypoint.s..."   6 seconds ago   Up 5 seconds             redis-node-4
9a0fd2b62b14   redis:6.0.8   "docker-entrypoint.s..."   6 seconds ago   Up 5 seconds             redis-node-3
cb67d2dfecd0   redis:6.0.8   "docker-entrypoint.s..."   6 seconds ago   Up 6 seconds             redis-node-2
59bcc7ed00e5   redis:6.0.8   "docker-entrypoint.s..."   7 seconds ago   Up 6 seconds             redis-node-1
[root@zyl-server ~]#

3、进入redis-node-1 为6台机器配置构建集群关系

redis-cli --cluster create 192.168.234.10:6381 192.168.234.10:6382 192.168.234.10:6383 192.168.234.10:6384 192.168.234.10:6385 192.168.234.10:6386 --cluster-replicas 1

[root@zyl-server ~]# docker exec -it redis-node-1 /bin/bash
root@zyl-server:/data# redis-cli --cluster create 192.168.234.10:6381 192.168.234.10:6382 192.168.234.10:6383 192.168.234.10:6384 192.168.234.10:6385 192.168.234.10:6386 --cluster-replicas 1
>>> Performing hash slots allocation on 6 nodes...
Master[0] -> Slots 0 - 5460
Master[1] -> Slots 5461 - 10922
Master[2] -> Slots 10923 - 16383
Adding replica 192.168.234.10:6385 to 192.168.234.10:6381
Adding replica 192.168.234.10:6386 to 192.168.234.10:6382
Adding replica 192.168.234.10:6384 to 192.168.234.10:6383
>>> Trying to optimize slaves allocation for anti-affinity
[WARNING] Some slaves are in the same host as their master
M: 1ea11eda762c317ac5b9f398827c51085e553652 192.168.234.10:6381
   slots:[0-5460] (5461 slots) master
M: f0a14e3d08738655dd7ed0b702187f7096f06bba 192.168.234.10:6382
   slots:[5461-10922] (5462 slots) master
M: 553a35ceea6fb2f0d2c668923d6650f65525a370 192.168.234.10:6383
   slots:[10923-16383] (5461 slots) master
S: dd03b2ff3629d360da59294c0b547849de41e8fb 192.168.234.10:6384
   replicates f0a14e3d08738655dd7ed0b702187f7096f06bba
S: 0b1cfb29bc066c74a831a948e3c23f8dc6e0bbe6 192.168.234.10:6385
   replicates 553a35ceea6fb2f0d2c668923d6650f65525a370
S: 6ebb4441ded1cfb4ce346e4349e155a685acdffd 192.168.234.10:6386
   replicates 1ea11eda762c317ac5b9f398827c51085e553652
Can I set the above configuration? (type 'yes' to accept): yes
>>> Nodes configuration updated
>>> Assign a different config epoch to each node
>>> Sending CLUSTER MEET messages to join the cluster
Waiting for the cluster to join
.
>>> Performing Cluster Check (using node 192.168.234.10:6381)
M: 1ea11eda762c317ac5b9f398827c51085e553652 192.168.234.10:6381
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
M: f0a14e3d08738655dd7ed0b702187f7096f06bba 192.168.234.10:6382
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
S: 0b1cfb29bc066c74a831a948e3c23f8dc6e0bbe6 192.168.234.10:6385
   slots: (0 slots) slave
   replicates 553a35ceea6fb2f0d2c668923d6650f65525a370
M: 553a35ceea6fb2f0d2c668923d6650f65525a370 192.168.234.10:6383
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
S: 6ebb4441ded1cfb4ce346e4349e155a685acdffd 192.168.234.10:6386
   slots: (0 slots) slave
   replicates 1ea11eda762c317ac5b9f398827c51085e553652
S: dd03b2ff3629d360da59294c0b547849de41e8fb 192.168.234.10:6384
   slots: (0 slots) slave
   replicates f0a14e3d08738655dd7ed0b702187f7096f06bba
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
python 复制代码
4、主节点查看集群状态
root@zyl-server:/data# redis-cli -p 6381

##获取有关Redis集群的信息,例如集群的状态、节点数量、槽位分配情况
127.0.0.1:6381> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:6
cluster_my_epoch:1
cluster_stats_messages_ping_sent:138
cluster_stats_messages_pong_sent:146
cluster_stats_messages_sent:284
cluster_stats_messages_ping_received:141
cluster_stats_messages_pong_received:138
cluster_stats_messages_meet_received:5
cluster_stats_messages_received:284
127.0.0.1:6381>

##获取当前集群中所有节点的信息
127.0.0.1:6381> cluster nodes
f0a14e3d08738655dd7ed0b702187f7096f06bba 192.168.234.10:6382@16382 master - 0 1693680656000 2 connected 5461-10922
0b1cfb29bc066c74a831a948e3c23f8dc6e0bbe6 192.168.234.10:6385@16385 slave 553a35ceea6fb2f0d2c668923d6650f65525a370 0 1693680659111 3 connected
1ea11eda762c317ac5b9f398827c51085e553652 192.168.234.10:6381@16381 myself,master - 0 1693680659000 1 connected 0-5460
553a35ceea6fb2f0d2c668923d6650f65525a370 192.168.234.10:6383@16383 master - 0 1693680657069 3 connected 10923-16383
6ebb4441ded1cfb4ce346e4349e155a685acdffd 192.168.234.10:6386@16386 slave 1ea11eda762c317ac5b9f398827c51085e553652 0 1693680658091 1 connected
dd03b2ff3629d360da59294c0b547849de41e8fb 192.168.234.10:6384@16384 slave f0a14e3d08738655dd7ed0b702187f7096f06bba 0 1693680660128 2 connected
127.0.0.1:6381>

3.3 redis集群--主从容错切换迁移案例

master:6381下线,slave:6386上位:

python 复制代码
1、停止redis-node-1的Docker容器

[root@zyl-server ~]# docker stop redis-node-1
redis-node-1
[root@zyl-server ~]#

2、列出当前正在运行的Docker容器

[root@zyl-server ~]# docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED        STATUS        PORTS     NAMES
51fa09a6a3e6   redis:6.0.8   "docker-entrypoint.s..."   10 hours ago   Up 10 hours             redis-node-6
74faf0961119   redis:6.0.8   "docker-entrypoint.s..."   10 hours ago   Up 10 hours             redis-node-5
2bb58b50c70a   redis:6.0.8   "docker-entrypoint.s..."   10 hours ago   Up 10 hours             redis-node-4
9a0fd2b62b14   redis:6.0.8   "docker-entrypoint.s..."   10 hours ago   Up 10 hours             redis-node-3
cb67d2dfecd0   redis:6.0.8   "docker-entrypoint.s..."   10 hours ago   Up 10 hours             redis-node-2
[root@zyl-server ~]#

3、进入名为redis-node-2的Docker容器

docker exec -it redis-node-2 /bin/bash

4、连接到Redis节点
root@zyl-server:/data# redis-cli -p 6382
127.0.0.1:6382>

5、##获取有关Redis集群的信息,例如集群的状态、节点数量、槽位分配情况
127.0.0.1:6382> cluster info
cluster_state:ok
cluster_slots_assigned:16384
cluster_slots_ok:16384
cluster_slots_pfail:0
cluster_slots_fail:0
cluster_known_nodes:6
cluster_size:3
cluster_current_epoch:7
cluster_my_epoch:2
cluster_stats_messages_ping_sent:1260
cluster_stats_messages_pong_sent:1243
cluster_stats_messages_meet_sent:1
cluster_stats_messages_auth-ack_sent:1
cluster_stats_messages_sent:2505
cluster_stats_messages_ping_received:1243
cluster_stats_messages_pong_received:1261
cluster_stats_messages_fail_received:1
cluster_stats_messages_auth-req_received:1
cluster_stats_messages_received:2506
127.0.0.1:6382>



##获取当前集群中所有节点的信息
127.0.0.1:6382> cluster nodes
6ebb4441ded1cfb4ce346e4349e155a685acdffd 192.168.234.10:6386@16386 master - 0 1693716720009 7 connected 0-5460
1ea11eda762c317ac5b9f398827c51085e553652 192.168.234.10:6381@16381 master,fail - 1693716449472 1693716444000 1 disconnected
0b1cfb29bc066c74a831a948e3c23f8dc6e0bbe6 192.168.234.10:6385@16385 slave 553a35ceea6fb2f0d2c668923d6650f65525a370 0 1693716719000 3 connected
553a35ceea6fb2f0d2c668923d6650f65525a370 192.168.234.10:6383@16383 master - 0 1693716721031 3 connected 10923-16383
f0a14e3d08738655dd7ed0b702187f7096f06bba 192.168.234.10:6382@16382 myself,master - 0 1693716720000 2 connected 5461-10922
dd03b2ff3629d360da59294c0b547849de41e8fb 192.168.234.10:6384@16384 slave f0a14e3d08738655dd7ed0b702187f7096f06bba 0 1693716722056 2 connected
127.0.0.1:6382>

还原之前的3主3从:

python 复制代码
1、启动名为redis-node-1的Docker容器
[root@zyl-server ~]# docker start redis-node-1
redis-node-1
[root@zyl-server ~]#

2、获取当前集群中所有节点的信息

127.0.0.1:6382> cluster nodes
6ebb4441ded1cfb4ce346e4349e155a685acdffd 192.168.234.10:6386@16386 master - 0 1693716888112 7 connected 0-5460
1ea11eda762c317ac5b9f398827c51085e553652 192.168.234.10:6381@16381 slave 6ebb4441ded1cfb4ce346e4349e155a685acdffd 0 1693716888000 7 connected
0b1cfb29bc066c74a831a948e3c23f8dc6e0bbe6 192.168.234.10:6385@16385 slave 553a35ceea6fb2f0d2c668923d6650f65525a370 0 1693716887097 3 connected
553a35ceea6fb2f0d2c668923d6650f65525a370 192.168.234.10:6383@16383 master - 0 1693716889129 3 connected 10923-16383
f0a14e3d08738655dd7ed0b702187f7096f06bba 192.168.234.10:6382@16382 myself,master - 0 1693716887000 2 connected 5461-10922
dd03b2ff3629d360da59294c0b547849de41e8fb 192.168.234.10:6384@16384 slave f0a14e3d08738655dd7ed0b702187f7096f06bba 0 1693716886000 2 connected
127.0.0.1:6382>
python 复制代码
3、停止上位的slave:6386,相当于给master:6381,上位机会

docker stop redis-node-6

4、获取当前集群中所有节点的信息

127.0.0.1:6382>  cluster nodes
6ebb4441ded1cfb4ce346e4349e155a685acdffd 192.168.234.10:6386@16386 master,fail - 1693717524807 1693717521000 7 disconnected
1ea11eda762c317ac5b9f398827c51085e553652 192.168.234.10:6381@16381 master - 0 1693717614888 8 connected 0-5460
0b1cfb29bc066c74a831a948e3c23f8dc6e0bbe6 192.168.234.10:6385@16385 slave 553a35ceea6fb2f0d2c668923d6650f65525a370 0 1693717614000 3 connected
553a35ceea6fb2f0d2c668923d6650f65525a370 192.168.234.10:6383@16383 master - 0 1693717612843 3 connected 10923-16383
f0a14e3d08738655dd7ed0b702187f7096f06bba 192.168.234.10:6382@16382 myself,master - 0 1693717615000 2 connected 5461-10922
dd03b2ff3629d360da59294c0b547849de41e8fb 192.168.234.10:6384@16384 slave f0a14e3d08738655dd7ed0b702187f7096f06bba 0 1693717615913 2 connected
127.0.0.1:6382>
python 复制代码
5、重新启动6386

[root@zyl-server ~]# docker start redis-node-6
redis-node-6
[root@zyl-server ~]#

6、获取当前集群中所有节点的信息

127.0.0.1:6382> cluster nodes
6ebb4441ded1cfb4ce346e4349e155a685acdffd 192.168.234.10:6386@16386 slave 1ea11eda762c317ac5b9f398827c51085e553652 0 1693717773565 8 connected
1ea11eda762c317ac5b9f398827c51085e553652 192.168.234.10:6381@16381 master - 0 1693717772000 8 connected 0-5460
0b1cfb29bc066c74a831a948e3c23f8dc6e0bbe6 192.168.234.10:6385@16385 slave 553a35ceea6fb2f0d2c668923d6650f65525a370 0 1693717773000 3 connected
553a35ceea6fb2f0d2c668923d6650f65525a370 192.168.234.10:6383@16383 master - 0 1693717771000 3 connected 10923-16383
f0a14e3d08738655dd7ed0b702187f7096f06bba 192.168.234.10:6382@16382 myself,master - 0 1693717772000 2 connected 5461-10922
dd03b2ff3629d360da59294c0b547849de41e8fb 192.168.234.10:6384@16384 slave f0a14e3d08738655dd7ed0b702187f7096f06bba 0 1693717771547 2 connected
127.0.0.1:6382>

3.4 redis集群--读写error

python 复制代码
1、进入redis-node-1,set k1 v1

[root@zyl-server ~]# docker exec -it redis-node-1 /bin/bash

root@zyl-server:/data# redis-cli -p 6381
127.0.0.1:6381> set k1 v1
(error) MOVED 12706 192.168.234.10:6383
127.0.0.1:6381> set k2 v2
OK
127.0.0.1:6381> set k3 v3
OK
127.0.0.1:6381> set k4 v4
(error) MOVED 8455 192.168.234.10:6382
127.0.0.1:6381>

这个错误提示是因为尝试执行的命令被Redis集群转发到了错误的节点。在Redis集群中,不同的槽位可能分布在不同的节点上,并且某些命令需要在正确的节点上执行。

解决方法如下:使用-c 选项来启用集群模式

python 复制代码
首先,使用redis-cli连接到Redis集群中的任意一个节点:redis-cli -c -h <任意一个节点IP地址> -p <任意一个节点端口>。
root@zyl-server:/data# redis-cli -p 6381 -c
127.0.0.1:6381> FLUSHALL  ##清空当前Redis节点上的所有数据
OK
127.0.0.1:6381>


2、使用了-c 选项来启用集群模式,后再set测试
在集群中,不同的键会根据其哈希值被分配到不同的槽位和节点上。

127.0.0.1:6381> set k1 v1
-> Redirected to slot [12706] located at 192.168.234.10:6383
OK
192.168.234.10:6383> set k2 v2
-> Redirected to slot [449] located at 192.168.234.10:6381
OK
192.168.234.10:6381> set k3 v3
OK
192.168.234.10:6381> set k4 v4
-> Redirected to slot [8455] located at 192.168.234.10:6382
OK
192.168.234.10:6382>


键"k1"被重定向到位于192.168.234.10:6383的槽位[12706]上。
键"k2"被重定向到位于192.168.234.10:6381的槽位[449]上。
键"k3"直接被设置在位于192.168.234.10:6381的节点上。
键"k4"被重定向到位于192.168.234.10:6382的槽位[8455]上。

3.5 redis集群--主从扩容案例(4主4从)

在原来3主3从基础上,变为4主4从,新增master:6387,slave:6388。

新建6387、6388两个节点+新建后启动+查看是否8节点。

python 复制代码
1、创建两个Redis节点,并将它们加入到Redis集群中
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

-d参数表示以后台模式运行容器。
--name参数指定了容器的名称为"redis-node-7"。
--net host参数表示容器与主机共享网络命名空间,以便容器能够使用主机的网络。
--privileged=true参数授予容器特权级别,以便在容器中执行底层操作。
-v /data/redis/share/redis-node-7:/data参数将主机上的目录/data/redis/share/redis-node-7挂载到容器内的/data目录。这样可以持久化保存容器内的数据。
redis:7.0.9指定了使用的Redis镜像和版本。
--cluster-enabled yes表示启用Redis集群。
--appendonly yes表示启用AOF(Append Only File)持久化模式。
--port 6387表示将Redis节点的端口设置为6387。

2、列出正在运行的Docker容器
docker ps
[root@zyl-server ~]# docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED         STATUS          PORTS     NAMES
d9a5a558f377   redis:6.0.8   "docker-entrypoint.s..."   5 seconds ago   Up 4 seconds              redis-node-8
26773aa52c7c   redis:6.0.8   "docker-entrypoint.s..."   6 seconds ago   Up 5 seconds              redis-node-7
51fa09a6a3e6   redis:6.0.8   "docker-entrypoint.s..."   11 hours ago    Up 38 minutes             redis-node-6
74faf0961119   redis:6.0.8   "docker-entrypoint.s..."   11 hours ago    Up 11 hours               redis-node-5
2bb58b50c70a   redis:6.0.8   "docker-entrypoint.s..."   11 hours ago    Up 11 hours               redis-node-4
9a0fd2b62b14   redis:6.0.8   "docker-entrypoint.s..."   11 hours ago    Up 11 hours               redis-node-3
cb67d2dfecd0   redis:6.0.8   "docker-entrypoint.s..."   11 hours ago    Up 11 hours               redis-node-2
59bcc7ed00e5   redis:6.0.8   "docker-entrypoint.s..."   11 hours ago    Up 53 minutes             redis-node-1
[root@zyl-server ~]#


3、进入6387容器实例内部
docker exec -it redis-node-7 /bin/bash


4、将新增的6387节点(空槽号)作为master节点加入原集群
redis-cli --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381
6387 就是将要作为master新增节点
6381 就是原来集群节点里面的领路人,相当于6387拜拜6381的码头从而找到组织加入集群

redis-cli --cluster add-node 192.168.234.10:6387 192.168.234.10:6381

root@zyl-server:/data# redis-cli --cluster add-node 192.168.234.10:6387 192.168.234.10:6381
>>> Adding node 192.168.234.10:6387 to cluster 192.168.234.10:6381
>>> Performing Cluster Check (using node 192.168.234.10:6381)
M: 1ea11eda762c317ac5b9f398827c51085e553652 192.168.234.10:6381
   slots:[0-5460] (5461 slots) master
   1 additional replica(s)
S: 0b1cfb29bc066c74a831a948e3c23f8dc6e0bbe6 192.168.234.10:6385
   slots: (0 slots) slave
   replicates 553a35ceea6fb2f0d2c668923d6650f65525a370
S: 6ebb4441ded1cfb4ce346e4349e155a685acdffd 192.168.234.10:6386
   slots: (0 slots) slave
   replicates 1ea11eda762c317ac5b9f398827c51085e553652
S: dd03b2ff3629d360da59294c0b547849de41e8fb 192.168.234.10:6384
   slots: (0 slots) slave
   replicates f0a14e3d08738655dd7ed0b702187f7096f06bba
M: f0a14e3d08738655dd7ed0b702187f7096f06bba 192.168.234.10:6382
   slots:[5461-10922] (5462 slots) master
   1 additional replica(s)
M: 553a35ceea6fb2f0d2c668923d6650f65525a370 192.168.234.10:6383
   slots:[10923-16383] (5461 slots) master
   1 additional replica(s)
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered.
>>> Getting functions from cluster
>>> Failed retrieving Functions from the cluster, skip this step as Redis version do not support function command (error = 'ERR unknown command `FUNCTION`, with args beginning with: `DUMP`, ')
>>> Send CLUSTER MEET to node 192.168.234.10:6387 to make it join the cluster.
[OK] New node added correctly.
root@zyl-server:/data#
python 复制代码
5、检查集群情况第1次,6387没有任何键、槽位或从节点。
redis-cli --cluster check 192.168.234.10:6381
python 复制代码
6、重新分派槽号
命令:redis-cli --cluster reshard IP地址:端口号

redis-cli --cluster reshard 192.168.234.10:6381
python 复制代码
7、检查集群情况第2次

root@zyl-server:/data# redis-cli --cluster check 192.168.234.10:6381

为什么6387是3个新的区间,以前的槽位号还是连续?

重新分配成本太高,所以前3家各自匀出来一部分,从6381/6382/6383三个旧节点分别匀出1364个坑位给新节点6387。

python 复制代码
8、为主节点6387分配从节点6388

命令:redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID


redis-cli --cluster add-node 192.168.234.10:6388 192.168.234.10:6387 --cluster-slave --cluster-master-id a8a40f0db21abc2db2c159e9c7931d2a7acdc8f2  -------这个是6387的编号,按照自己实际情况

redis-cli --cluster add-node 192.168.234.10:6388 192.168.234.10:6387  --cluster-slave --cluster-master-id a8a40f0db21abc2db2c159e9c7931d2a7acdc8f2
python 复制代码
9、检查集群情况第3次
redis-cli --cluster check 192.168.234.10:6381

redis集群--主从扩容案例(4主4从)------------------成功!!!


3.6 redis集群--主从缩容案例(4主4从--->3主3从)

目的:6387和6388下线。

python 复制代码
1、检查集群情况1获得6388的节点ID

redis-cli --cluster check 192.168.234.10:6388

a0abf90dbec7d33cb0cd3179cb5efb7e653a1a4c

2、将6388删除 ,从集群中将4号从节点6388删除

命令:redis-cli --cluster del-node ip:从机端口 从机6388节点ID

redis-cli --cluster del-node 192.168.234.10:6388 a0abf90dbec7d33cb0cd3179cb5efb7e653a1a4c

root@zyl-server:/data# redis-cli --cluster del-node 192.168.234.10:6388 a03a551fb6f8320ee404f07254e6c934beb52d7e
>>> Removing node a03a551fb6f8320ee404f07254e6c934beb52d7e from cluster 192.168.234.10:6388
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
root@zyl-server:/data#
python 复制代码
3、再次检查集群
redis-cli --cluster check 192.168.234.10:6381
python 复制代码
4、将6387的槽号清空,重新分配,本例将清出来的槽号都给6381
redis-cli --cluster reshard 192.168.234.10:6381
python 复制代码
5、检查集群情况第二次
redis-cli --cluster check 192.168.234.10:6381
python 复制代码
6、将6387删除
命令:redis-cli --cluster del-node ip:端口 6387节点ID

redis-cli --cluster del-node 192.168.234.10:6387 f0eea5b2dfe28c742b00bb660bb67a2d0ee30004


root@zyl-server:/data# redis-cli --cluster del-node 192.168.234.10:6387 f0eea5b2dfe28c742b00bb660bb67a2d0ee30004
>>> Removing node f0eea5b2dfe28c742b00bb660bb67a2d0ee30004 from cluster 192.168.234.10:6387
>>> Sending CLUSTER FORGET messages to the cluster...
>>> Sending CLUSTER RESET SOFT to the deleted node.
root@zyl-server:/data#


7、检查集群情况第三次
redis-cli --cluster check 192.168.234.10:6381

redis集群--主从缩容案例(4主4从--->3主3从)------------------成功!!!


|---------------------------|
| 💖The End💖点点关注,收藏不迷路💖 |

相关推荐
百结2144 小时前
Mysql数据库操作
数据库·mysql·oracle
Leinwin4 小时前
OpenClaw 多 Agent 协作框架的并发限制与企业化规避方案痛点直击
java·运维·数据库
2401_865382504 小时前
信息化项目运维与运营的区别
运维·运营·信息化项目·政务信息化
漠北的哈士奇4 小时前
VMware Workstation导入ova文件时出现闪退但是没有报错信息
运维·vmware·虚拟机·闪退·ova
ego.iblacat5 小时前
MySQL 服务基础
数据库·mysql
如意.7595 小时前
【Linux开发工具实战】Git、GDB与CGDB从入门到精通
linux·运维·git
运维小欣5 小时前
智能体选型实战指南
运维·人工智能
yy55275 小时前
Nginx 性能优化与监控
运维·nginx·性能优化
爱吃土豆的马铃薯ㅤㅤㅤㅤㅤㅤㅤㅤㅤ6 小时前
Linux 查询某进程文件所在路径 命令
linux·运维·服务器
攒了一袋星辰7 小时前
高并发强一致性顺序号生成系统 -- SequenceGenerator
java·数据库·mysql