一文精通Redis单机部署

目录

一、单机

1.1 前置环境

1.2 下载安装包

1.3 安装并启动

1.3.1 创建运行目录

1.3.2 创建守护进程服务

1.3.3 创建停止脚本

1.3.4 启动

1.4 配置man手册

1.5 配置日志切割

二、Redis持久化

2.1 RDB持久化

① 概念

② 配置

③ 优化

④ 持久化过程

⑤ RDB优缺点

2.2 AOF持久化

① 概念

② 配置

③ 优化

④ Rewite重写机制

⑤ 持久化过程

⑥ AOF优缺点

2.3 AOF与RDB对比


一、单机

官网:Install Redis from Source | Docs

操作系统IP地址主机名称软件包
Almalinux-8.10192.168.44.209redis1Redis

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 下载安装包

官网: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

#配置环境变量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 持久化流程:

关键执行步骤如下

  1. Redis 父进程首先判断:当前是否在执行 save,或 bgsave/bgrewriteaof 的子进程,如果在执行则 bgsave 命令直接返回。bgsave/bgrewriteaof 的子进程不能同时执行,主要是基于性能方面的考虑:两个并发的子进程同时执行大量的磁盘写操作,可能引起严重的性能问题。

  2. 父进程执行 fork 操作创建子进程,这个过程中父进程是阻塞的,Redis 不能执行来自客户端的任何命令。父进程 fork 后,bgsave 命令返回”Background saving started”信息并不再阻塞父进程,并可以响应其他命令。

  3. 子进程进程对内存数据生成快照文件。

  4. 父进程在此期间接收的新的写操作,使用 COW 机制写入。

  5. 子进程完成快照写入,替换旧 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 日志也只记录两次快照期间的操作,不用记录所有操作,也不会出现文件过大的情况,避免了重写开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值