目录
一、单机
官网:Install Redis from Source | Docs
操作系统 | IP地址 | 主机名称 | 软件包 |
---|---|---|---|
Almalinux-8.10 | 192.168.44.209 | redis1 | Redis |
1.1 前置环境
#安装docker运行时209
#准备主机清单
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
1.2 下载安装包
发行版源码包: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
#配置环境变量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
1.3 安装并启动
1.3.1 创建运行目录
#创建redis系统用户209
root in 🌐 linux-learn in ~
➜ useradd -r -M -s /sbin/nologin redis
root in 🌐 linux-learn in ~
➜ id redis
uid=993(redis) gid=988(redis) 组=988(redis)
#创建redis运行相关目录209
root in 🌐 linux-learn in ~
➜ mkdir /data/redis/redis-6379/{data,conf} -p
root in 🌐 linux-learn in ~
➜ tree /data/redis/
/data/redis/
└── redis-6379
├── conf
└── data
3 directories, 0 files
#更改所有权209
root in 🌐 linux-learn in ~
➜ chown -R redis:redis /data/redis
root in 🌐 linux-learn in ~
➜ ll /data/redis/
总用量 0
drwxr-xr-x 4 redis redis 30 9月 2 23:38 redis-6379
1.3.2 创建守护进程服务
#创建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
1.3.3 创建停止脚本
#创建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
1.3.4 启动
#准备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
systemctl daemon-reload
systemctl start redis-6379.service
systemctl enable redis-6379.service
#停止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>
1.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
1.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
二、Redis持久化
2.1 RDB持久化
① 概念
RDB ( Redis Data Base) 指的是在指定的时间间隔内将内存中的数据集快照写入磁盘,RDB 是内存快照(内存数据的二进制序列化形式)的方式持久化,每次都是从 Redis 中生成一个快照进行数据的全量备份。是Redis默认使用的持久化功能。每次Redis停止时会自动持久化RDB数据!!
② 配置
SAVE:阻塞服务器并创建RDB文件
#通过在 redis-cli 客户端中执行 save 命令可立即进行一次持久化保存。save 命令在执行期间会阻塞 redis-server 进程,
#直至持久化过程完毕。而在 redis-server 进程阻塞期间,Redis不能处理任何读写请求,无法对外提供服务。
root in 🌐 linux-learn in /tmp
➜ 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> save
BGSAVE:以非阻塞方式创建RDB文件
#通过在 redis-cli 客户端中执行 bgsave 命令可立即进行一次持久化保存。不同于 save 命令的是,正如该命令的名称一样,
#background save,后台运行 save。bgsave 命令会使服务器进程 redis-server 生成一个子进程,由该子进程负责完成保存过程。
#在子进程进行保存过程中,不会阻塞 redis-server 进程对客户端读写请求的处理。
root in 🌐 linux-learn in /tmp
➜ 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> bgsave
#需要注意的是由于执行BGSAVE命令需要创建子进程,所以父进程占用的内存数量越大,创建子进程这一操作耗费的时间也会越长,
#因此Redis服务器在执行BGSAVE命令时,仍然可能会由于创建子进程而被短暂地阻塞。
通过配置文件自动创建RDB文件
自动条件触发的本质仍是 bgsave 命令的执行。只不过是用户通过在配置文件中做相应的设置后,Redis 会根据设置信息自动调用 bgsave 命令执行。
#编辑持久化配置209
root in 🌐 linux-learn in /tmp took 4m26s
➜ vim /data/redis/redis-6379/conf/redis-6379.conf
#持久化RDB
save 900 1
save 300 10
save 60 10000
dbfilename dump.rdb
#数据目录
dir /data/redis/redis-6379/data
持久化策略按照如下顺序进行:
如果服务器在60秒之内,对数据库进行了至少10000次修改,则进行持久化。
如果服务器在300秒之内,对数据库进行了至少10次修改,则进行持久化。
如果服务器在900秒之内,对数据库进行了至少1次修改,则进行持久化。
③ 优化
stop-writes-on-bgsave-error yes
翻译:
然而,如果您已经设置了对Redis服务器持久化的正确监控,您可能需要禁用此功能,以便Redis能够继续正常工作,即使磁盘、权限等出现问题。
解释:
如果在没有设置持久化正确结果的监控的情况下,启用了RDB且最后一次持久化数据失败(磁盘损坏,权限等原因),Redis就会停止接收数据。这会让用户意识到数据没有正确持久化到磁盘上,否则没有人会注意到出故障了。当然,如果 bgsave 命令后来可以正常工作了,Redis将自动允许再次写入。
rdbcompression yes
翻译:
是否在导出.rdb数据库文件的时候采用LZF压缩字符串和对象? 默认情况下总是设置成‘yes’,因为它几乎总是一场胜利。 如果你想在存储的子进程中节省一些CPU就设置成’no’, 但是这样如果你的kye/value是可压缩的,你得到的数据就会很大。
解释:
设置为yes时,进行持久化会启用 LZF算法压缩来压缩字符串对象。虽然压缩 RDB 文件会消耗系统资源和CPU,降低性能,但可大幅降低磁盘文件的大小,方便保存到磁盘,加速主从集群中从节点的数据同步。
rdbchecksum yes
翻译:
从RDB的版本5开始CRC64校验和被放置在文件的末尾。这使格式更能抵抗损坏,但有一定的性能在保存和加载RDB文件时按需付费(约10%),因此您可以禁用它以获得最大性能。 在禁用校验和的情况下创建的RDB文件的校验和为零,这将告诉加载代码跳过检查。
解释:
在存储快照后,我们还可以让redis使用CRC64算法来进行数据校验,但是这样做会增加大约10%的性能消耗,如果希望获取到最大的性能提升,可以关闭此功能。
sanitize-dump-payload no
翻译:
该配置用于设置在加载 RDB 文件或进行持久化时是否开启对 zipList、listPack 等数据的全面安全检测。该检测可以降低命令处理时发生系统崩溃的可能。其可设置的值有三种选择:
no:不检测
yes:总是检测
clients:只有当客户端连接时检测。排除了加载 RDB 文件与进行持久化时的检测。
默认值本应该是 clients,但其会影响 Redis 集群的工作,所以默认值为 no,不检测。
rdb-del-sync-files no
主从复制时,是否删除用于同步的从机上的 RDB 文件。默认是 no,不删除。不过需要注意,只有当从机的 RDB 和 AOF 持久化功能都未开启时才生效。
dbfilename dump.rdb
指定 RDB 文件的默认名称,默认为 dump.rdb。
dir /data/redis/redis-6379/data
设置快照文件的存放路径,这个配置项一定是个目录,而不能是文件名。默认是和当前配置文件保存在同一目录。
④ 持久化过程
RDB 持久化方案进行备份时,Redis 会单独 fork 一个子进程来进行持久化,会将数据写入一个临时文件中,持久化完成后替换旧的 RDB 文件。在整个持久化过程中,主进程(为客户端提供服务的进程)不参与 IO 操作,这样能确保 Redis 服务的高性能,RDB 持久化机制适合对数据完整性要求不高但追求高效恢复的使用场景。下面展示 RDB 持久化流程:
关键执行步骤如下
-
Redis 父进程首先判断:当前是否在执行 save,或 bgsave/bgrewriteaof 的子进程,如果在执行则 bgsave 命令直接返回。bgsave/bgrewriteaof 的子进程不能同时执行,主要是基于性能方面的考虑:两个并发的子进程同时执行大量的磁盘写操作,可能引起严重的性能问题。
-
父进程执行 fork 操作创建子进程,这个过程中父进程是阻塞的,Redis 不能执行来自客户端的任何命令。父进程 fork 后,bgsave 命令返回”Background saving started”信息并不再阻塞父进程,并可以响应其他命令。
-
子进程进程对内存数据生成快照文件。
-
父进程在此期间接收的新的写操作,使用 COW 机制写入。
-
子进程完成快照写入,替换旧 RDB 文件,随后子进程退出。
在生成 RDB 文件的步骤中,在同步到磁盘和持续写入这个过程是如何处理数据不一致的情况呢?生成快照 RDB 文件时是否会对业务产生影响?
Fork 子进程的作用
上面说到了 RDB 持久化过程中,主进程会 fork 一个子进程来负责 RDB 的备份,这里简单介绍一下 fork:
-
Linux 操作系统中的程序,fork 会产生一个和父进程完全相同的子进程。子进程与父进程所有的数据均一致,但是子进程是一个全新的进程,与原进程是父子进程关系。
-
出于效率考虑,Linux 操作系统中使用 COW(Copy On Write)写时复制机制,fork 子进程一般情况下与父进程共同使用一段物理内存,只有在进程空间中的内存发生修改时,内存空间才会复制一份出来。
在 Redis 中,RDB 持久化就是充分的利用了这项技术,Redis 在持久化时调用 glibc 函数 fork 一个子进程,全权负责持久化工作,这样父进程仍然能继续给客户端提供服务。fork 的子进程初始时与父进程(Redis 的主进程)共享同一块内存;当持久化过程中,客户端的请求对内存中的数据进行修改,此时就会通过 COW (Copy On Write) 机制对数据段页面进行分离,也就是复制一块内存出来给主进程去修改。
COW (Copy On Write) 机制对数据段页面进行分离,也就是复制一块内存出来给主进程去修改。这会出现极端情况,内存翻倍占用,因此Redis服务器的内存设置通常需要预留一部分出来
相关配置参数:maxmemory <bytes>
⑤ RDB优缺点
优点:
存储紧凑,节省内存空间。
恢复速度非常快。
适合全量备份、全量复制的场景,经常用于灾难恢复(对数据的完整性和一致性要求相对较低的场合)。
缺点:
容易丢失数据,容易丢失两次快照之间 Redis 服务器中变化的数据。
RDB 通过 fork 子进程对内存快照进行全量备份,是一个重量级操作,频繁执行成本高。
2.2 AOF持久化
① 概念
AOF (Append Only File) 是把所有对内存进行修改的指令(写操作)以独立日志文件的方式进行记录,重启时通过执行 (AOF) 文件中的 Redis 命令来恢复数据。
② 配置
#编辑持久化配置209
root in 🌐 linux-learn in /tmp took 4m26s
➜ vim /data/redis/redis-6379/conf/redis-6379.conf
#持久化aof配置
appendonly yes
appendfsync everysec
appendfilename "appendonly.aof"
③ 优化
appendonly yes
默认情况下 AOF 持久化是没有开启的,通过修改配置文件中的 appendonly 属性为 yes 可以开启。但是在生产环境下,修改配置文件需要重启Redis服务器才能生效。所以,采用下面方式开启 AOF 更好。
appendfilename "appendonly.aof"
Redis 7 在这里发生了重大变化。以前的Redis版本中只有一个 appendonly.aof 文件,现在变成了三类文件,并且这三类文件名的前缀都是appendonly.aof。
基本文件:可以是 RDB 格式也可以是 AOF 格式。其存放的内容是由 RDB 转为 AOF 当时内存的快照数据。在数据量非常大的时候,该文件可以有多个。
增量文件:以操作日志形式记录转为 AOF 后的写入操作。该文件可以有多个。
清单文件:用于维护 AOF 文件的创建顺序,保障激活时的应用顺序。该文件只有一个。
appenddirname "appendonlydir"
为了方便管理,可以专门为 AOF 持久化文件指定存放目录。目录名由 appenddirname 属性指定,存放的位置由 redis.conf 配置文件的 dir 属性指定的目录决定。redis7新特性
aof-use-rdb-preamble yes
对于基本文件可以是 RDB 格式也可以是 AOF 格式。通过 aof-use-rdb-preamble 属性可以选择。其默认值为 yes,即默认 AOF 持久化的基本文件为 rdb 格式文件,也就是默认采用混合式持久化。如果关闭混合持久化,那么第一个基本文件就是 AOF 格式。
appendfsync everysec
Linux 操作系统中为了提升性能,使用了页缓存。当我们将 aof_buf 的内容写到磁盘上时,此时数据并没有真正的落盘,而是在页缓存中,为了将页缓存中的数据真正落盘,需要执行 fsync / fdatasync 命令来强制刷盘。这边的文件同步做的就是刷盘操作,或者叫文件刷盘可能更容易理解一些。
AOF 缓存区的同步文件策略由参数 appendfsync 控制,有三种同步策略,各个值的含义如下:
always:命令写入 aof_buf 后立即调用系统 write 操作和系统 fsync 操作同步到 AOF 文件,fsync 完成后线程返回。这种情况下,每次有写命令都要同步到 AOF 文件,硬盘 IO 成为性能瓶颈,Redis 只能支持大约几百TPS写入,严重降低了 Redis 的性能;即便是使用固态硬盘(SSD),每秒大约也只能处理几万个命令,而且会大大降低 SSD 的寿命。可靠性较高,数据基本不丢失。
no:命令写入 aof_buf 后调用系统 write 操作,不对 AOF 文件做 fsync 同步;同步由操作系统负责,通常同步周期为30秒。这种情况下,文件同步的时间不可控,且缓冲区中堆积的数据会很多,数据安全性无法保证。
everysec:命令写入 aof_buf 后调用系统 write 操作,write 完成后线程返回;fsync 同步文件操作由专门的线程每秒调用一次。everysec 是前述两种策略的折中,是性能和数据安全性的平衡,因此是 Redis 的默认配置,也是我们推荐的配置。
no-appendfsync-on-rewrite no
设置为 yes 表示 rewrite 期间对新写操作不 fsync,暂时存在内存中,等 rewrite 完成后再写入,默认为 no。但如果对延迟要求很高的应用,这个字段可以设置为yes,否则还是设置为no,这样对持久化特性来说这是更安全的选择。
aof-rewrite-incremental-fsync yes
当 bgrewriteaof 在执行过程也是先将 rewrite 计算的结果写入到了 aof_rewrite_buf 缓存中,然后当缓存中数据达到一定量后就会调用 fsync()进行刷盘操作,即数据同步,将数据写入到临时文件。该属性用于控制 fsync()每次刷盘的数据量最大不超过 4MB。这样可以避免由于单次刷盘量过大而引发长时间阻塞。
aof-load-truncated yes
在进行 AOF 持久化过程中可能会出现系统突然宕机的情况,此时写入到 AOF 文件中的最后一条数据可能会不完整。当主机启动后,Redis 在 AOF 文件不完整的情况下是否可以启动,取决于属性 aof-load-truncated 的设置。其值为:
yes:AOF 文件最后不完整的数据直接从 AOF 文件中截断删除,不影响 Redis 的启动。
no:AOF 文件最后不完整的数据不可以被截断删除,Redis 无法启动。
在设置为no的时候AOF文件损坏,如何启动?可以使用redis-check-aof工具修复AOF文件,该工具会截断尾部无法解析的AOF。修复完成后Redis才可以启动。
aof-timestamp-enabeld no
该属性设置为 yes 则会开启在 AOF 文件中增加时间戳的显示功能,可方便按照时间对数据进行恢复。但该方式可能会与 AOF 解析器不兼容,所以默认值为 no,不开启
④ Rewite重写机制
AOF Rewrite
随着使用时间的推移,AOF 文件会越来越大。为了防止 AOF 文件由于太大而占用大量的磁盘空间,降低性能,Redis 引入了 Rewrite 机制来对 AOF 文件进行压缩。所谓 Rewrite 其实就是对 AOF 文件进行重写整理。当 Rewrite 开启后,主进程 redis-server创建出一个子进程 bgrewriteaof,由该子进程完成 rewrite 过程。首先会读取当前数据库的状态,将结果写入到一个临时文件,写入完毕后,再 rename 该临时文件为原 aof文件名,覆盖原有文件。
AOF重写的实现原理:首先从数据库中读取键现在的值,然后用一条命令去记录键值对,代替之前记录这个键值对的多条命令。从原理的角度理解下面的重写策略会方便很多。
Rewrite 策略
rewrite 计算也称为 rewrite 策略。rewrite 计算遵循以下策略:
读操作命令不写入文件
无效命令不写入文件(比如多次set同一个key,前面的set就是无效命令)
过期数据不写入文件
多条命令合并写入文件(Hash、集合等数据结构以及对同一个key的值多次进行加减操作等)
手动Rewrite
root in 🌐 linux-learn in /tmp
➜ 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> bgrewriteaof
该命令会使主进程 redis-server 创建出一个子进程 bgrewriteaof,由该子进程完成 rewrite过程。而在 rewrite 期间,redis-server 仍是可以对外提供读写服务的。
自动Rewrite
手动方式需要人办干预,所以一般采用自动方式。由于 Rewrite 过程是一个计算过程,需要消耗大量系统资源,会降低系统性能。所以,Rewrite 过程并不是随时随地任意开启的,而是通过设置一些条件,当满足条件后才会启动,以降低对性能的影响。
#编辑自动Rewrite配置209
root in 🌐 linux-learn in /tmp took 4m26s
➜ vim /data/redis/redis-6379/conf/redis-6379.conf
auto-aof-rewrite-percentage 100
auto-aof-rewite-min-size 64mb
auto-aof-rewrite-percentage
当 aof 文件相较于上一次的 aof 文件大小的百分比达到多少时触发 AOF 重写。举个例子,auto-aof-rewrite-percentage 选项配置为 100,上一版本的 aof 文件大小为 100M,那么当我们的 aof 文件达到 200M 的时候,触发 AOF 重写;
auto-aof-rewite-min-size
开启 rewrite 的 AOF 文件最小值,默认 64MB。也就是最小能容忍 aof 文件的大小,超过这个大小必须进行 AOF 重写;
注意:
在实际中,为了避免在执行命令是造成客户端输入缓冲区溢出,重写程序在处理列表、哈希表、集合、有序集合这四种可能会带有多个元素的键时,会先检查所包含的元素数量,如果元素数量超过了 redis.h/REDIS_AOF_REWRITE_ITEMS_PRE_CMD 常量的值,那么重写程序将使用多条命令来记录键的值,而不单单使用一条命令。
在目前版本中,REDIS_AOF_REWRITE_ITEMS_PRE_CMD 常量的值是64,也就是说,如果一个集合键包含了超过64个元素,那么重写程序会用多条 SADD 命令来记录这个集合,并且每条命令设置的元素数量也为64个。
⑤ 持久化过程
注意:
在整个 AOF 后台重写过程中,只有信号处理函数执行时会对服务器进程(父进程)造成阻塞,在其他时候,AOF 后台重写不会阻塞父进程,这将 AOF 重写对服务器性能造成的影响降到了最低。
⑥ AOF优缺点
优点:
AOF 持久化的方法提供了多种的同步频率,即使使用默认的同步频率每秒同步一次,Redis 最多也就丢失 1 秒的数据而已。
AOF 文件使用 Redis 命令追加的形式来构造,因此,即使 Redis 只能向 AOF 文件写入命令的片断,使用 redis-check-aof 工具也很容易修正 AOF 文件。
AOF 文件的格式可读性较强,这也为使用者提供了更灵活的处理方式。例如,如果我们不小心错用了 FLUSHALL 命令,在重写还没进行时,我们可以手工将最后的 FLUSHALL 命令去掉,然后再使用 AOF 来恢复数据。
缺点:
对于具有相同数据的的 Redis,AOF 文件通常会比 RDF 文件体积更大。
虽然 AOF 提供了多种同步的频率,默认情况下,每秒同步一次的频率也具有较高的性能。但在 Redis 的负载较高时,RDB 比 AOF 具好更好的性能保证。
RDB 使用快照的形式来持久化整个 Redis 数据,而 AOF 只是将每次执行的命令追加到 AOF 文件中,因此从理论上说,RDB 比 AOF 方式更健壮。官方文档也指出,AOF 的确也存在一些 BUG,这些 BUG 在 RDB 没有存在。
2.3 AOF与RDB对比
虽然跟 AOF 相比,RDB 快照的恢复速度快,但快照的频率不好把握,如果频率太低,两次快照间一旦宕机,就可能有比较多的数据丢失。如果频率太高,又会产生额外开销,那么,还有什么方法既能利用 RDB 的快速恢复,又能以较小的开销做到尽量少丢数据呢?
在 Redis4.0 提出了混合使用 AOF 和 RDB 快照的方法,也就是两次 RDB 快照期间的所有命令操作由 AOF 日志文件进行记录。这样的好处是 RDB 快照不需要很频繁的执行,可以避免频繁 fork 对主线程的影响,而且 AOF 日志也只记录两次快照期间的操作,不用记录所有操作,也不会出现文件过大的情况,避免了重写开销。