当前位置: 首页 > java >正文

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;

    查看从数据库状态发现已经同步

    主从复制测试

    1. 主机新建库-使用库-新建表-插入数据,ok
    2. 从机使用库-查看记录,ok

    三、Redis集群搭建

    面试题

    1~2亿条数据需要缓存,请问如何设计这个存储案例?

    回答:单机单台100%不可能,肯定是分布式存储,用redis如何落地?

    上述问题阿里P6~P7工程案例和场景设计类必考题目, 一般业界有3种解决方案

    1. 哈希取余分区
    2. 一致性哈希算法分区
    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已经没有了,集群又恢复到了三主三从。


    感谢阅读!

    http://www.xdnf.cn/news/18267.html

    相关文章:

  1. java线程池相关知识
  2. XR(AR/VR/MR)芯片方案,Soc VS “MCU+协处理器”?
  3. 【动态规划、dp】P4933 大师
  4. pnpm : 无法加载文件 C:\Program Files\nodejs\pnpm.ps1,因为在此系统上禁止运行脚本。
  5. C++之多态(从0到1的突破)
  6. Python如何将两个列表转化为一个字典
  7. 基于STM32的APP遥控视频水泵小车设计
  8. Codeforces MIN = GCD
  9. Python爬虫实战:研究dark-fantasy,构建奇幻文学数据采集分析系统
  10. BM25 vs TF-IDF:经典文本检索方法的对比
  11. 【39】OpenCV C++实战篇——直线拟合、直线测距、平行线段测距;(边缘检测,剔除噪点,轮廓检测,渐进概率霍夫直线)
  12. Django管理后台结合剪映实现课件视频生成应用
  13. MySQL架构
  14. MySQL实战45讲 24-25
  15. hadoop技术栈(九)Hbase替代方案
  16. Linux 进程间通信(IPC):信号、共享内存
  17. Vue3 el-table实现 将子表字段动态显示在主表行尾
  18. MySQL 三大日志:redo log、undo log、binlog 详解
  19. 在职老D渗透日记day21:sqli-labs靶场通关(第27a关)get联合注入 过滤select和union “闭合
  20. 趣谈设计模式之策略模式-比特咖啡给你一杯满满的情绪价值,让您在数字世界里”畅饮“
  21. 基于VLM 的机器人操作视觉-语言-动作模型:综述 2
  22. 选项式api和组合式api
  23. 如何将Date类型的数据转换为LocalDateTime类型
  24. Git的初步学习
  25. 【力扣 Hot100】 刷题日记——双指针的经典应用
  26. RabbitMQ:SpringAMQP Fanout Exchange(扇型交换机)
  27. Java技术总监的成长之路(技术干货分享)
  28. 驱动开发系列65 - NVIDIA 开源GPU驱动open-gpu-kernel-modules 目录结构
  29. 【PyTorch】多对象分割项目
  30. Apache Doris 4.0 AI 能力揭秘(一):AI 函数之 LLM 函数介绍