一文精通Redis主从、哨兵模式部署

目录

三、Redis主从

3.1 节点规划

3.2 配置免密登录

3.3 主从实例安装

3.3.1 前置环境

3.3.2 下载安装包

3.3.3 安装并启动

① 创建运行目录

② 创建守护进程服务

③ 创建停止脚本

④ 启动

3.3.4 配置man手册

3.3.5 配置日志切割

3.4 主从配置

3.5 主从验证

3.6 主从原理

3.6.1 相关概念

3.6.1 全量同步原理

3.6.2 增量同步原理

3.6.3 总结

3.7 主从优化

四、Redis哨兵

4.1 哨兵的作用与原理

4.2 节点规划

4.3 配置免密登录

4.4 Sentinel实例安装

4.4.1 前置环境

4.4.2 下载安装包

4.4.3 安装并启动

① 创建运行目录

② 创建守护进程服务

③ 创建停止脚本

④ 启动

4.4.4 配置man手册

4.4.5 配置日志切割

4.5 配置哨兵

4.6 哨兵测试


三、Redis主从

3.1 节点规划

操作系统IP地址端口号主机名称软件包
Almalinux192.168.44.2096379redis1redis
Almalinux192.168.44.2106379redis2redis
Almalinux192.168.44.2116379redis3redis

3.2 配置免密登录

#209
cd ~
cat >host_list.txt <<'EOF'
192.168.44.209 1
192.168.44.210 1
192.168.44.211 1
EOF
ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa -y
yum install -y sshpass
cd ~
for i in $(seq $(cat host_list.txt |wc -l));\
do \
host_ip="$(cat host_list.txt |awk "NR==${i}"'{print $1}')";\
host_password="$(cat host_list.txt |awk "NR==${i}"'{print $2}')";\
echo "start config host:${host_ip}";\
sshpass -p"${host_password}" ssh-copy-id "-o StrictHostKeyChecking=no" -i /root/.ssh/id_rsa.pub root@"${host_ip}";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${host_ip}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done
#验证209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "ip a";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#修改主机名称所有节点
#批量209
cd ~
num=1
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "hostnamectl set-hostname redis${num}";\
ssh root@"${i}" "hostname";\
num=$((num+1));\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#安装相关小软件所有节点
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install rsync logrotate -y";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#修改host文件所有节点
#单机编辑209
vim /etc/hosts
192.168.44.209   redis1
192.168.44.210   redis2
192.168.44.211   redis3
192.168.44.200   vip
#分发209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /etc/hosts root@"${i}":/etc/hosts;\
ssh root@"${i}" "cat /etc/hosts";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#关闭防火墙和selinux 所有节点
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "systemctl stop firewalld";\
ssh root@"${i}" "systemctl disable firewalld";\
ssh root@"${i}" "sed -ri 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux";\
ssh root@"${i}" "grep -F 'SELINUX=' /etc/sysconfig/selinux";\
ssh root@"${i}" "setenforce 0";\
ssh root@"${i}" "getenforce";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

3.3 主从实例安装

官网:Install Redis from Source | Docs

3.3.1 前置环境

=====================================

仅209单机操作即可

=====================================

#安装docker运行时209
#准备主机清单,这一步会破坏后续批量部署主机清单
#操作完后别忘了参考3.2节密码登录配置,把它还原回来
#~~~~~~~~~集群是三台机器~~~~~~~~~~~~~~~~~
cd ~
cat <<'EOF' | sudo tee ./host_list.txt
192.168.44.209 1
EOF
ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa -y

#配置免密登录209
yum install -y sshpass
cd ~
for i in $(seq $(cat host_list.txt |wc -l));\
do \
host_ip="$(cat host_list.txt |awk "NR==${i}"'{print $1}')";\
host_password="$(cat host_list.txt |awk "NR==${i}"'{print $2}')";\
echo "start config host:${host_ip}";\
sshpass -p"${host_password}" ssh-copy-id "-o StrictHostKeyChecking=no" -i /root/.ssh/id_rsa.pub root@"${host_ip}";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${host_ip}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#验证209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "ip a";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#安装小软件
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install rsync -y";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#官方网站:https://docs.docker.com/engine/install/centos/
#清理环境
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
#官方源(备用)
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "curl  https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo";\
ssh root@"${i}" "ls -l /etc/yum.repos.d";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done
=====================================================================
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
=====================================================================
#安装指定版本docker这里是20.10.14版本
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install -y yum-utils";\
ssh root@"${i}" "yum list docker-ce --showduplicates | sort -r";\
ssh root@"${i}" "yum list docker-ce-cli --showduplicates | sort -r";\
ssh root@"${i}" "yum list containerd.io --showduplicates | sort -r";\
ssh root@"${i}" "yum install docker-ce-20.10.14 docker-ce-cli-20.10.14 containerd.io -y";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done
#阿里源(推荐)
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "curl  http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo";\
ssh root@"${i}" "ls -l /etc/yum.repos.d";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done
==================================================================
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
==================================================================

#等等安装GPG签名报错?
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "rpm --import https://mirrors.aliyun.com/almalinux/RPM-GPG-KEY-AlmaLinux";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#创建文件夹所有节点
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install tree -y";\
ssh root@"${i}" "mkdir /etc/docker -p";\
ssh root@"${i}" "mkdir /data/docker -p";\
ssh root@"${i}" "tree /data";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#修改docker配置文件,bip172.xx.xx.1的xx.xx替换为主机ip的后两位
#单机编辑209
#参考弃用文档:https://docs.docker.com/engine/deprecated/#duplicate-keys-with-conflicting-values-in-engine-labels
#参考daemon.json配置文档:https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file
#旧版配置,graph在版本v17.05中已弃用;在版本中v23.0彻底移除;用data-root替代
vim /etc/docker/daemon.json
{
  "graph": "/data/docker",
  "storage-driver": "overlay2",
  "insecure-registries": ["registry.access.redhat.com","quay.io","192.168.44.201:8088"],
  "registry-mirrors": [
    "https://uoggbpok.mirror.aliyuncs.com",
    "http://hub-mirror.c.163.com",
    "https://mirror.baidubce.com",
    "https://docker.mirrors.sjtug.sjtu.edu.cn",
    "https://docker.nju.edu.cn"
  ],
  "bip": "172.16.0.1/16",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": {"max-size":"100m", "max-file":"3"}
}
#新版配置,如果发现无法启动docker守护进程,请使用这个配置
vim /etc/docker/daemon.json
{
  "data-root": "/data/docker",
  "storage-driver": "overlay2",
  "insecure-registries": ["registry.access.redhat.com","quay.io","192.168.44.201:8088"],
  "registry-mirrors": [
    "https://uoggbpok.mirror.aliyuncs.com",
    "http://hub-mirror.c.163.com",
    "https://mirror.baidubce.com",
    "https://docker.mirrors.sjtug.sjtu.edu.cn",
    "https://docker.nju.edu.cn"
  ],
  "bip": "172.16.0.1/16",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": {"max-size":"100m", "max-file":"3"}
}
#分发209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /etc/docker/daemon.json root@"${i}":/etc/docker/;\
ssh root@"${i}" "cat /etc/docker/daemon.json";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#所有节点
#启动docker,验证版本信息
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "systemctl daemon-reload";\
ssh root@"${i}" "systemctl enable docker";\
ssh root@"${i}" "systemctl start docker";\
ssh root@"${i}" "docker version";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#安装完成
[root@docker ~]# docker info 

#Docker仓库凉凉了??
#单机配置代理209
#https://docs.docker.com/engine/daemon/proxy/#systemd-unit-file
[root@docker ~]# mkdir -p /etc/systemd/system/docker.service.d
[root@docker ~]# vim /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://192.168.1.131:8080"
Environment="HTTPS_PROXY=http://192.168.1.131:8080"
Environment="NO_PROXY=localhost,127.0.0.1,docker-registry.example.com,192.168.44.201,registry.myhabor.com"

#分发209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "mkdir -p /etc/systemd/system/docker.service.d";\
rsync -avzP /etc/systemd/system/docker.service.d/http-proxy.conf root@"${i}":/etc/systemd/system/docker.service.d/;\
ssh root@"${i}" "cat /etc/systemd/system/docker.service.d/http-proxy.conf";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#单机还原镜像加速配置209
[root@docker ~]# vim /etc/docker/daemon.json
{
  "data-root": "/data/docker",
  "storage-driver": "overlay2",
  "insecure-registries": ["registry.access.redhat.com","quay.io","192.168.44.201:8088"],
  "bip": "172.16.0.1/16",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": {"max-size":"100m", "max-file":"3"}
}

#分发
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /etc/docker/daemon.json root@"${i}":/etc/docker/;\
ssh root@"${i}" "cat /etc/docker/daemon.json";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#重启docker
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "systemctl daemon-reload";\
ssh root@"${i}" "systemctl restart docker";\
ssh root@"${i}" "docker version";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#运行java8临时容器209
[root@docker ~]# docker container run -it --rm openjdk:8 /bin/bash
root@3568980b5c9b:/# env
HOSTNAME=3568980b5c9b
JAVA_HOME=/usr/local/openjdk-8
PWD=/
HOME=/root
LANG=C.UTF-8
TERM=xterm
SHLVL=1
PATH=/usr/local/openjdk-8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
JAVA_VERSION=8u342
_=/usr/bin/env

3.3.2 下载安装包

官网:Downloads - Redis

发行版源码包:Index of /releases/

#官方推荐源码编译安装,我们投机取巧一下。
#直接下载docker与rpm组装版本209
=>  root @ 󰌽 linux-learn: 󰉋 ~------------------------------------------------------------------------------------------
➜ cd /tmp

=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ yum download --destdir=/tmp redis

#把rpm转化为tar。tgz模式209
=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ rpm2archive redis-5.0.3-5.module_el8.4.0+2583+b9845322.x86_64.rpm

=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ ll
总用量 2.3M
-rw-r--r-- 1 root root 926K 9月   2 20:28 redis-5.0.3-5.module_el8.4.0+2583+b9845322.x86_64.rpm
-rw-r--r-- 1 root root 1.4M 9月   2 20:37 redis-5.0.3-5.module_el8.4.0+2583+b9845322.x86_64.rpm.tgz
drwx------ 3 root root   17 9月   2 20:11 systemd-private-c531182ee6b945ddb1c53618f8c26222-chronyd.service-DKdUBk

#把它解压缩到特定的目录备用209
=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ mkdir -p /tmp/redis-dir

=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ tar xf redis-5.0.3-5.module_el8.4.0+2583+b9845322.x86_64.rpm.tgz -C /tmp/redis-dir

=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ tree /tmp/redis-dir
/tmp/redis-dir
├── etc
│   ├── logrotate.d
│   │   └── redis
│   ├── redis.conf
│   ├── redis-sentinel.conf
│   └── systemd
│       └── system
│           ├── redis-sentinel.service.d
│           │   └── limit.conf
│           └── redis.service.d
│               └── limit.conf
├── usr
│   ├── bin
│   │   ├── redis-benchmark
│   │   ├── redis-check-aof -> redis-server
│   │   ├── redis-check-rdb -> redis-server
│   │   ├── redis-cli
│   │   ├── redis-sentinel -> redis-server
│   │   └── redis-server
│   ├── lib
│   │   └── systemd
│   │       └── system
│   │           ├── redis-sentinel.service
│   │           └── redis.service
│   ├── lib64
│   │   └── redis
│   │       └── modules
│   ├── libexec
│   │   └── redis-shutdown
│   └── share
│       ├── licenses
│       │   └── redis
│       │       ├── COPYING
│       │       ├── COPYING-hiredis
│       │       ├── COPYING-jemalloc
│       │       └── COPYRIGHT-lua
│       └── man
│           ├── man1
│           │   ├── redis-benchmark.1.gz
│           │   ├── redis-check-aof.1.gz
│           │   ├── redis-check-rdb.1.gz
│           │   ├── redis-cli.1.gz
│           │   ├── redis-sentinel.1.gz -> redis-server.1.gz
│           │   └── redis-server.1.gz
│           └── man5
│               ├── redis.conf.5.gz
│               └── redis-sentinel.conf.5.gz -> redis.conf.5.gz
└── var
    ├── lib
    │   └── redis
    └── log
        └── redis

26 directories, 26 files

#运行almalinux:8临时容器209
#注意你的宿主机什么操作系统就运行什么
#我的是almalinux:8
root in 🌐 linux-learn in ~
➜ docker container run --name=redis \
--rm \
-it \
almalinux:8 /bin/bash

#把临时容器放入后台运行209
root in 🌐 linux-learn in ~
➜ Ctrl + p + q

#进入容器209
root in 🌐 linux-learn in ~ took 1m55s
➜ docker container exec -it redis /bin/bash

#下载源码并编译
[root@a438ba4941d9 /]# cd /tmp/
[root@a438ba4941d9 tmp]#
[root@a438ba4941d9 tmp]# curl -L https://download.redis.io/releases/redis-6.2.6.tar.gz -o redis-6.2.6.tar.gz
[root@a438ba4941d9 tmp]# tar xf redis-6.2.6.tar.gz
[root@a438ba4941d9 tmp]# cd redis-6.2.6
[root@a438ba4941d9 redis-6.2.6]# yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm
[root@a438ba4941d9 redis-6.2.6]# yum install make gcc glibc glibc-devel openssl openssl-devel systemd-devel -y
[root@a438ba4941d9 redis-6.2.6]# make BUILD_TLS=yes USE_SYSTEMD=yes
[root@a438ba4941d9 redis-6.2.6]# make install
[root@a438ba4941d9 redis-6.2.6]# ls -l
total 244
-rw-rw-r--  1 root root 33624 Oct  4  2021 00-RELEASENOTES
-rw-rw-r--  1 root root    51 Oct  4  2021 BUGS
-rw-rw-r--  1 root root  5026 Oct  4  2021 CONDUCT
-rw-rw-r--  1 root root  3384 Oct  4  2021 CONTRIBUTING
-rw-rw-r--  1 root root  1487 Oct  4  2021 COPYING
-rw-rw-r--  1 root root    11 Oct  4  2021 INSTALL
-rw-rw-r--  1 root root  6888 Oct  4  2021 MANIFESTO
-rw-rw-r--  1 root root   151 Oct  4  2021 Makefile
-rw-rw-r--  1 root root 21567 Oct  4  2021 README.md
-rw-rw-r--  1 root root  3055 Oct  4  2021 TLS.md
drwxrwxr-x  7 root root   213 Sep  2 14:23 deps
-rw-rw-r--  1 root root 93724 Oct  4  2021 redis.conf
-rwxrwxr-x  1 root root   275 Oct  4  2021 runtest
-rwxrwxr-x  1 root root   279 Oct  4  2021 runtest-cluster
-rwxrwxr-x  1 root root  1079 Oct  4  2021 runtest-moduleapi
-rwxrwxr-x  1 root root   281 Oct  4  2021 runtest-sentinel
-rw-rw-r--  1 root root 13768 Oct  4  2021 sentinel.conf
drwxrwxr-x  3 root root 12288 Sep  2 14:29 src
drwxrwxr-x 11 root root   182 Oct  4  2021 tests
drwxrwxr-x  9 root root  4096 Oct  4  2021 utils
[root@a438ba4941d9 redis-6.2.6]# ls -l /usr/local/bin/
total 25048
-rwxr-xr-x 1 root root  6592864 Sep  2 14:29 redis-benchmark
lrwxrwxrwx 1 root root       12 Sep  2 14:29 redis-check-aof -> redis-server
lrwxrwxrwx 1 root root       12 Sep  2 14:29 redis-check-rdb -> redis-server
-rwxr-xr-x 1 root root  6804832 Sep  2 14:29 redis-cli
lrwxrwxrwx 1 root root       12 Sep  2 14:29 redis-sentinel -> redis-server
-rwxr-xr-x 1 root root 12245112 Sep  2 14:29 redis-server

#新开启一个终端,把容器里边的redis复制出来209
#创建我们redis的目录结构
root in 🌐 linux-learn in ~ took 4m36s
➜ mkdir /opt/redis-6.2.6/{bin,share,conf} -p

root in 🌐 linux-learn in ~
➜ mkdir /opt/redis-6.2.6/share/man/{man1,man5} -p

root in 🌐 linux-learn in ~ took 4s
➜ tree /opt/redis-6.2.6/
/opt/redis-6.2.6/
├── bin
├── conf
└── share
    └── man
        ├── man1
        └── man5

6 directories, 0 files

#复制容器里边的redis到安装目录209
root in 🌐 linux-learn in ~
➜ docker container cp redis:/usr/local/bin /tmp/redis-bin

root in 🌐 linux-learn in ~
➜ docker container cp redis:/tmp/redis-6.2.6/redis.conf /opt/redis-6.2.6/conf/

root in 🌐 linux-learn in ~
➜ docker container cp redis:/tmp/redis-6.2.6/sentinel.conf /opt/redis-6.2.6/conf/

root in 🌐 linux-learn in ~
➜ cp -r /tmp/redis-bin/* /opt/redis-6.2.6/bin/

root in 🌐 linux-learn in ~
➜ tree /opt/redis-6.2.6/
/opt/redis-6.2.6/
├── bin
│   ├── redis-benchmark
│   ├── redis-check-aof -> redis-server
│   ├── redis-check-rdb -> redis-server
│   ├── redis-cli
│   ├── redis-sentinel -> redis-server
│   └── redis-server
├── conf
│   ├── redis.conf
│   └── sentinel.conf
└── share
    └── man
        ├── man1
        └── man5

6 directories, 8 files

#分发Redis存档
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install -y tree";\
rsync -avzP /opt/redis-6.2.6 root@"${i}":/opt/;\
ssh root@"${i}" "tree /opt -L 1";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#配置环境变量209
root in 🌐 linux-learn in ~
➜ ln -s /opt/redis-6.2.6 /opt/redis

root in 🌐 linux-learn in ~
➜ tree /opt/ -L 1
/opt/
├── containerd
├── redis -> /opt/redis-6.2.6
├── redis-6.2.6
└── tool

4 directories, 0 files

root in 🌐 linux-learn in ~
➜ vim ~/.bashrc
# redis
export PATH="/opt/redis/bin:$PATH"

#验证209
root in 🌐 linux-learn in ~
➜ redis-server --help
Usage: ./redis-server [/path/to/redis.conf] [options] [-]
       ./redis-server - (read config from stdin)
       ./redis-server -v or --version
       ./redis-server -h or --help
       ./redis-server --test-memory <megabytes>

Examples:
       ./redis-server (run the server with default conf)
       ./redis-server /etc/redis/6379.conf
       ./redis-server --port 7777
       ./redis-server --port 7777 --replicaof 127.0.0.1 8888
       ./redis-server /etc/myredis.conf --loglevel verbose -
       ./redis-server /etc/myredis.conf --loglevel verbose

Sentinel mode:
       ./redis-server /etc/sentinel.conf --sentinel

root in 🌐 linux-learn in ~
➜ redis-server -v
Redis server v=6.2.6 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=679f60a40763578

#分发环境变量配置
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "ln -s /opt/redis-6.2.6 /opt/redis";\
ssh root@"${i}" "tree /opt -L 1";\
rsync -avzP ~/.bashrc root@"${i}":~/.bashrc;\
ssh root@"${i}" "tail ~/.bashrc";\
ssh root@"${i}" "/opt/redis/bin/redis-server -v";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

3.3.3 安装并启动

① 创建运行目录
#创建redis系统用户209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "useradd -r -M -s /sbin/nologin redis";\
ssh root@"${i}" "id redis";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#创建redis运行相关目录209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "mkdir /data/redis/redis-6379/{data,conf} -p";\
ssh root@"${i}" "tree /data/redis";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#更改所有权209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "chown -R redis:redis /data/redis";\
ssh root@"${i}" "ls -l /data/redis";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

② 创建守护进程服务
#创建redis守护进程服务文件209
#模板文件
========================================================================================================
root in 🌐 linux-learn in ~
➜ cat /tmp/redis-dir/usr/lib/systemd/system/redis.service
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/usr/bin/redis-server /etc/redis.conf --supervised systemd
ExecStop=/usr/libexec/redis-shutdown
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
========================================================================================================
#创建我们需要的
cat >/etc/systemd/system/redis-6379.service <<'EOF'
[Unit]
Description=Redis persistent key-value database
After=network.target

[Service]
ExecStart=/opt/redis/bin/redis-server /data/redis/redis-6379/conf/redis-6379.conf --supervised systemd
ExecStop=/opt/redis/bin/redis-shutdown redis-6379
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF

#创建redis守护进程服务文件限制209
#模板
========================================================================================================
root in 🌐 linux-learn in ~
➜ cat /tmp/redis-dir/etc/systemd/system/redis.service.d/limit.conf
# If you need to change max open file limit
# for example, when you change maxclient in configuration
# you can change the LimitNOFILE value below
# see "man systemd.exec" for information

[Service]
LimitNOFILE=10240
========================================================================================================
#创建我们需要的
mkdir -p /etc/systemd/system/redis-6379.service.d
cat >/etc/systemd/system/redis-6379.service.d/limit.conf <<'EOF'
# If you need to change max open file limit
# for example, when you change maxclient in configuration
# you can change the LimitNOFILE value below
# see "man systemd.exec" for information

[Service]
LimitNOFILE=10240
EOF

#分发守护进程服务
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /etc/systemd/system/redis-6379.service root@"${i}":/etc/systemd/system/;\
ssh root@"${i}" "mkdir -p /etc/systemd/system/redis-6379.service.d";\
rsync -avzP /etc/systemd/system/redis-6379.service.d/limit.conf root@"${i}":/etc/systemd/system/redis-6379.service.d/;\
ssh root@"${i}" "cat /etc/systemd/system/redis-6379.service";\
ssh root@"${i}" "echo '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'";\
ssh root@"${i}" "echo";\
ssh root@"${i}" "echo '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'";\
ssh root@"${i}" "cat /etc/systemd/system/redis-6379.service.d/limit.conf";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

③ 创建停止脚本
#创建redis停止脚本209
#模板
========================================================================================================
root in 🌐 linux-learn in ~
➜ cat /tmp/redis-dir/usr/libexec/redis-shutdown
#!/bin/bash
#
# Wrapper to close properly redis and sentinel
test x"$REDIS_DEBUG" != x && set -x

REDIS_CLI=/usr/bin/redis-cli

# Retrieve service name
SERVICE_NAME="$1"
if [ -z "$SERVICE_NAME" ]; then
   SERVICE_NAME=redis
fi

# Get the proper config file based on service name
CONFIG_FILE="/etc/$SERVICE_NAME.conf"

# Use awk to retrieve host, port from config file
HOST=`awk '/^[[:blank:]]*bind/ { print $2 }' $CONFIG_FILE | tail -n1`
PORT=`awk '/^[[:blank:]]*port/ { print $2 }' $CONFIG_FILE | tail -n1`
PASS=`awk '/^[[:blank:]]*requirepass/ { print $2 }' $CONFIG_FILE | tail -n1`
SOCK=`awk '/^[[:blank:]]*unixsocket\s/ { print $2 }' $CONFIG_FILE | tail -n1`

# Just in case, use default host, port
HOST=${HOST:-127.0.0.1}
if [ "$SERVICE_NAME" = redis ]; then
    PORT=${PORT:-6379}
else
    PORT=${PORT:-26379}
fi

# Setup additional parameters
# e.g password-protected redis instances
[ -z "$PASS"  ] || ADDITIONAL_PARAMS="-a $PASS"

# shutdown the service properly
if [ -e "$SOCK" ] ; then
        $REDIS_CLI -s $SOCK $ADDITIONAL_PARAMS shutdown
else
        $REDIS_CLI -h $HOST -p $PORT $ADDITIONAL_PARAMS shutdown
fi
========================================================================================================

#创建我们需要的209
root in 🌐 linux-learn in ~
➜ vim /opt/redis-6.2.6/bin/redis-shutdown

root in 🌐 linux-learn in ~ took 5m25s
➜ cat /opt/redis-6.2.6/bin/redis-shutdown
#!/bin/bash
#
# Wrapper to close properly redis and sentinel
test x"$REDIS_DEBUG" != x && set -x

redis_cli="/opt/redis/bin/redis-cli"

# Retrieve service name
service_name="$1"
if [ -z "${service_name}" ]; then
  service_name="redis"
fi

# Get the proper config file based on service name
config_file="/data/redis/${service_name}/conf/${service_name}.conf"

# Use awk to retrieve host, port from config file
redis_host="$(awk '/^[[:blank:]]*bind/ { print $2 }' "${config_file}" | tail -n1)"
redis_port="$(awk '/^[[:blank:]]*port/ { print $2 }' "${config_file}" | tail -n1)"
redis_pass="$(awk '/^[[:blank:]]*requirepass/ { print $2 }' "${config_file}" | tail -n1)"
redis_sock="$(awk '/^[[:blank:]]*unixsocket[s]?/ { print $2 }' "${config_file}" | tail -n1)"

# Just in case, use default host, port
redis_host="${redis_host:-127.0.0.1}"
if [ "${service_name}" == "redis-6379" ]; then
  redis_port="${redis_port:-6379}"
else
  redis_port="${redis_port:-26379}"
fi

# Setup additional parameters
# e.g password-protected redis instances
[ -z "${redis_pass}" ] || additional_params="-a ${redis_pass}"

# shutdown the service properly
if [ -e "${redis_sock}" ]; then
  bash -c "${redis_cli} -s ${redis_sock} ${additional_params} shutdown"
else
  bash -c "${redis_cli} -h ${redis_host} -p ${redis_port} ${additional_params} shutdown"
fi

#添加执行权限209
root in 🌐 linux-learn in ~
➜ chmod +x /opt/redis-6.2.6/bin/redis-shutdown

#分发redis停止脚本209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /opt/redis-6.2.6 root@"${i}":/opt/;\
ssh root@"${i}" "tree /opt/redis-6.2.6";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

④ 启动
#准备redis配置文件209
#模板
root in 🌐 linux-learn in ~
➜ cat /opt/redis-6.2.6/conf/redis.conf
#编辑我们需要的
root in 🌐 linux-learn in ~
➜ cp /opt/redis-6.2.6/conf/redis.conf /data/redis/redis-6379/conf/redis-6379.conf
#修改绑定IP地址,数据持久化等等
root in 🌐 linux-learn in ~
➜ vim /data/redis/redis-6379/conf/redis-6379.conf
=======================================================================================================
#IP地址
bind 0.0.0.0
#端口号
port 6379
#前台no,后台tes
daemonize no
#pid文件
pidfile /data/redis/redis-6379/redis_6379.pid
#日志级别
loglevel warning
#日志文件
logfile /data/redis/redis-6379/redis_6379.log
#持久化RDB
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
#数据目录
dir /data/redis/redis-6379/data
#持久化aof配置
appendonly yes
appendfsync everysec 
appendfilename "appendonly.aof"
#安全认证
protected-mode yes
requirepass 123456
masterauth 123456
=======================================================================================================

#分发配置209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /data/redis/redis-6379/conf/redis-6379.conf root@"${i}":/data/redis/redis-6379/conf/;\
ssh root@"${i}" "tree /data/redis";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#启动看看209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "systemctl daemon-reload";\
ssh root@"${i}" "systemctl start redis-6379.service";\
ssh root@"${i}" "systemctl enable redis-6379.service";\
ssh root@"${i}" "systemctl status redis-6379.service";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#停止209
systemctl stop redis-6379.service

#连接测试209
root in 🌐 linux-learn in ~ took 12s
➜ redis-cli -h 192.168.44.209 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.44.209:6379>

3.3.4 配置man手册

#模板文件209
root in 🌐 linux-learn in ~
➜ tree /tmp/redis-dir/usr/share/man/
/tmp/redis-dir/usr/share/man/
├── man1
│   ├── redis-benchmark.1.gz
│   ├── redis-check-aof.1.gz
│   ├── redis-check-rdb.1.gz
│   ├── redis-cli.1.gz
│   ├── redis-sentinel.1.gz -> redis-server.1.gz
│   └── redis-server.1.gz
└── man5
    ├── redis.conf.5.gz
    └── redis-sentinel.conf.5.gz -> redis.conf.5.gz

2 directories, 8 files

#复制man手册到安装目录209
root in 🌐 linux-learn in ~
➜ cp -r /tmp/redis-dir/usr/share/man/man1/* /opt/redis-6.2.6/share/man/man1/

root in 🌐 linux-learn in ~
➜ cp -r /tmp/redis-dir/usr/share/man/man5/* /opt/redis-6.2.6/share/man/man5/

root in 🌐 linux-learn in ~
➜ tree /opt/redis-6.2.6/
/opt/redis-6.2.6/
├── bin
│   ├── redis-benchmark
│   ├── redis-check-aof -> redis-server
│   ├── redis-check-rdb -> redis-server
│   ├── redis-cli
│   ├── redis-sentinel -> redis-server
│   ├── redis-server
│   └── redis-shutdown
├── conf
│   ├── redis.conf
│   └── sentinel.conf
└── share
    └── man
        ├── man1
        │   ├── redis-benchmark.1.gz
        │   ├── redis-check-aof.1.gz
        │   ├── redis-check-rdb.1.gz
        │   ├── redis-cli.1.gz
        │   ├── redis-sentinel.1.gz -> redis-server.1.gz
        │   └── redis-server.1.gz
        └── man5
            ├── redis.conf.5.gz
            └── redis-sentinel.conf.5.gz -> redis.conf.5.gz

6 directories, 17 files

#验证209
root in 🌐 linux-learn in ~
➜ man redis
redis-benchmark      redis-check-rdb      redis.conf           redis-sentinel.conf
redis-check-aof      redis-cli            redis-sentinel       redis-server

#分发man手册209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /opt/redis-6.2.6 root@"${i}":/opt/;\
ssh root@"${i}" "tree /opt/redis-6.2.6";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

3.3.5 配置日志切割

#模板文件209
root in 🌐 linux-learn in ~ took 20s
➜ tree /tmp/redis-dir/
/tmp/redis-dir/
├── etc
│   ├── logrotate.d
│   │   └── redis

#编辑日志切割配置209
root in 🌐 linux-learn in ~ took 4s
➜ yum install logrotate -y

root in 🌐 linux-learn in ~
➜ vim /etc/logrotate.d/redis-6379
/data/redis/redis-6379/*.log {
    weekly
    rotate 10
    copytruncate
    delaycompress
    compress
    notifempty
    missingok
}

#验证209
root in 🌐 linux-learn in ~
➜ logrotate -f /etc/logrotate.d/redis-6379

root in 🌐 linux-learn in ~
➜ tree /data/redis/
/data/redis/
└── redis-6379
    ├── conf
    │   └── redis-6379.conf
    ├── data
    │   ├── appendonly.aof
    │   └── dump.rdb
    ├── redis_6379.log
    ├── redis_6379.log.1
    ├── redis_6379.log.2.gz
    ├── redis_6379.log.3.gz
    └── redis_6379.pid

3 directories, 8 files

#分发日志切割配置209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install logrotate -y";\
rsync -avzP /etc/logrotate.d/redis-6379 root@"${i}":/etc/logrotate.d/;\
ssh root@"${i}" "cat /etc/logrotate.d/redis-6379";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

3.4 主从配置

IP地址主机名称角色
192.168.44.209redis1master
192.168.44.210redis2slave
192.168.44.211redis3slave

开始配置主从~

节点209的操作

#编辑主从复制宣布ip
root in 🌐 redis1 in ~
➜ vim /data/redis/redis-6379/conf/redis-6379.conf
replica-announce-ip 192.168.44.209
replica-announce-port 6379

#重启redis
root in 🌐 redis1 in ~
➜ systemctl restart redis-6379.service

节点210的操作

#编辑主从复制宣布ip地址210
root in 🌐 redis2 in ~
➜ vim /data/redis/redis-6379/conf/redis-6379.conf
replica-announce-ip 192.168.44.210
replica-announce-port 6379

#重启redis服务210
root in 🌐 redis2 in ~
➜ systemctl restart redis-6379.service

#临时210
root in 🌐 redis2 in ~
➜ redis-cli -h 192.168.44.210 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.44.210:6379> REPLICAOF 192.168.44.209 6379

#永久210
root in 🌐 redis2 in ~ took 7s
➜ sed -rn '459,480p' /data/redis/redis-6379/conf/redis-6379.conf
################################# REPLICATION #################################

# Master-Replica replication. Use replicaof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication.
#
#   +------------------+      +---------------+
#   |      Master      | ---> |    Replica    |
#   | (receive writes) |      |  (exact copy) |
#   +------------------+      +---------------+
#
# 1) Redis replication is asynchronous, but you can configure a master to
#    stop accepting writes if it appears to be not connected with at least
#    a given number of replicas.
# 2) Redis replicas are able to perform a partial resynchronization with the
#    master if the replication link is lost for a relatively small amount of
#    time. You may want to configure the replication backlog size (see the next
#    sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
#    network partition replicas automatically try to reconnect to masters
#    and resynchronize with them.
#
# replicaof <masterip> <masterport>
replicaof 192.168.44.209 6379

节点211的操作

#编辑主从复制宣布ip地址211
root in 🌐 redis3 in ~
➜ vim /data/redis/redis-6379/conf/redis-6379.conf
replica-announce-ip 192.168.44.211
replica-announce-port 6379

#重启redis服务211
root in 🌐 redis3 in ~
➜ systemctl restart redis-6379.service

#临时211
root in 🌐 redis3 in ~
➜ redis-cli -h 192.168.44.211 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.44.211:6379> REPLICAOF 192.168.44.209 6379

#永久211
root in 🌐 redis3 in ~ took 7s
➜ sed -rn '459,480p' /data/redis/redis-6379/conf/redis-6379.conf
################################# REPLICATION #################################

# Master-Replica replication. Use replicaof to make a Redis instance a copy of
# another Redis server. A few things to understand ASAP about Redis replication.
#
#   +------------------+      +---------------+
#   |      Master      | ---> |    Replica    |
#   | (receive writes) |      |  (exact copy) |
#   +------------------+      +---------------+
#
# 1) Redis replication is asynchronous, but you can configure a master to
#    stop accepting writes if it appears to be not connected with at least
#    a given number of replicas.
# 2) Redis replicas are able to perform a partial resynchronization with the
#    master if the replication link is lost for a relatively small amount of
#    time. You may want to configure the replication backlog size (see the next
#    sections of this file) with a sensible value depending on your needs.
# 3) Replication is automatic and does not need user intervention. After a
#    network partition replicas automatically try to reconnect to masters
#    and resynchronize with them.
#
# replicaof <masterip> <masterport>
replicaof 192.168.44.209 6379

3.5 主从验证

master节点209的操作

#验证主从209
root in 🌐 redis3 in ~ took 1m44s
➜ redis-cli -h 192.168.44.209 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.44.209:6379> INFO replication
# Replication
role:master
connected_slaves:2
slave0:ip=192.168.44.210,port=6379,state=online,offset=644,lag=1
slave1:ip=192.168.44.211,port=6379,state=online,offset=644,lag=1
master_failover_state:no-failover
master_replid:f5b54179bb2b62243bad42aa283069b9fb70945c
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:644
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:1
repl_backlog_histlen:644

#插入数据209
192.168.44.209:6379> set master yes
OK
192.168.44.209:6379> get master
"yes"

slave节点210,211操作

#210
root in 🌐 redis3 in ~ took 2m25s
➜ redis-cli -h 192.168.44.210 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.44.210:6379> get master
"yes"
192.168.44.210:6379> set slave210 yes
(error) READONLY You can't write against a read only replica.

#211
root in 🌐 redis3 in ~ took 40s
➜ redis-cli -h 192.168.44.211 -p 6379 -a 123456
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.44.211:6379> get master
"yes"
192.168.44.211:6379> set slave211 yes
(error) READONLY You can't write against a read only replica.

#从节点只能读,不能写

3.6 主从原理

3.6.1 相关概念

主从复制原理

Redis 在复制时底层采用的是 psync 命令完成的数据主从同步,同步主要分为:全量复制和增量复制两种

  • 全量复制:顾名思义也就是一次性把主节点数据全部发送给从节点,所以这种情况下,当数据量比较大时,会对主节点和网络造成很大的开销。

  • 部分复制:用于处理主从复制时因网络中断等原因造成数据丢失的场景。当从节点再次和主节点连接时,主节点会补发丢失的数据。因为是补发,所以在发送的数据量一定是小于全量的数据。

概念

在接下来讲解全量复制和部分复制前,需要明确几个概念,在底层使用 psync 命令运行时需要以下几个条件:

复制偏移量

主节点和从节点分别维护一个复制偏移量(offset),代表的是主节点向从节点传递的字节数;主节点每次向从节点传播 N 个字节数据时,主节点的 offset 增加 N;从节点每次收到主节点传来的 N 个字节数据时,从节点的 offset 增加 N。

offset 用于判断主从节点的数据库状态是否一致:如果二者 offset 相同,则一致;如果 offset 不同,则不一致,此时可以根据两个 offset 找出从节点缺少的那部分数据。例如,如果主节点的 offset 是1000,而从节点的 offset 是500,那么部分复制就需要将 offset 为501-1000 的数据传递给从节点。而 offset 为 501-1000 的数据存储的位置,就是下面要介绍的复制积压缓冲区。

复制积压缓冲区

复制积压缓冲区是由主节点维护的、固定长度的、先进先出(FIFO)队列,默认大小1MB;当主节点开始有从节点时创建,其作用是备份主节点最近发送给从节点的数据。注意,无论主节点有一个还是多个从节点,都只需要一个复制积压缓冲区。

在命令传播阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积压缓冲区,作为写命令的备份;除了存储写命令,复制积压缓冲区中还存储了其中的每个字节对应的复制偏移量(offset)。由于复制积压缓冲区定长且是先进先出,所以它保存的是主节点最近执行的写命令;时间较早的写命令会被挤出缓冲区。

由于该缓冲区长度固定且有限,因此可以备份的写命令也有限,当主从节点 offset 的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。反过来说,为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小(通过配置repl-backlog-size);例如如果网络中断的平均时间是 60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为 100KB,则复制积压缓冲区的平均需求为 6MB,保险起见,可以设置为 12MB,来保证绝大多数断线情况都可以使用部分复制。

从节点将 offset 发送给主节点后,主节点根据 offset 和缓冲区大小决定能否执行部分复制:

  • 如果 offset 偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制。

  • 如果 offset 偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制

运行 ID(runid)

每个 Redis 节点在启动时都会生成一个运行 id,即 runid,该 id 用于唯一标识 Redis 节点,它是一个由 40 位随机的十六进制的字符组成的字符串,通过 info server 命令可以查看节点的 runid

从节点在初次建立连接进行全量复制时(从节点发送 psync ? -1),主节点会将自己的 runid 告知给从节点,从节点将其保存起来。当主从节点断开重连时,从节点会将这个runid发送给主节点,主节点会根据从节点发送的 runid来判断选择何种复制:

  • 如果从节点发送的 runid 与当前主节点的 runid 一致时,主节点则尝试进行部分复制,当然能不能进行部分复制还要看偏移量是否在复制积压缓冲区。

  • 如果从节点发送的 runid 与当前主节点的 runid 不一致时,则进行全量复制。

psync命令流程

在了解了复制偏移量、复制积压缓冲区、节点运行 id 之后,下面我们看一下主从节点是如何确定使用全量复制还是部分复制的。

首先,从节点根据当前状态,决定如何调用 psync 命令:

  • 如果从节点之前未执行过 slaveof 或最近执行了slaveof no one,则从节点发送命令为 psync ? -1,向主节点请求全量复制。

  • 如果从节点之前执行了slaveof,则发送命令为 psync ,其中 runid 为上次复制的主节点的 runid,offset 为上次复制截止时从节点保存的复制偏移量。

主节点根据收到的 psync 命令,及当前服务器状态,决定执行全量复制还是部分复制:

  • 如果主节点版本低于 Redis2.8,则返回 -ERR 回复,此时从节点重新发送 sync 命令执行全量复制。

  • 如果主节点版本够新,且 runid 与从节点发送的 runid 相同,且从节点发送的 offset 之后的数据在复制积压缓冲区中都存在,则回复 +continue,表示将进行部分复制,从节点等待主节点发送其缺少的数据即可。

  • 如果主节点版本够新,但是 runid 与从节点发送的 runid 不同,或从节点发送的 offset 之后的数据已不在复制积压缓冲区中(在队列中被挤出了),则回复 +fullresync ,表示要进行全量复制,其中 runid 表示主节点当前的 runid,offset 表示主节点当前的 offset,从节点保存这两个值,以备使用。

3.6.1 全量同步原理

全量复制:顾名思义也就是一次性把主节点数据全部发送给从节点,所以这种情况下,当数据量比较大时,会对主节点和网络造成很大的开销。

全量复制是 Redis 最早支持的复制方式,触发全量复制的命令是 sync 和 psync。下面我们介绍一下 Redis 中全量复制的流程:

  1. 发送 psync 命令进行数据同步,由于是第一次进行复制,从节点没有复制偏移量和主节点运行 id,所以发送 psync ?-1。

  2. 主节点接收从节点的命令后,主节点根据 psync ? -1 解析出当前为全量复制 ( 或者判断{runid}是否和自己一致,如果不一致就使用全量同步 ) ,所以回复 +FULLRESYNC,同时也会将自身的 runid 和 offset 偏移量发送给从节点,响应为 +FULLRESYNC {runid} {offset}。

  3. 从节点接受主节点的响应后,会保存主节点的 runid 和 偏移量 offset。

  4. 主节点执行 bgsave 保存 RDB 文件到本地,主节点发送 RDB 文件给从节点,从节点把接受的 RDB 文件保存在本地,并直接作为从节点的数据文件,接受完 RDB 文件后从节点打印相关日志。

  5. 从节点开始接受 RDB 文件到接受完成期间,主节点仍然响应读写命令,因此主节点会把这期间写命令保存在客户端的缓冲区中,当从节点加载完 RDB 文件后,主节点在把缓冲区的数据发送给从节点,已保证主从之间的数据一致性。如果主节点和从节点 RDB 文件的数据传输时间过长时,按上面分析可能会造成客户端的缓冲区溢出。默认配置为 client-output-buffer-limit slave 256MB 64MB 60。 如果 60 秒内缓冲区消耗大于 64MB 或者超过 256MB 时,主节点将直接关闭客户端连接,造成全量同步失败。

  6. 从节点接受完主节点传送来的全部数据后会清空自身的旧数据。

  7. 从节点清空数据后开始加载 RDB 文件,如果 RDB 文件比较大时,该操作也是比较耗时的。

  8. 从节点成功加载完 RDB 文件后,如果当前节点开启了 AOF 持久化功能,它会立刻做 bgrewriteaof 操作,为了保证全量复制后 AOF 持久化文件立刻可用

全量复制主要耗时地方如下:

  1. 主节点通过 bgsave 命令 fork 子进程进行 RDB 持久化,该过程是非常消耗 CPU、内存(页表复制)、硬盘 IO 的。

  2. 主节点通过网络将 RDB 文件发送给从节点,对主从节点的带宽都会带来很大的消耗。

  3. 从节点清空老数据、载入新 RDB 文件的过程是阻塞的,无法响应客户端的命令;如果从节点执行 bgrewriteaof,也会带来额外的消耗。

其它场景应该尽量必免使用全量复制。由于 Redis 全量复制有种种弊端,所以 Redis 提供了部分复制功能,下面我们看一下 Redis 中的部分复制功能。

3.6.2 增量同步原理

部分复制主要是 Redis 针对全量复制的过高开销做出的一种优化措施,使用 psync{runId}{offset}命令实现,当主从节点在命令传播节点发生了网络中断,出现数据丢失情况,则从节点会向主节点请求发送丢失的数据,如果请求的偏移量在复制积压缓冲区中,则主节点就将剩余的数据补发给从节点,保持主从节点数据一致,由于补发的数据一般都会比较小,所以开销相当于全量复制而言也会很小,流程如下:

  1. 当主从节点之间网络出现中断时,如果超过 repl-timeout 时间,主节点会认为从节点故障并中断复制连接。

  2. 由于主节点没有宕机,所以他依然会响应客户端命令,但因复制连接中断命令无法发送给从节点,但主节点内部会将这段时间的命令保存在客户端缓冲区中,默认大小为 1MB。

  3. 当主从节点网络恢复后,从节点会再次连接上主节点。

  4. 当主从节点连接恢复后,由于从节点之前保存了自身的偏移量和主节点的运行 id。因此会把它们当作 psync 参数发送给主节点,要求进行部分复制操作。

  5. 主节点接受从节点的 psync 命令,会先核对请求的 runid 是否和自身的的 runid 一致,如果一致,说明该从节点复制的当前主节点。然后查看请求的 offset 是否在复制积压缓冲区,如果在则进行部分复制,否则进行全量复制,部分复制回复 +continue 响应,从节点接受回复

  6. 在进行部分复制时,主节点只需要根据 offset 将复制积压缓冲区的数据发送给从节点,保证主从复制进入正常状态

心跳

在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:ping 和 replconf ack。心跳机制对于主从复制的超时判断、数据安全等有作用。

  • 主从节点彼此都有心跳检测机制,各自模拟成对方的客户端进行通信,通过 client list 命令查看复制客户端信息,主节点的连接状态为 flags = M,从节点连接状态为 flags = S。

  • 主节点默认每隔 10 秒对从节点发送 ping 命令,判断从节点的存活性和连接状态,可能通过 repl-ping-slave-period 参数修改发送频率。

  • 从节点在主线程中每隔 1 秒发送 replconf ack{offset} 命令,给主节点上报自身当前的偏移量。

3.6.3 总结

本文主要讲解了主从复制之间的复制原理,分为:全量复制和部分复制。Master 区分是全量复制还是部分复制,依靠的是 runid 与 offset 参数。

第一次复制,则进行全量复制,Master 生成 RDB 文件,并将之后生成的命令存入复制积压缓冲区。Slave 断线重连后,Master 依据 offset 在复制积压缓冲区中选择传输的起始字节。如果找不到则进行全量复制。

3.7 主从优化

master节点配置优化209

repl-diskless-sync yes

#复制同步策略:磁盘或套接字。
#
#新副本和无法重新连接的副本
继续
#复制过程只是接收差异,需要做所谓的
#“完全同步”。RDB文件从主机传输到
#复制品。
#
#传输可以通过两种不同的方式发生:
#
#1)磁盘备份:Redis主机创建一个新进程来写入RDB
#磁盘上的文件。稍后,文件由家长传输
#以增量方式处理副本。
#2)无盘:Redis主机创建了一个新进程
直接写
#RDB文件到副本套接字,而无需接触磁盘。
#
#使用磁盘支持的复制,在生成RDB文件的同时,会生成更多的副本
#可以排队,并在当前子节点后立即使用RDB文件提供服务
#生成RDB文件完成了它的工作。改用无盘复制
#一旦传输开始,到达的新副本将被排队,并有一个新的
#当前传输终止时,传输将开始。
#
#当使用无盘复制时,主机会等待可配置的数量
#开始传输前的时间(秒),希望倍数
#副本将到达,传输可以并行化。
#
#对于慢速磁盘和快速(大带宽)网络,无盘复制
#效果更好。
repl-diskless-sync yes

maxmemory 4g

##############################内存管理################################
#将内存使用限制设置为指定的字节数。
#当达到内存限制时,Redis将尝试删除密钥
#根据所选的驱逐策略(请参阅maxmemory策略)。
#
#如果Redis不能根据策略删除密钥,或者如果策略是
#设置为'noeviction',Redis将开始回复命令错误
#这将使用更多的内存,如SET、LPUSH等,并将继续
#回复GET等只读命令。
#
#当使用Redis作为LRU时,此选项通常很有用
或LFU缓存,或
#为实例设置硬内存限制(使用“noeviction”策略)。
#
#警告:如果您将副本连接到启用了最大内存的实例,
#减去馈送副本所需的输出缓冲区的大小
#根据已使用的内存计数,以便网络问题/重新同步
#不触发按键被逐出的循环,进而输出
#副本缓冲区已满,驱逐的密钥DEL触发删除
#直到数据库完全清空。
#
#简而言之。。。如果您附加了副本,建议您设置较低的
#最大内存限制,以便系统上有一些可用RAM用于复制
#输出缓冲区(但如果策略为“noeviction”,则不需要)。
#
# maxmemory <bytes>
maxmemory 4<g> 4294967296<bytes>

repl-backlog-size 1mb

#设置复制积压的大小。积压是一个积累的缓冲区
#当副本断开连接一段时间时,副本数据
#复制副本希望再次重新连接,通常需要完全重新同步
#不需要,但a
#部分重新同步就足够了,只需将部分数据传递给副本即可
#断开连接时错过。
#
#复制积压越大,副本可以承受的时间就越长
#断开连接,然后能够执行部分重新同步。
#
#只有当至少有一个副本连接时,才会分配积压。
#
#repl积压大小1mb
#适当增大复制积压的大小,可以容忍从节点故障恢复的时间久一些
#同时我们应该尽可能快速地发现从节点故障并迅速恢复
#从而避免全量复制
repl-backlog-size 1mb

四、Redis哨兵

4.1 哨兵的作用与原理

哨兵作用一览

集群状态监控

master选举

一旦发现master挂了,哨兵需要在slave中选举一个作为新的master,选择的依据如下:

  1. 首先会判断slave与master断开时间的长短,如果超过指定的时间(down-after-milliseconds*10)则会排除该slave节点

  2. 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永远不会参与选举

  3. 如果slave-priority值一样,则会判断slave节点的offset值,越大说明数据同步得越全,优先级越高

  4. 最后判断slave的runid大小,越小优先级越高

自动故障转移

4.2 节点规划

IP地址主机名称软件包Redis端口Sentinel端口
192.168.44.209redis1redis,sentinel637926379
192.168.44.210redis2redis,sentinel637926379
192.168.44.211redis3redis,sentinel637926379

4.3 配置免密登录

#209
cd ~
cat >host_list.txt <<'EOF'
192.168.44.209 1
192.168.44.210 1
192.168.44.211 1
EOF
ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa -y
yum install -y sshpass
cd ~
for i in $(seq $(cat host_list.txt |wc -l));\
do \
host_ip="$(cat host_list.txt |awk "NR==${i}"'{print $1}')";\
host_password="$(cat host_list.txt |awk "NR==${i}"'{print $2}')";\
echo "start config host:${host_ip}";\
sshpass -p"${host_password}" ssh-copy-id "-o StrictHostKeyChecking=no" -i /root/.ssh/id_rsa.pub root@"${host_ip}";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${host_ip}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done
#验证209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "ip a";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#修改主机名称所有节点
#批量209
cd ~
num=1
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "hostnamectl set-hostname redis${num}";\
ssh root@"${i}" "hostname";\
num=$((num+1));\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#安装相关小软件所有节点
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install rsync logrotate -y";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#修改host文件所有节点
#单机编辑209
vim /etc/hosts
192.168.44.209   redis1
192.168.44.210   redis2
192.168.44.211   redis3
192.168.44.200   vip
#分发209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /etc/hosts root@"${i}":/etc/hosts;\
ssh root@"${i}" "cat /etc/hosts";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#关闭防火墙和selinux 所有节点
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "systemctl stop firewalld";\
ssh root@"${i}" "systemctl disable firewalld";\
ssh root@"${i}" "sed -ri 's#SELINUX=enforcing#SELINUX=disabled#g' /etc/sysconfig/selinux";\
ssh root@"${i}" "grep -F 'SELINUX=' /etc/sysconfig/selinux";\
ssh root@"${i}" "setenforce 0";\
ssh root@"${i}" "getenforce";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

4.4 Sentinel实例安装

官网:Install Redis from Source | Docs

4.4.1 前置环境

=====================================

仅209单机操作即可

=====================================

#安装docker运行时209
#准备主机清单
#注意~~~~~~~~
#这一步会破坏集群主机清单
#~~~~~~~完成后请参考4.3节还原主机清单
#~~~~~~~~~不然后续集群批量操作会失败~~~~~~~~~~~~~~~~
cd ~
cat <<'EOF' | sudo tee ./host_list.txt
192.168.44.209 1
EOF
ssh-keygen -t rsa -N "" -f /root/.ssh/id_rsa -y

#配置免密登录209
yum install -y sshpass
cd ~
for i in $(seq $(cat host_list.txt |wc -l));\
do \
host_ip="$(cat host_list.txt |awk "NR==${i}"'{print $1}')";\
host_password="$(cat host_list.txt |awk "NR==${i}"'{print $2}')";\
echo "start config host:${host_ip}";\
sshpass -p"${host_password}" ssh-copy-id "-o StrictHostKeyChecking=no" -i /root/.ssh/id_rsa.pub root@"${host_ip}";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${host_ip}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#验证209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "ip a";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#安装小软件
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install rsync -y";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#官方网站:https://docs.docker.com/engine/install/centos/
#清理环境
yum remove docker \
                  docker-client \
                  docker-client-latest \
                  docker-common \
                  docker-latest \
                  docker-latest-logrotate \
                  docker-logrotate \
                  docker-engine
#官方源(备用)
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "curl  https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo";\
ssh root@"${i}" "ls -l /etc/yum.repos.d";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done
=====================================================================
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
=====================================================================
#安装指定版本docker这里是20.10.14版本
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install -y yum-utils";\
ssh root@"${i}" "yum list docker-ce --showduplicates | sort -r";\
ssh root@"${i}" "yum list docker-ce-cli --showduplicates | sort -r";\
ssh root@"${i}" "yum list containerd.io --showduplicates | sort -r";\
ssh root@"${i}" "yum install docker-ce-20.10.14 docker-ce-cli-20.10.14 containerd.io -y";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done
#阿里源(推荐)
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "curl  http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo";\
ssh root@"${i}" "ls -l /etc/yum.repos.d";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done
==================================================================
curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
curl -o /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
==================================================================

#等等安装GPG签名报错?
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "rpm --import https://mirrors.aliyun.com/almalinux/RPM-GPG-KEY-AlmaLinux";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#创建文件夹所有节点
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install tree -y";\
ssh root@"${i}" "mkdir /etc/docker -p";\
ssh root@"${i}" "mkdir /data/docker -p";\
ssh root@"${i}" "tree /data";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#修改docker配置文件,bip172.xx.xx.1的xx.xx替换为主机ip的后两位
#单机编辑209
#参考弃用文档:https://docs.docker.com/engine/deprecated/#duplicate-keys-with-conflicting-values-in-engine-labels
#参考daemon.json配置文档:https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file
#旧版配置,graph在版本v17.05中已弃用;在版本中v23.0彻底移除;用data-root替代
vim /etc/docker/daemon.json
{
  "graph": "/data/docker",
  "storage-driver": "overlay2",
  "insecure-registries": ["registry.access.redhat.com","quay.io","192.168.44.201:8088"],
  "registry-mirrors": [
    "https://uoggbpok.mirror.aliyuncs.com",
    "http://hub-mirror.c.163.com",
    "https://mirror.baidubce.com",
    "https://docker.mirrors.sjtug.sjtu.edu.cn",
    "https://docker.nju.edu.cn"
  ],
  "bip": "172.16.0.1/16",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": {"max-size":"100m", "max-file":"3"}
}
#新版配置,如果发现无法启动docker守护进程,请使用这个配置
vim /etc/docker/daemon.json
{
  "data-root": "/data/docker",
  "storage-driver": "overlay2",
  "insecure-registries": ["registry.access.redhat.com","quay.io","192.168.44.201:8088"],
  "registry-mirrors": [
    "https://uoggbpok.mirror.aliyuncs.com",
    "http://hub-mirror.c.163.com",
    "https://mirror.baidubce.com",
    "https://docker.mirrors.sjtug.sjtu.edu.cn",
    "https://docker.nju.edu.cn"
  ],
  "bip": "172.16.0.1/16",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": {"max-size":"100m", "max-file":"3"}
}
#分发209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /etc/docker/daemon.json root@"${i}":/etc/docker/;\
ssh root@"${i}" "cat /etc/docker/daemon.json";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#所有节点
#启动docker,验证版本信息
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "systemctl daemon-reload";\
ssh root@"${i}" "systemctl enable docker";\
ssh root@"${i}" "systemctl start docker";\
ssh root@"${i}" "docker version";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#安装完成
[root@docker ~]# docker info 

#Docker仓库凉凉了??
#单机配置代理209
#https://docs.docker.com/engine/daemon/proxy/#systemd-unit-file
[root@docker ~]# mkdir -p /etc/systemd/system/docker.service.d
[root@docker ~]# vim /etc/systemd/system/docker.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://192.168.1.131:8080"
Environment="HTTPS_PROXY=http://192.168.1.131:8080"
Environment="NO_PROXY=localhost,127.0.0.1,docker-registry.example.com,192.168.44.201,registry.myhabor.com"

#分发209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "mkdir -p /etc/systemd/system/docker.service.d";\
rsync -avzP /etc/systemd/system/docker.service.d/http-proxy.conf root@"${i}":/etc/systemd/system/docker.service.d/;\
ssh root@"${i}" "cat /etc/systemd/system/docker.service.d/http-proxy.conf";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#单机还原镜像加速配置209
[root@docker ~]# vim /etc/docker/daemon.json
{
  "data-root": "/data/docker",
  "storage-driver": "overlay2",
  "insecure-registries": ["registry.access.redhat.com","quay.io","192.168.44.201:8088"],
  "bip": "172.16.0.1/16",
  "exec-opts": ["native.cgroupdriver=systemd"],
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": {"max-size":"100m", "max-file":"3"}
}

#分发
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /etc/docker/daemon.json root@"${i}":/etc/docker/;\
ssh root@"${i}" "cat /etc/docker/daemon.json";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#重启docker
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "systemctl daemon-reload";\
ssh root@"${i}" "systemctl restart docker";\
ssh root@"${i}" "docker version";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#运行java8临时容器209
[root@docker ~]# docker container run -it --rm openjdk:8 /bin/bash
root@3568980b5c9b:/# env
HOSTNAME=3568980b5c9b
JAVA_HOME=/usr/local/openjdk-8
PWD=/
HOME=/root
LANG=C.UTF-8
TERM=xterm
SHLVL=1
PATH=/usr/local/openjdk-8/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
JAVA_VERSION=8u342
_=/usr/bin/env

4.4.2 下载安装包

官网:Downloads - Redis

发行版源码包:Index of /releases/

#官方推荐源码编译安装,我们投机取巧一下。
#直接下载docker与rpm组装版本209
=>  root @ 󰌽 linux-learn: 󰉋 ~------------------------------------------------------------------------------------------
➜ cd /tmp

=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ yum download --destdir=/tmp redis

#把rpm转化为tar。tgz模式209
=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ rpm2archive redis-5.0.3-5.module_el8.4.0+2583+b9845322.x86_64.rpm

=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ ll
总用量 2.3M
-rw-r--r-- 1 root root 926K 9月   2 20:28 redis-5.0.3-5.module_el8.4.0+2583+b9845322.x86_64.rpm
-rw-r--r-- 1 root root 1.4M 9月   2 20:37 redis-5.0.3-5.module_el8.4.0+2583+b9845322.x86_64.rpm.tgz
drwx------ 3 root root   17 9月   2 20:11 systemd-private-c531182ee6b945ddb1c53618f8c26222-chronyd.service-DKdUBk

#把它解压缩到特定的目录备用209
=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ mkdir -p /tmp/redis-dir

=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ tar xf redis-5.0.3-5.module_el8.4.0+2583+b9845322.x86_64.rpm.tgz -C /tmp/redis-dir

=>  root @ 󰌽 linux-learn: 󰉋 /tmp---------------------------------------------------------------------------------------
➜ tree /tmp/redis-dir
/tmp/redis-dir
├── etc
│   ├── logrotate.d
│   │   └── redis
│   ├── redis.conf
│   ├── redis-sentinel.conf
│   └── systemd
│       └── system
│           ├── redis-sentinel.service.d
│           │   └── limit.conf
│           └── redis.service.d
│               └── limit.conf
├── usr
│   ├── bin
│   │   ├── redis-benchmark
│   │   ├── redis-check-aof -> redis-server
│   │   ├── redis-check-rdb -> redis-server
│   │   ├── redis-cli
│   │   ├── redis-sentinel -> redis-server
│   │   └── redis-server
│   ├── lib
│   │   └── systemd
│   │       └── system
│   │           ├── redis-sentinel.service
│   │           └── redis.service
│   ├── lib64
│   │   └── redis
│   │       └── modules
│   ├── libexec
│   │   └── redis-shutdown
│   └── share
│       ├── licenses
│       │   └── redis
│       │       ├── COPYING
│       │       ├── COPYING-hiredis
│       │       ├── COPYING-jemalloc
│       │       └── COPYRIGHT-lua
│       └── man
│           ├── man1
│           │   ├── redis-benchmark.1.gz
│           │   ├── redis-check-aof.1.gz
│           │   ├── redis-check-rdb.1.gz
│           │   ├── redis-cli.1.gz
│           │   ├── redis-sentinel.1.gz -> redis-server.1.gz
│           │   └── redis-server.1.gz
│           └── man5
│               ├── redis.conf.5.gz
│               └── redis-sentinel.conf.5.gz -> redis.conf.5.gz
└── var
    ├── lib
    │   └── redis
    └── log
        └── redis

26 directories, 26 files

#运行almalinux:8临时容器209
#注意你的宿主机什么操作系统就运行什么
#我的是almalinux:8
root in 🌐 linux-learn in ~
➜ docker container run --name=redis \
--rm \
-it \
almalinux:8 /bin/bash

#把临时容器放入后台运行209
root in 🌐 linux-learn in ~
➜ Ctrl + p + q

#进入容器209
root in 🌐 linux-learn in ~ took 1m55s
➜ docker container exec -it redis /bin/bash

#下载源码并编译
[root@a438ba4941d9 /]# cd /tmp/
[root@a438ba4941d9 tmp]#
[root@a438ba4941d9 tmp]# curl -L https://download.redis.io/releases/redis-6.2.6.tar.gz -o redis-6.2.6.tar.gz
[root@a438ba4941d9 tmp]# tar xf redis-6.2.6.tar.gz
[root@a438ba4941d9 tmp]# cd redis-6.2.6
[root@a438ba4941d9 redis-6.2.6]# yum install -y https://mirrors.aliyun.com/epel/epel-release-latest-8.noarch.rpm
[root@a438ba4941d9 redis-6.2.6]# yum install make gcc glibc glibc-devel openssl openssl-devel systemd-devel -y
[root@a438ba4941d9 redis-6.2.6]# make BUILD_TLS=yes USE_SYSTEMD=yes
[root@a438ba4941d9 redis-6.2.6]# make install
[root@a438ba4941d9 redis-6.2.6]# ls -l
total 244
-rw-rw-r--  1 root root 33624 Oct  4  2021 00-RELEASENOTES
-rw-rw-r--  1 root root    51 Oct  4  2021 BUGS
-rw-rw-r--  1 root root  5026 Oct  4  2021 CONDUCT
-rw-rw-r--  1 root root  3384 Oct  4  2021 CONTRIBUTING
-rw-rw-r--  1 root root  1487 Oct  4  2021 COPYING
-rw-rw-r--  1 root root    11 Oct  4  2021 INSTALL
-rw-rw-r--  1 root root  6888 Oct  4  2021 MANIFESTO
-rw-rw-r--  1 root root   151 Oct  4  2021 Makefile
-rw-rw-r--  1 root root 21567 Oct  4  2021 README.md
-rw-rw-r--  1 root root  3055 Oct  4  2021 TLS.md
drwxrwxr-x  7 root root   213 Sep  2 14:23 deps
-rw-rw-r--  1 root root 93724 Oct  4  2021 redis.conf
-rwxrwxr-x  1 root root   275 Oct  4  2021 runtest
-rwxrwxr-x  1 root root   279 Oct  4  2021 runtest-cluster
-rwxrwxr-x  1 root root  1079 Oct  4  2021 runtest-moduleapi
-rwxrwxr-x  1 root root   281 Oct  4  2021 runtest-sentinel
-rw-rw-r--  1 root root 13768 Oct  4  2021 sentinel.conf
drwxrwxr-x  3 root root 12288 Sep  2 14:29 src
drwxrwxr-x 11 root root   182 Oct  4  2021 tests
drwxrwxr-x  9 root root  4096 Oct  4  2021 utils
[root@a438ba4941d9 redis-6.2.6]# ls -l /usr/local/bin/
total 25048
-rwxr-xr-x 1 root root  6592864 Sep  2 14:29 redis-benchmark
lrwxrwxrwx 1 root root       12 Sep  2 14:29 redis-check-aof -> redis-server
lrwxrwxrwx 1 root root       12 Sep  2 14:29 redis-check-rdb -> redis-server
-rwxr-xr-x 1 root root  6804832 Sep  2 14:29 redis-cli
lrwxrwxrwx 1 root root       12 Sep  2 14:29 redis-sentinel -> redis-server
-rwxr-xr-x 1 root root 12245112 Sep  2 14:29 redis-server

#新开启一个终端,把容器里边的redis复制出来209
#创建我们redis的目录结构
root in 🌐 linux-learn in ~ took 4m36s
➜ mkdir /opt/redis-6.2.6/{bin,share,conf} -p

root in 🌐 linux-learn in ~
➜ mkdir /opt/redis-6.2.6/share/man/{man1,man5} -p

root in 🌐 linux-learn in ~ took 4s
➜ tree /opt/redis-6.2.6/
/opt/redis-6.2.6/
├── bin
├── conf
└── share
    └── man
        ├── man1
        └── man5

6 directories, 0 files

#复制容器里边的redis到安装目录209
root in 🌐 linux-learn in ~
➜ docker container cp redis:/usr/local/bin /tmp/redis-bin

root in 🌐 linux-learn in ~
➜ docker container cp redis:/tmp/redis-6.2.6/redis.conf /opt/redis-6.2.6/conf/

root in 🌐 linux-learn in ~
➜ docker container cp redis:/tmp/redis-6.2.6/sentinel.conf /opt/redis-6.2.6/conf/

root in 🌐 linux-learn in ~
➜ cp -r /tmp/redis-bin/* /opt/redis-6.2.6/bin/

root in 🌐 linux-learn in ~
➜ tree /opt/redis-6.2.6/
/opt/redis-6.2.6/
├── bin
│   ├── redis-benchmark
│   ├── redis-check-aof -> redis-server
│   ├── redis-check-rdb -> redis-server
│   ├── redis-cli
│   ├── redis-sentinel -> redis-server
│   └── redis-server
├── conf
│   ├── redis.conf
│   └── sentinel.conf
└── share
    └── man
        ├── man1
        └── man5

6 directories, 8 files

#分发Redis存档
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install -y tree";\
rsync -avzP /opt/redis-6.2.6 root@"${i}":/opt/;\
ssh root@"${i}" "tree /opt -L 1";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#配置环境变量209
root in 🌐 linux-learn in ~
➜ ln -s /opt/redis-6.2.6 /opt/redis

root in 🌐 linux-learn in ~
➜ tree /opt/ -L 1
/opt/
├── containerd
├── redis -> /opt/redis-6.2.6
├── redis-6.2.6
└── tool

4 directories, 0 files

root in 🌐 linux-learn in ~
➜ vim ~/.bashrc
# redis
export PATH="/opt/redis/bin:$PATH"

#验证209
root in 🌐 linux-learn in ~
➜ redis-server --help
Usage: ./redis-server [/path/to/redis.conf] [options] [-]
       ./redis-server - (read config from stdin)
       ./redis-server -v or --version
       ./redis-server -h or --help
       ./redis-server --test-memory <megabytes>

Examples:
       ./redis-server (run the server with default conf)
       ./redis-server /etc/redis/6379.conf
       ./redis-server --port 7777
       ./redis-server --port 7777 --replicaof 127.0.0.1 8888
       ./redis-server /etc/myredis.conf --loglevel verbose -
       ./redis-server /etc/myredis.conf --loglevel verbose

Sentinel mode:
       ./redis-server /etc/sentinel.conf --sentinel

root in 🌐 linux-learn in ~
➜ redis-server -v
Redis server v=6.2.6 sha=00000000:0 malloc=jemalloc-5.1.0 bits=64 build=679f60a40763578

#分发环境变量配置
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "ln -s /opt/redis-6.2.6 /opt/redis";\
ssh root@"${i}" "tree /opt -L 1";\
rsync -avzP ~/.bashrc root@"${i}":~/.bashrc;\
ssh root@"${i}" "tail ~/.bashrc";\
ssh root@"${i}" "/opt/redis/bin/redis-server -v";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

4.4.3 安装并启动

① 创建运行目录
#创建redis系统用户209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "useradd -r -M -s /sbin/nologin redis";\
ssh root@"${i}" "id redis";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#创建Sentinel运行相关目录209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "mkdir /data/redis/redis-sentinel/{data,conf} -p";\
ssh root@"${i}" "tree /data/redis";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#更改所有权209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "chown -R redis:redis /data/redis";\
ssh root@"${i}" "ls -l /data/redis";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

② 创建守护进程服务
#创建sentinel守护进程服务文件209
#模板文件
========================================================================================================
root in 🌐 linux-learn in ~
➜ cat /tmp/redis-dir/usr/lib/systemd/system/redis-sentinel.service
[Unit]
Description=Redis Sentinel
After=network.target

[Service]
ExecStart=/usr/bin/redis-sentinel /etc/redis-sentinel.conf --supervised systemd
ExecStop=/usr/libexec/redis-shutdown redis-sentinel
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
========================================================================================================
#创建我们需要的
cat >/etc/systemd/system/redis-sentinel.service <<'EOF'
[Unit]
Description=Redis Sentinel
After=network.target

[Service]
ExecStart=/opt/redis/bin/redis-sentinel /data/redis/redis-sentinel/conf/redis-sentinel.conf --supervised systemd
ExecStop=/opt/redis/bin/redis-shutdown redis-sentinel
Type=notify
User=redis
Group=redis
RuntimeDirectory=redis
RuntimeDirectoryMode=0755

[Install]
WantedBy=multi-user.target
EOF

#创建sentinel守护进程服务文件限制209
#模板
========================================================================================================
root in 🌐 linux-learn in ~
➜ cat /tmp/redis-dir/etc/systemd/system/redis-sentinel.service.d/limit.conf
# If you need to change max open file limit
# for example, when you change maxclient in configuration
# you can change the LimitNOFILE value below
# see "man systemd.exec" for information

[Service]
LimitNOFILE=10240
========================================================================================================
#创建我们需要的
mkdir -p /etc/systemd/system/redis-sentinel.service.d
cat >/etc/systemd/system/redis-sentinel.service.d/limit.conf <<'EOF'
# If you need to change max open file limit
# for example, when you change maxclient in configuration
# you can change the LimitNOFILE value below
# see "man systemd.exec" for information

[Service]
LimitNOFILE=10240
EOF

#分发守护进程服务
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /etc/systemd/system/redis-sentinel.service root@"${i}":/etc/systemd/system/;\
ssh root@"${i}" "mkdir -p /etc/systemd/system/redis-sentinel.service.d";\
rsync -avzP /etc/systemd/system/redis-sentinel.service.d/limit.conf root@"${i}":/etc/systemd/system/redis-sentinel.service.d/;\
ssh root@"${i}" "cat /etc/systemd/system/redis-sentinel.service";\
ssh root@"${i}" "echo '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'";\
ssh root@"${i}" "echo";\
ssh root@"${i}" "echo '~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~'";\
ssh root@"${i}" "cat /etc/systemd/system/redis-sentinel.service.d/limit.conf";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

③ 创建停止脚本
#创建redis停止脚本209
#模板
========================================================================================================
root in 🌐 linux-learn in ~
➜ cat /tmp/redis-dir/usr/libexec/redis-shutdown
#!/bin/bash
#
# Wrapper to close properly redis and sentinel
test x"$REDIS_DEBUG" != x && set -x

REDIS_CLI=/usr/bin/redis-cli

# Retrieve service name
SERVICE_NAME="$1"
if [ -z "$SERVICE_NAME" ]; then
   SERVICE_NAME=redis
fi

# Get the proper config file based on service name
CONFIG_FILE="/etc/$SERVICE_NAME.conf"

# Use awk to retrieve host, port from config file
HOST=`awk '/^[[:blank:]]*bind/ { print $2 }' $CONFIG_FILE | tail -n1`
PORT=`awk '/^[[:blank:]]*port/ { print $2 }' $CONFIG_FILE | tail -n1`
PASS=`awk '/^[[:blank:]]*requirepass/ { print $2 }' $CONFIG_FILE | tail -n1`
SOCK=`awk '/^[[:blank:]]*unixsocket\s/ { print $2 }' $CONFIG_FILE | tail -n1`

# Just in case, use default host, port
HOST=${HOST:-127.0.0.1}
if [ "$SERVICE_NAME" = redis ]; then
    PORT=${PORT:-6379}
else
    PORT=${PORT:-26379}
fi

# Setup additional parameters
# e.g password-protected redis instances
[ -z "$PASS"  ] || ADDITIONAL_PARAMS="-a $PASS"

# shutdown the service properly
if [ -e "$SOCK" ] ; then
        $REDIS_CLI -s $SOCK $ADDITIONAL_PARAMS shutdown
else
        $REDIS_CLI -h $HOST -p $PORT $ADDITIONAL_PARAMS shutdown
fi
========================================================================================================

#创建我们需要的209
root in 🌐 linux-learn in ~
➜ vim /opt/redis-6.2.6/bin/redis-shutdown

root in 🌐 linux-learn in ~ took 5m25s
➜ cat /opt/redis-6.2.6/bin/redis-shutdown
#!/bin/bash
#
# Wrapper to close properly redis and sentinel
test x"$REDIS_DEBUG" != x && set -x

redis_cli="/opt/redis/bin/redis-cli"

# Retrieve service name
service_name="$1"
if [ -z "${service_name}" ]; then
  service_name="redis"
fi

# Get the proper config file based on service name
config_file="/data/redis/${service_name}/conf/${service_name}.conf"

# Use awk to retrieve host, port from config file
redis_host="$(awk '/^[[:blank:]]*bind/ { print $2 }' "${config_file}" | tail -n1)"
redis_port="$(awk '/^[[:blank:]]*port/ { print $2 }' "${config_file}" | tail -n1)"
redis_pass="$(awk '/^[[:blank:]]*requirepass/ { print $2 }' "${config_file}" | tail -n1)"
redis_sock="$(awk '/^[[:blank:]]*unixsocket[s]?/ { print $2 }' "${config_file}" | tail -n1)"

# Just in case, use default host, port
redis_host="${redis_host:-127.0.0.1}"
if [ "${service_name}" == "redis-6379" ]; then
  redis_port="${redis_port:-6379}"
else
  redis_port="${redis_port:-26379}"
fi

# Setup additional parameters
# e.g password-protected redis instances
[ -z "${redis_pass}" ] || additional_params="-a ${redis_pass}"

# shutdown the service properly
if [ -e "${redis_sock}" ]; then
  bash -c "${redis_cli} -s ${redis_sock} ${additional_params} shutdown"
else
  bash -c "${redis_cli} -h ${redis_host} -p ${redis_port} ${additional_params} shutdown"
fi

#添加执行权限209
root in 🌐 linux-learn in ~
➜ chmod +x /opt/redis-6.2.6/bin/redis-shutdown

#分发redis停止脚本209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /opt/redis-6.2.6 root@"${i}":/opt/;\
ssh root@"${i}" "tree /opt/redis-6.2.6";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

④ 启动
#准备sentinel配置文件209
#模板
root in 🌐 linux-learn in ~
➜ cat /opt/redis-6.2.6/conf/sentinel.conf
#编辑我们需要的
root in 🌐 linux-learn in ~
➜ cp /opt/redis-6.2.6/conf/sentinel.conf /data/redis/redis-sentinel/conf/redis-sentinel.conf
#修改绑定端口,哨兵配置等等
root in 🌐 linux-learn in ~
➜ vim /data/redis/redis-sentinel/conf/redis-sentinel.conf
=======================================================================================================
#IP地址
bind 0.0.0.0
#保护模式
protected-mode yes
#端口号
port 26379
#前台no,后台tes
daemonize no
#pid文件
pidfile /data/redis/redis-sentinel/redis_sentinel.pid
#日志文件
logfile /data/redis/redis-sentinel/redis_sentinel.log
#日志级别
loglevel verbose
#数据目录
dir /data/redis/redis-sentinel/data
#监听当前Redis主从master配置
sentinel monitor mymaster 192.168.44.209 6379 2
#节点下线最大时间(毫秒),超过该时间的节点不参与选举
sentinel down-after-milliseconds mymaster 5000
#节点故障恢复超时时间(毫秒)
sentinel failover-timeout mymaster 60000
#认证信息
sentinel auth-pass mymaster 123456
#一次故障转移
sentinel parallel-syncs mymaster 1
=======================================================================================================

#分发配置209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /data/redis/redis-sentinel/conf/redis-sentinel.conf root@"${i}":/data/redis/redis-sentinel/conf/;\
ssh root@"${i}" "tree /data/redis";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#注意了,修改所有权为redis用户,因为sentinel需要权限修改配置209
#因为守护进程我们用的redis用户~~
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "chown -R redis:redis /data/redis";\
ssh root@"${i}" "ls -l /data/redis";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#启动看看209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "systemctl daemon-reload";\
ssh root@"${i}" "systemctl start redis-sentinel.service";\
ssh root@"${i}" "systemctl enable redis-sentinel.service";\
ssh root@"${i}" "systemctl status redis-sentinel.service";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

#停止209
systemctl stop redis-sentinel.service

#测试209
root in 🌐 redis1 in ~ took 4s
➜ systemctl status redis-sentinel.service

4.4.4 配置man手册

#模板文件209
root in 🌐 linux-learn in ~
➜ tree /tmp/redis-dir/usr/share/man/
/tmp/redis-dir/usr/share/man/
├── man1
│   ├── redis-benchmark.1.gz
│   ├── redis-check-aof.1.gz
│   ├── redis-check-rdb.1.gz
│   ├── redis-cli.1.gz
│   ├── redis-sentinel.1.gz -> redis-server.1.gz
│   └── redis-server.1.gz
└── man5
    ├── redis.conf.5.gz
    └── redis-sentinel.conf.5.gz -> redis.conf.5.gz

2 directories, 8 files

#复制man手册到安装目录209
root in 🌐 linux-learn in ~
➜ cp -r /tmp/redis-dir/usr/share/man/man1/* /opt/redis-6.2.6/share/man/man1/

root in 🌐 linux-learn in ~
➜ cp -r /tmp/redis-dir/usr/share/man/man5/* /opt/redis-6.2.6/share/man/man5/

root in 🌐 linux-learn in ~
➜ tree /opt/redis-6.2.6/
/opt/redis-6.2.6/
├── bin
│   ├── redis-benchmark
│   ├── redis-check-aof -> redis-server
│   ├── redis-check-rdb -> redis-server
│   ├── redis-cli
│   ├── redis-sentinel -> redis-server
│   ├── redis-server
│   └── redis-shutdown
├── conf
│   ├── redis.conf
│   └── sentinel.conf
└── share
    └── man
        ├── man1
        │   ├── redis-benchmark.1.gz
        │   ├── redis-check-aof.1.gz
        │   ├── redis-check-rdb.1.gz
        │   ├── redis-cli.1.gz
        │   ├── redis-sentinel.1.gz -> redis-server.1.gz
        │   └── redis-server.1.gz
        └── man5
            ├── redis.conf.5.gz
            └── redis-sentinel.conf.5.gz -> redis.conf.5.gz

6 directories, 17 files

#验证209
root in 🌐 linux-learn in ~
➜ man redis
redis-benchmark      redis-check-rdb      redis.conf           redis-sentinel.conf
redis-check-aof      redis-cli            redis-sentinel       redis-server

#分发man手册209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
rsync -avzP /opt/redis-6.2.6 root@"${i}":/opt/;\
ssh root@"${i}" "tree /opt/redis-6.2.6";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

4.4.5 配置日志切割

#模板文件209
root in 🌐 linux-learn in ~ took 20s
➜ tree /tmp/redis-dir/
/tmp/redis-dir/
├── etc
│   ├── logrotate.d
│   │   └── redis

#编辑日志切割配置209
root in 🌐 linux-learn in ~ took 4s
➜ yum install logrotate -y

root in 🌐 linux-learn in ~
➜ vim /etc/logrotate.d/redis-sentinel
/data/redis/redis-sentinel/*.log {
    weekly
    rotate 10
    copytruncate
    delaycompress
    compress
    notifempty
    missingok
}

#验证209
root in 🌐 linux-learn in ~
➜ logrotate -f /etc/logrotate.d/redis-sentinel

root in 🌐 linux-learn in ~
➜ tree /data/redis/redis-sentinel/
/data/redis/redis-sentinel/
├── conf
│   └── redis-sentinel.conf
├── data
├── redis_sentinel.log
├── redis_sentinel.log.1
└── redis_sentinel.pid

2 directories, 4 files

#分发日志切割配置209
#批量209
cd ~
for i in $(cat host_list.txt |awk '{print $1}');\
do \
ssh root@"${i}" "yum install logrotate -y";\
rsync -avzP /etc/logrotate.d/redis-sentinel root@"${i}":/etc/logrotate.d/;\
ssh root@"${i}" "cat /etc/logrotate.d/redis-sentinel";\
echo -e "\033[36m===================================================\033[0m";\
echo -e "\033[36m${i}\033[0m";\
echo -e "\033[36m===================================================\033[0m";\
echo;\
done

4.5 配置哨兵

节点209配置

#编辑配置开启哨兵宣布ip地址209
root in 🌐 redis1 in ~ took 1m18s
➜ vim /data/redis/redis-sentinel/conf/redis-sentinel.conf
sentinel announce-ip 192.168.44.209
sentinel announce-port 6379

#重启哨兵209
root in 🌐 redis1 in ~
➜ systemctl restart redis-sentinel.service

节点210配置

#编辑配置开启哨兵宣布ip地址210
root in 🌐 redis2 in ~ took 1m18s
➜ vim /data/redis/redis-sentinel/conf/redis-sentinel.conf
sentinel announce-ip 192.168.44.210
sentinel announce-port 6379

#重启哨兵210
root in 🌐 redis2 in ~
➜ systemctl restart redis-sentinel.service

节点211配置

#编辑配置开启哨兵宣布ip地址211
root in 🌐 redis3 in ~ took 1m18s
➜ vim /data/redis/redis-sentinel/conf/redis-sentinel.conf
sentinel announce-ip 192.168.44.211
sentinel announce-port 6379

#重启哨兵211
root in 🌐 redis3 in ~
➜ systemctl restart redis-sentinel.service

4.6 哨兵测试

#查看哨兵209
=>  root @ 󰌽 redis1: 󰉋 ~----------------------------------------
➜ /opt/redis/bin/redis-cli -h 192.168.44.209 -p 26379
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
192.168.44.209:26379> INFO sentinel
# Sentinel
sentinel_masters:1
sentinel_tilt:0
sentinel_running_scripts:0
sentinel_scripts_queue_length:0
sentinel_simulate_failure_flags:0
master0:name=mymaster,status=ok,address=192.168.44.209:6379,slaves=2,sentinels=3

#监听日志209,210,211
root in 🌐 redis1 in ~
➜ tail -F /data/redis/redis-sentinel/redis_sentinel.log

#停止master节点209
root in 🌐 redis1 in ~
➜ systemctl stop redis-6379.service

#故障转移成功209
#选了211为主,其余的成为从
=>  root @ 󰌽 redis1: 󰉋 ~----------------------------------------
➜ grep -E 'sentinel (monitor|known)' /data/redis/redis-sentinel/conf/redis-sentinel.conf
# sentinel monitor <master-name> <ip> <redis-port> <quorum>
sentinel monitor mymaster 192.168.44.211 6379 1
sentinel known-replica mymaster 192.168.44.209 6379
sentinel known-replica mymaster 192.168.44.210 6379
sentinel known-sentinel mymaster 192.168.44.211 26379 50a7e1258fd235f455c904b113f25fc64adb772e
sentinel known-sentinel mymaster 192.168.44.210 26379 5c9dd1a680d74dbf7cae16a1417def64f8c4b41b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值