Docker集群部署MySQL、Redis集群实例

Docker / Docker Swarm · 2022-11-11 · 784 人浏览
Docker集群部署MySQL、Redis集群实例

Docker集群部署MySQL、Redis集群实例

简介

image-20220817141638655

需要具备的基础

  • MySQL数据库开发能力
  • 了解Redis,会简单操作
  • 了解Linux指令,能在Linux上安装卸载软件

哪里需要集群?

image-20220817142139526

前后端分离部署图

image-20220817143621533

image-20220817144044877

项目Demo

  • renrenfast开源前后端项目

Linux基础强化

firewalld防火墙

  • centos7默认安装了firewalld防火墙
  • 通过防火墙允许或限制数据的通过
管理防火墙
查看状态
firewall-cmd --state
启动、关闭、重启防火墙
service firewall start
service firewall stop
service firewall restart
端口管理
# 开放
firewall-cmd --permanent --add-port=8080-8085/tcp
# 重新加载防火墙配置
firewall-cmd --reload
# 关闭端口,要与之前写的add时开放的端口范围相同,不能开放多个端口,只关闭一个端口
firewall-cmd --permanent --remove-port=8080-8085/tcp
查看开启的端口
firewall-cmd --permanent --list-ports
查看使用网络的服务
firewall-cmd --permanent --list-services

云计算中的Docker

image-20220817155426675

Docker容器管理命令

image-20220817155749789

Docker镜像导入导出

docker save java > /home/java.tar.gz
docker load java < /home/java.tar.gz

Docker暂停 停止容器

docker pause container-name
docker unpause container-name
docker stop container-name
docker start -i container-name

MySQL集群搭建

常见MySQL集群方案

image-20220817161655710

选用PXC集群方式。

PXC原理

  • PXC(Percona XtraDB Cluster)

image-20220822124834235

  • 任何一个节点都可读可写
  • 建议PXC使用Percona Server(MySQL改进版,性能提升很大)

PXC与Replication方案对比

image-20220817162040057

image-20220817162124018

PXC的数据强一致性

  • PXC同步复制,事务在所有集群节点要么同时提交,要么不提交

image-20220817162459703

  • Replication采用异步复制,无法保证数据一致性

image-20220817162541964

PXC集群安装

  • 最新的PXC版本是PXC8.0,即对应MySQL8.0。本实验使用PXC5.7,即对应MySQL5.7,主要是因为大部分项目都采用的MySQL5.7
实验版本最新版本
PXC5.78.0
XtraBackup2.48.0

节点分配

物理机IP: 10.248.192.137

Docker内部网段子网掩码:172.18.0.0/24

节点docker内部IP映射物理机端口
MySQL-node1172.17.0.23306
MySQL-node2172.17.0.33307
MySQL-node3172.17.0.43308
MySQL-node4172.17.0.53309
MySQL-node4172.17.0.63310
Haproxy172.17.0.74001 WEB看板端口<br/>4002 MySQL负载均衡入口

拉取Docker镜像

docker pull percona/percona-xtradb-cluster
docker image ls

由于镜像的名字太长,不便于使用,我们可以在本地对镜像名称进行修改

docker tag percona/percona-xtradb-cluster pxc
docker image ls

此时可以把原来的镜像删除掉

docker iamge rm percona/percona-xtradb-cluster pxc

创建内部网络

  • 出于安全考虑,需要给PXC集群实例创建Docker内部网络
# 创建网段
docker network create net1
# 查看网段信息
docker network inspect net1
# 删除网段
docker network rm net1
  • docker默认的网段是172.17.0.x
  • 创建网络的时候不指定网段,会默认从dokcer默认网段向下排,例如下一个网段是172.18.0.x
  • 创建指定网段
docker network create --subnet=172.18.0.0/24 net1
docker inspect net1
# 如果删除
docker network rm net1
  • 子网掩码172.18.0.0/24中的/24的意思是172.17.0前三位固定,最后一位动,即子网掩码为255.255.255.0,用二进制表示前面就是24位1
  • 如果子网掩码是172.18.0.0/16,那么172.18固定,后面两个段动。

创建Docker卷

  • 业务数据通常存在物理机里,而不是存在容器内
  • PXC无法使用目录映射方式运行(启动会闪退),所以需要使用Docker卷技术
# --name可以省略不写
docker volume create --name v1
docker inspect v1
[
    {
        "CreatedAt": "2022-08-18T09:41:14+08:00",
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/snap/docker/common/var-lib-docker/volumes/v1/_data",
        "Name": "v1",
        "Options": {},
        "Scope": "local"
    }
]
# 如果删除
docker volume rm v1

volume在物理机的/var/snap/docker/common/var-lib-docker/volumes/v1/_data位置

创建PXC容器

  • 向PXC镜像传入运行参数就能创建出PXC容器
  • MYSQL_ROOT_PASSWORD 数据库密码,账户默认为root
  • CLUSTER_NAME 集群名称
  • XTRABACKUP_PASSWORD 数据库节点之间同步的密码
  • --privileged:使用该参数,container内的root拥有真正的root权限
  • 使用pxc镜像
  • 第一个启动的PXC节点是主节点,它要初始化PXC集群
  • PXC启动之后,就没有主节点角色
  • PXC集群任何一个节点都是可以读写数据的
# 第一个PXC
docker run -d -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=abc123456 \
-e CLUSTER_NAME=PXC \
-e XTRABACKUP_PASSWORD=abc123456 \
-v v1:/var/lib/mysql \
--privileged \
--name=node1 \
--net=net1 --ip=172.18.0.2 \
pxc

# 创建第2、3、4、5个volume
# docker volume create --name v1 上面创建过了
docker volume create --name v2
docker volume create --name v3
docker volume create --name v4
docker volume create --name v5

# 创建其他4个节点
# 需要修改端口、挂载卷名、IP、容器名,同时增加CLUSTER_JOIN参数

# 第2个PXC
docker run -d -p 3307:3306 \
-e MYSQL_ROOT_PASSWORD=abc123456 \
-e CLUSTER_NAME=PXC \
-e XTRABACKUP_PASSWORD=abc123456 \
-e CLUSTER_JOIN=node1 \
-v v2:/var/lib/mysql \
--privileged --name=node2 \
--net=net1 --ip=172.18.0.3 \
pxc

# 第3个PXC
docker run -d -p 3308:3306 -e CLUSTER_NAME=PXC -e MYSQL_ROOT_PASSWORD=abc123456 -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v3:/var/lib/mysql --privileged --name=node3 --net=net1 --ip=172.18.0.4 pxc
# 第4个PXC
docker run -d -p 3309:3306 -e CLUSTER_NAME=PXC -e MYSQL_ROOT_PASSWORD=abc123456 -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v4:/var/lib/mysql --privileged --name=node4 --net=net1 --ip=172.18.0.5 pxc
# 第5个PXC
docker run -d -p 3310:3306 -e CLUSTER_NAME=PXC -e MYSQL_ROOT_PASSWORD=abc123456 -e XTRABACKUP_PASSWORD=abc123456 -e CLUSTER_JOIN=node1 -v v5:/var/lib/mysql --privileged --name=node5 --net=net1 --ip=172.18.0.6 pxc
  • 必须主节点可以访问了,才能创建从节点,否则会闪退
docker container ls
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                                                                 NAMES
6563dac8b2ae   pxc       "/entrypoint.sh mysq…"   6 seconds ago    Up 6 seconds    4567-4568/tcp, 33060/tcp, 0.0.0.0:3310->3306/tcp, :::3310->3306/tcp   node5
17c1d1314252   pxc       "/entrypoint.sh mysq…"   8 seconds ago    Up 8 seconds    4567-4568/tcp, 33060/tcp, 0.0.0.0:3309->3306/tcp, :::3309->3306/tcp   node4
e58f6800f23d   pxc       "/entrypoint.sh mysq…"   9 seconds ago    Up 8 seconds    4567-4568/tcp, 33060/tcp, 0.0.0.0:3308->3306/tcp, :::3308->3306/tcp   node3
45df9d0864fb   pxc       "/entrypoint.sh mysq…"   26 seconds ago   Up 26 seconds   4567-4568/tcp, 33060/tcp, 0.0.0.0:3307->3306/tcp, :::3307->3306/tcp   node2
893961f0c9e3   pxc       "/entrypoint.sh mysq…"   14 minutes ago   Up 14 minutes   4567-4568/tcp, 0.0.0.0:3306->3306/tcp, :::3306->3306/tcp, 33060/tcp   node1

node2-node5闪退问题(PXC8.0)

上面的步骤操作完后,过一会儿node2-node5会闪退。本实验使用的是PXC8.0(Percona Server for MySQL 8.0),直接启动node2-5会出现MySQL无法启动的情况。查看log信息大致如下:

2022-08-18T06:24:23.078258Z 0 [ERROR] [MY-000000] [Galera] failed to open gcomm backend connection: 110: failed to reach primary view (pc.wait_prim_timeout): 110 (Connection timed out)
         at gcomm/src/pc.cpp:connect():161
2022-08-18T06:24:23.078271Z 0 [ERROR] [MY-000000] [Galera] gcs/src/gcs_core.cpp:gcs_core_open():219: Failed to open backend connection: -110 (Connection timed out)
2022-08-18T06:24:24.078556Z 0 [Note] [MY-000000] [Galera] gcomm: terminating thread
2022-08-18T06:24:24.078655Z 0 [Note] [MY-000000] [Galera] gcomm: joining thread
2022-08-18T06:24:24.078865Z 0 [ERROR] [MY-000000] [Galera] gcs/src/gcs.cpp:gcs_open():1811: Failed to open channel 'PXC' at 'gcomm://node1': -110 (Connection timed out)
2022-08-18T06:24:24.078959Z 0 [ERROR] [MY-000000] [Galera] gcs connect failed: Connection timed out
2022-08-18T06:24:24.079004Z 0 [ERROR] [MY-000000] [WSREP] Provider/Node (gcomm://node1) failed to establish connection with cluster (reason: 7)
2022-08-18T06:24:24.079052Z 0 [ERROR] [MY-010119] [Server] Aborting
2022-08-18T06:24:24.079551Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.28-19.1)  Percona XtraDB Cluster (GPL), Release rel19, Revision f544540, WSREP version 26.4.3.

虽说报错信息和文章中的不一样,但是确实是我在参考其他资料时没有提到的一点,一个变量:pxc-encrypt-cluster-traffic上,根据官网资料,pxc-encrypt-cluster-traffic 变量默认是启用,所以要求所有节点使用相同的密钥和证书文件,MySQL生成默认密钥和证书文件,并将其放在数据目录中。这些自动生成的文件适用于自动 SSL 配置。所以将第一个节点数据目录下的 *.pem全部复制到第二个节点,再次执行systemctl start mysql命令,节点正常启动

所以,通过docker inspect node1查看v1卷的物理路径,然后复制其证书文件到v2、v3、v4、v5卷中即可。

cp *.pem /var/snap/docker/common/var-lib-docker/volumes/v2/_data/
cp *.pem /var/snap/docker/common/var-lib-docker/volumes/v3/_data/
cp *.pem /var/snap/docker/common/var-lib-docker/volumes/v4/_data/
cp *.pem /var/snap/docker/common/var-lib-docker/volumes/v5/_data/

再重启node2-node5的容器即可

docker container stop node2 node3 node4 node5
docker container start node2 node3 node4 node5

数据库负载均衡

  • 虽然搭建了集群,但是没有负载均衡,请求还是只会落在一个数据库上

image-20220818101727689

  • 使用Haproxy做负载均衡,请求会均匀分发给每个PXC节点,单节点负载低,性能好

image-20220818101841734

  • 负载均衡中间件对比

image-20220818102031723

安装Haproxy

docker pull haproxy
docker image ls

创建Haproxy配置文件

  • Haproxy配置文件需要自己写
touch /home/bill/haproxy/haproxy.cfg
  • 配置模板
global
    #工作目录
    chroot /usr/local/etc/haproxy
    #日志文件,使用rsyslog服务中local5日志设备(/var/log/local5),等级info
    log 127.0.0.1 local5 info
    #守护进程运行
    daemon

defaults
    log    global
    mode    http
    #日志格式
    option    httplog
    #日志中不记录负载均衡的心跳检测记录
    option    dontlognull
    #连接超时(毫秒)
    timeout connect 5000
    #客户端超时(毫秒)
    timeout client  50000
    #服务器超时(毫秒)
    timeout server  50000

#监控界面    
listen  admin_stats
    #监控界面的访问的IP和端口
    bind  0.0.0.0:8888
    #访问协议
    mode        http
    #URI相对地址
    stats uri   /dbs
    #统计报告格式
    stats realm     Global\ statistics
    #登陆帐户信息
    stats auth  admin:abc123456
#数据库负载均衡
listen  proxy-mysql
    #访问的IP和端口
    bind  0.0.0.0:3306  
    #网络协议
    mode  tcp
    #负载均衡算法(轮询算法)
    #轮询算法:roundrobin
    #权重算法:static-rr
    #最少连接算法:leastconn
    #请求源IP算法:source 
    balance  roundrobin
    #日志格式
    option  tcplog
    #在MySQL中创建一个没有权限的haproxy用户,密码为空。Haproxy使用这个账户对MySQL数据库心跳检测
    option  mysql-check user haproxy
    server  MySQL_1 172.18.0.2:3306 check weight 1 maxconn 2000  
    server  MySQL_2 172.18.0.3:3306 check weight 1 maxconn 2000  
    server  MySQL_3 172.18.0.4:3306 check weight 1 maxconn 2000 
    server  MySQL_4 172.18.0.5:3306 check weight 1 maxconn 2000
    server  MySQL_5 172.18.0.6:3306 check weight 1 maxconn 2000
    #使用keepalive检测死链
    option  tcpka  
  • 第50-55行为心跳检测,需要在每个MySQL节点上创建一个无任何权限、无密码的haproxy用户,用来进行心跳检测
# 在node1-node5上面执行
CREATE USER 'haproxy'@'%' IDENTIFIED BY ''; # 账号为haproxy,密码为空

创建Haproxy容器

  • 8888是haproxy状态网页的端口
  • 3306的haproxy的默认端口,由于已经被node1占用,故需要修改映射端口
  • 考虑到高可用,至少2个Haproxy容器
docker run -it -d \
-p 4001:8888 -p 4002:3306 \
-v /home/bill/haproxy:/usr/local/etc/haproxy \
--name h1 --privileged --net=net1 --ip=172.18.0.7 haproxy

启动之后发现闪退,查看log如下:

docker logs h1
[NOTICE]   (1) : New worker (9) forked
[NOTICE]   (1) : Loading success.
[NOTICE]   (9) : haproxy version is 2.6.2-16a3646
[NOTICE]   (9) : path to executable is /usr/local/sbin/haproxy
[ALERT]    (9) : [haproxy.main()] Cannot chroot(/usr/local/etc/haproxy).
[NOTICE]   (1) : haproxy version is 2.6.2-16a3646
[NOTICE]   (1) : path to executable is /usr/local/sbin/haproxy
[WARNING]  (1) : Current worker (9) exited with code 1 (Exit)
[ALERT]    (1) : exit-on-failure: killing every processes with SIGTERM
[WARNING]  (1) : All workers exited. Exiting... (1)

看到有Cannot chroot(/usr/local/etc/haproxy)推测权限问题,于是以root账户运行容器(加上-u 0参数):

docker run -it -d \
-u 0 \
-p 4001:8888 -p 4002:3306 \
-v /home/bill/haproxy:/usr/local/etc/haproxy \
--name h1 --privileged --net=net1 --ip=172.18.0.7 haproxy

启动成功

docker logs -f h1
[NOTICE]   (1) : New worker (9) forked
[NOTICE]   (1) : Loading success.

访问 http://10.248.192.137:4001/dbs ,输入账号密码(admin:abc123456),界面如下:

image-20220818153217683

再数据库连接工具中,输入4002端口连接:

image-20220818153435405

MySQL连接成功,Haproxy启动成功

例如在H1中创建test数据库:

create database test;

可以看到node1-node5节点均同步新建了test数据库:

image-20220818153914484

Haproxy双机热备

  • 单节点Haproxy不具备高可用,必须要有冗余设计

image-20220822130109008

虚拟IP

image-20220822130204797

Haproxy双机热备方案

利用Keepalived实现双机热备

image-20220822130730576

image-20220822130812964

安装Keepalived
  • Keepalived必须安装在Haproxy所在的容器内
apt-get update
apt-get install keepalived
Keepalived配置文件
  • Keepalived的配置文件路径是: /etc/keepalived/keepalived.conf

    • state: Keepalived的身份(MASTER主服务,BACKUP备用服务器)。主服务抢占虚拟IP,备用服务不会抢占IP
    • interface: 宿主机的网卡名
    • virtual_router_id: 虚拟路由ID,MASTER和BACKUP需要一致,值为0~255之间
    • priority:MASTER的权重要高于BACKUP,根据硬件配置调节,数字越大优先级越高
    • advert_int: 心跳检测时间间隔(秒)
    • authentication: 主从服务的鉴权账户,主备服务需配置相同
    • virtual_ipaddress: 虚拟IP地址。可以设置多个虚拟IP,每行一个
vrrp_instance  VI_1 {
    state  MASTER
    interface  eth0
    virtual_router_id  51
    priority  100
    advert_int  1
    authentication {
        auth_type  PASS
        auth_pass  123456
    }
    virtual_ipaddress {
        172.18.0.201
    }
}
  • haproxy容器内默认是没有vim编辑器的,需要手动安装vim编辑器
apt-get install vim
vi /etc/keepalived/keepalived.conf
启动Keepalived服务
service keepalived start
在宿主机中验证配置
ping 172.18.0.201
PING 172.18.0.201 (172.18.0.201) 56(84) bytes of data.
64 字节,来自 172.18.0.201: icmp_seq=1 ttl=64 时间=0.124 毫秒
64 字节,来自 172.18.0.201: icmp_seq=2 ttl=64 时间=0.085 毫秒
64 字节,来自 172.18.0.201: icmp_seq=3 ttl=64 时间=0.088 毫秒
64 字节,来自 172.18.0.201: icmp_seq=4 ttl=64 时间=0.087 毫秒
64 字节,来自 172.18.0.201: icmp_seq=5 ttl=64 时间=0.087 毫秒
^C
--- 172.18.0.201 ping 统计 ---
已发送 5 个包, 已接收 5 个包, 0% 包丢失, 耗时 4095 毫秒
rtt min/avg/max/mdev = 0.085/0.094/0.124/0.014 ms

配置MASTER节点成功。

MySQL的热备份

冷备份与热备份
  • 冷备份

    • 冷备份需要关闭数据库,在进行备份操作,通常做法是拷贝数据文件
    • 冷备份是最简单最安全的一种备份方式
    • 大型网站无法做到关闭业务备份数据,所以冷备份不是最佳选择
  • 热备份

    • 在系统运行的状态下去备份,也是难度最大的备份
    • MySQL常见的热备份有LVM和XtraBackup两种方案
    • 建议使用XtraBackup热备MySQL
XtraBackup

image-20220822152233517

  • 备份过程中不锁表,快速可靠
  • XtraBackup备份过程中不会打断正在执行的任务(例如增删改查)
  • XtraBackup能够基于压缩等功能节约磁盘空间和流量
全量备份和增量备份
  • 全量备份是备份全部数据,备份过程时间长,占用空间大

image-20220822152809269

  • 增量备份只备份变化的那部分数据。备份时间短,占用空间小

image-20220822153036099

增量备份操作步骤
这部分不要操作,只是一个踩坑的地方。往下看单独部署XtraBackup容器

先创建一个volume,用来存放备份的数据

docker volume create backup

把volume映射到node1上

docker stop node1

image-20220822153617877

node1节点成功关闭,下面需要把node1删掉,重新创建node1并挂载backup数据卷。由于node1的数据存储在v1卷,因此重新创建node1不影响节点的数据。

# 删除node1节点
docker container rm node1

# 创建node1
docker run -d -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=abc123456 \
-e CLUSTER_NAME=PXC \
-e XTRABACKUP_PASSWORD=abc123456 \
-e CLUSTER_JOIN=node2 \
-v v1:/var/lib/mysql \
-v backup:/data \
--privileged \
--name=node1 \
--net=net1 --ip=172.18.0.2 \
pxc
  • 增加了-v backup:/data,映射备份目录
  • 增加了-e CLUSTER_JOIN=node2,加入到集群内,join到node2-node5任意一个节点均可

image-20220822154249417

node1节点成功启动。下一步进入到PXC容器安装XtraBackup,并执行备份:

# 需要使用root身份操作
docker exec -it -u 0 node1 bash
# PXC5.7镜像自带innobackupex
# apt-get update
# apt-get install percona-xtrabackup-24
# 全量备份
innobackupex --user=root --password=abc123456 /data/backup/full
  • 这里有个问题,pxc8.0的容器里没有apt-get命令,通过离线安装包方式安装也比较麻烦,不利于自动化构建。通过查阅资料,发现一种更好的XtraBackup部署方法:https://docs.percona.com/percona-xtrabackup/8.0/installation/docker.html
  • 根据官网教程,如果是PXC8.0,可以单独部署一个XtraBackup容器,在启动XtraBackup容器的时候,指定需要备份的MySQL节点,挂载需要备份的MySQL的volume,相比于上面的进到PXC容器去手动安装XtraBackup,要更方便、快捷
  • PXC5.7镜像自带innobackupex,不用apt安装,而且PXC5.7容器内没有apt-get
PXC全量恢复
  • 数据库可以热备份,但是不能热还原。只能新建空白的MySQL节点,再进行数据恢复,再建立PXC集群
  • 还原数据前要将未提交的事务回滚,还原数据之后重启MySQL

查看数据在物理机的位置

ls /var/snap/docker/common/var-lib-docker/volumes/backup/_data/backup/full/
2022-08-23_04-34-13

恢复数据操作

# 删除MySQL集群及数据卷
docker container stop node1 node2 node3 node4 node5
docker container rm node1 node2 node3 node4 node5
docker volume rm v1 v2 v3 v4 v5
# 重新创建node1
docker volume create v1
docker run -d -p 3306:3306 \
-e MYSQL_ROOT_PASSWORD=abc123456 \
-e CLUSTER_NAME=PXC \
-e XTRABACKUP_PASSWORD=abc123456 \
-v v1:/var/lib/mysql \
-v backup:/data \
--privileged \
--name=node1 \
--net=net1 --ip=172.18.0.2 \
pxc
# 进入到node1节点内
docker exec -it -u 0 node1 bash

# =====================================
# 清空MySQL数据
rm -rf /var/lib/mysql/*
# 未提交的事务回滚
innobackupex --user=root --password=abc123456 --apply-back /data/backup/full/2022-08-23_04-34-13
# 执行冷还原
innobackupex --user=root --password=abc123456 --copy-back /data/backup/full/2022-08-23_04-34-13
# 需要把MySQL数据权限改成mysql:mysql(默认为root:root,否则容器会重启失败)
chown -R mysql:mysql /var/lib/mysql
# 退出容器
exit
# =====================================

# 重启容器
docker container restart node1

image-20220823131146119

MySQL_1节点启动成功,并且数据恢复成功(haproxy的心跳监测靠的是haproxy账号不断地去尝试登录MySQL)

PXC集群搭建-生产环境所遇问题

1. 不能映射目录,只能挂volume

path in container:

  • /var/lib/mysql
  • /var/log/mysql
  • /backup

2. 第一个创建的节点重启会启动失败

参考CSDN:https://blog.csdn.net/qq_26896085/article/details/104547257

我的解决方案是删掉容器(不要动创建好的volume),重新创建容器并添加启动参数-e CLUSTER_JOIN=pxc02,也就是加入到一个可用节点里

3. 关于MySQL账户的恢复

MySQL账户不能单纯的通过导入mysql数据库内的user和db表解决,单纯的导入这两个表的数据,MySQL节点之间会不同步。

如果可以通过create user创建最好,可以自动同步。https://www.jb51.net/article/194392.htm

mysqlpump -uroot -proot --exclude-databases=% --users --exclude-users=mysql.session,mysql.sys,root > /backup/user.sql

RedisCluster集群

  • 高速缓存利用内存保护数据,读写速度远超硬盘
  • 高速缓存可以减少I/O操作,降低I/O压力
  • Redis是VMware开发的开源免费KV型NoSQL缓存产品
  • Redis具有良好性能,最多可以提供10万次/秒的读写
  • 目前新浪微博团队组建了世界上最大的Redis集群(2018)

Redis集群介绍

  1. RedisCluster: 官方推荐,没有中心节点(PXC也无中心节点)
  2. Codis: 中间件产品,存在中心节点(360公司推出)
  3. Twemproxy:中间件产品,存在中心节点

使用RedisCluster

  • 无中心节点,客户端与redis节点直连,不需要中间代理层
  • 数据可以被分片存储(每个节点存储的数据不同)。每个节点有加冗余节点,节点故障可切换到冗余节点,保障集群正常运转
  • 管理方便,后续可自行增加或删除节点

image-20220823145012635

  • 本实验搭建的是redis-6节点(一主一从结构)
编号IP对外开放端口redis节点名
1172.19.0.25001r1
2172.19.0.35002r2
3172.19.0.45003r3
4172.19.0.55004r4
5172.19.0.65005r5
6172.19.0.75006r6
  • 其中salve-master结构是通过下面的redis-trib.rb脚本自动配置所得

Redis主从同步

  • Redis集群中的数据库复制是通过主从同步来实现的
  • 主节点(Master)把数据发送给从节点(Slave)
  • 主从同步的好处在于高可用,Redis节点有冗余设计

image-20220823145303691

Redis集群高可用

  • Redis集群中应该包含奇数个Master,至少应该有3个Master
  • Redis集群中每个Master都应该有Slave

image-20220823145605899

  • RedisCluster无需配置负载均衡,因为renrenfast后端已经实现了redis负载均衡

拉取redis image

包括拉取镜像、创建net2网络

# yyyyttttwwww的redis已经把配置文件修改完毕
docker pull yyyyttttwwww/redis
# 重命名
docker tag yyyyttttwwww/redis redis
docker network create --subnet=172.19.0.0/16 net2
docker run -it -d --name r1 -p 5001:6379 --net=net2 --ip=172.19.0.2 redis bash

配置Redis节点

  • 配置文件路径:/usr/redis/redis.conf
  • 重点参数详情

    • daemonize yes # 以后台进程运行
    • cluster-enabled yes # 开启集群
    • cluster-config-file nodes.conf # 集群配置文件
    • cluster-node-timeout 15000 # 超时时间
    • appendonly yes # 开启AOF模式,即日志功能,redis宕机可以根据AOF的日志恢复数据
vi /usr/redis/redis.conf
# 搜索 不要进入到insert模式,直接输入/命令
/daemonize
/cluster-enabled
/cluster-config-file
/cluster-node-timeout
/appendonly
# 保存
:wq
# 运行redis
cd /usr/redis/src
./redis-server ../redis.conf

首个节点搭建成功。接下来创建第2-6个redis节点并分别启动redis服务(容器跑起来并未自动启动redis服务):

docker run -it -d --name r2 -p 5002:6379 --net=net2 --ip=172.19.0.3 redis bash
docker run -it -d --name r3 -p 5003:6379 --net=net2 --ip=172.19.0.4 redis bash
docker run -it -d --name r4 -p 5004:6379 --net=net2 --ip=172.19.0.5 redis bash
docker run -it -d --name r5 -p 5005:6379 --net=net2 --ip=172.19.0.6 redis bash
docker run -it -d --name r6 -p 5006:6379 --net=net2 --ip=172.19.0.7 redis bash
docker exec -it r2 /usr/redis/src/redis-server /usr/redis/redis.conf
docker exec -it r3 /usr/redis/src/redis-server /usr/redis/redis.conf
docker exec -it r4 /usr/redis/src/redis-server /usr/redis/redis.conf
docker exec -it r5 /usr/redis/src/redis-server /usr/redis/redis.conf
docker exec -it r6 /usr/redis/src/redis-server /usr/redis/redis.conf

安装redis-trib.rb

  • redis-tribe是基于Ruby的Redis集群命令行工具
  • 使用的是yyyyttttwwww/redis,Ruby脚本和Ruby环境都已安装
# 在容器中(进入到6个redis容器中的任意一个,进行如下操作即可组网)
cd /usr/redis
mkdir cluster
cp /usr/redis/src/redis-trib.rb /usr/redis/cluster/
cd /usr/redis/cluster
apt-get install ruby
apt-get install rubygems
gem install redis

创建Redis集群

  • --replicas 1 表示每个主节点创建一个从节点
docker exec -it r1 bash
# 进到容器中
./redis-trib.rb create --replicas 1 172.19.0.2:6379 172.19.0.3:6379 172.19.0.4:6379 172.19.0.5:6379 172.19.0.6:6379 172.19.0.7:6379 
>>> Creating cluster
>>> Performing hash slots allocation on 6 nodes...
Using 3 masters:
172.19.0.2:6379
172.19.0.3:6379
172.19.0.4:6379
Adding replica 172.19.0.5:6379 to 172.19.0.2:6379
Adding replica 172.19.0.6:6379 to 172.19.0.3:6379
Adding replica 172.19.0.7:6379 to 172.19.0.4:6379
M: 74734d141f051f70a1b59c883dd1a7368e803ab9 172.19.0.2:6379
   slots:0-5460 (5461 slots) master
M: 1b49e26dc5277e19bbc987329bad7f1fb4a36bb1 172.19.0.3:6379
   slots:5461-10922 (5462 slots) master
M: 353faec9b383c10928ca476f361163b7165e9565 172.19.0.4:6379
   slots:10923-16383 (5461 slots) master
S: 19c4869c9f70a8f64808e399ce6e3b84b834d03e 172.19.0.5:6379
   replicates 74734d141f051f70a1b59c883dd1a7368e803ab9
S: aa6fdd39064848a56fff6d81268d0593fa11a588 172.19.0.6:6379
   replicates 1b49e26dc5277e19bbc987329bad7f1fb4a36bb1
S: 7218cd5956cb6bd5d3f7f42228a4ec1a5d3ec4a4 172.19.0.7:6379
   replicates 353faec9b383c10928ca476f361163b7165e9565
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 172.19.0.2:6379)
M: 74734d141f051f70a1b59c883dd1a7368e803ab9 172.19.0.2:6379
   slots:0-5460 (5461 slots) master
M: 1b49e26dc5277e19bbc987329bad7f1fb4a36bb1 172.19.0.3:6379
   slots:5461-10922 (5462 slots) master
M: 353faec9b383c10928ca476f361163b7165e9565 172.19.0.4:6379
   slots:10923-16383 (5461 slots) master
M: 19c4869c9f70a8f64808e399ce6e3b84b834d03e 172.19.0.5:6379
   slots: (0 slots) master
   replicates 74734d141f051f70a1b59c883dd1a7368e803ab9
M: aa6fdd39064848a56fff6d81268d0593fa11a588 172.19.0.6:6379
   slots: (0 slots) master
   replicates 1b49e26dc5277e19bbc987329bad7f1fb4a36bb1
M: 7218cd5956cb6bd5d3f7f42228a4ec1a5d3ec4a4 172.19.0.7:6379
   slots: (0 slots) master
   replicates 353faec9b383c10928ca476f361163b7165e9565
[OK] All nodes agree about slots configuration.
>>> Check for open slots...
>>> Check slots coverage...
[OK] All 16384 slots covered

创建成功。访问任意一个节点即可测试。

docker exec -it r1 bash
/usr/redis/src/redis-cli -c
127.0.0.1:6379>set a 10
-> Redirected to slot [15495] located at 172.19.0.4:6379 # 
OK
172.19.0.4:6379> get a
"10"
  • /usr/redis/src/redis-cli -c 中的 -c 表示连接到redis cluster
  • set a 10时,经过集群计算数据存储到172.19.0.4节点上

尝试把172.19.0.4(master)节点挂掉,并查看cluster节点状态:

docker container pause r3
docker exec -it r1 bash
root@a62d4263df70:/# /usr/redis/src/redis-cli -c
127.0.0.1:6379> cluster nodes
353faec9b383c10928ca476f361163b7165e9565 172.19.0.4:6379 master,fail - 1661308551183 1661308547172 3 connected
1b49e26dc5277e19bbc987329bad7f1fb4a36bb1 172.19.0.3:6379 master - 0 1661308571248 2 connected 5461-10922
7218cd5956cb6bd5d3f7f42228a4ec1a5d3ec4a4 172.19.0.7:6379 master - 0 1661308572250 7 connected 10923-16383
aa6fdd39064848a56fff6d81268d0593fa11a588 172.19.0.6:6379 slave 1b49e26dc5277e19bbc987329bad7f1fb4a36bb1 0 1661308574256 5 connected
74734d141f051f70a1b59c883dd1a7368e803ab9 172.19.0.2:6379 myself,master - 0 0 1 connected 0-5460
19c4869c9f70a8f64808e399ce6e3b84b834d03e 172.19.0.5:6379 slave 74734d141f051f70a1b59c883dd1a7368e803ab9 0 1661308573254 4 connected
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.19.0.7:6379
"10"

并且此时get a,依然可以使用备用节点获取到数据。

恢复r3节点,再去get a,依然可以取到数据,只不过主备节点身份互换。

docker container unpause r3
# 再次进入到r1
docker exec -it r1 bash
/usr/redis/src/redis-cli -c
127.0.0.1:6379> get a
-> Redirected to slot [15495] located at 172.19.0.7:6379
"10"
172.19.0.7:6379> cluster nodes
aa6fdd39064848a56fff6d81268d0593fa11a588 172.19.0.6:6379 slave 1b49e26dc5277e19bbc987329bad7f1fb4a36bb1 0 1661308887352 5 connected
1b49e26dc5277e19bbc987329bad7f1fb4a36bb1 172.19.0.3:6379 master - 0 1661308884344 2 connected 5461-10922
353faec9b383c10928ca476f361163b7165e9565 172.19.0.4:6379 slave 7218cd5956cb6bd5d3f7f42228a4ec1a5d3ec4a4 0 1661308889360 7 connected
7218cd5956cb6bd5d3f7f42228a4ec1a5d3ec4a4 172.19.0.7:6379 myself,master - 0 0 7 connected 10923-16383
19c4869c9f70a8f64808e399ce6e3b84b834d03e 172.19.0.5:6379 slave 74734d141f051f70a1b59c883dd1a7368e803ab9 0 1661308888356 4 connected
74734d141f051f70a1b59c883dd1a7368e803ab9 172.19.0.2:6379 master - 0 1661308886350 1 connected 0-5460
172.19.0.7:6379>

172.19.0.7变为master,172.19.0.4变为salve。

参考资料

  1. PXC8.0集群搭建遇见的坑
  2. Docker启动、进入容器,查看容器log
  3. Docker命令_各种参数简介(run、v、rm、-w、-u、-e)
  4. percona-xtrabackup官方文档 - Docker部署方法
  5. mysql 启动失败 详情,MySQL 启动失败的常见原因


Docker Dcoker Swarm MySQL PXC redis
Theme Jasmine by Kent Liao And Bill

本站由提供云存储服务