1. Redis性能优化
1.设置最大打开文件数
cat /etc/security/limits.conf
redis soft nofile 100000
redis hard nofile 100000
2.请确保将Linux内核的超额内存设置设为1。
cat /etc/sysctl.conf
vm.overcommit_memory=1
net.core.somaxconn=65535
sysctl -p
3.设置内存大页
cat /etc/rc.local
echo never > /sys/kernel/mm/transparent_hugepage/enabled
system资源限制
[Unit]
Description=Redis Single Service
After=network.target
[Service]
Type=notify
User=dev
Group=dev
TimeoutStartSec=120s
ExecStart=/data/redis/src/redis-server /data/redis/redis.conf
ExecStop=/data/redis/src/redis-cli shutdown -a w4RedisService
Restart=on-failure
RestartSec=30s
LimitNOFILE=100000
LimitNPROC=65535
[Install]
WantedBy=multi-user.target
2. Redis持久化分类
在Redis中,分别为我们提供了 RDB 和 AOF 两种持久化模式。在4.0及以后版本中,提供了一种混合持久化的功能,就是RDB和AOF结合的持久化模式。
分类如下:
RDB持久化方式是通过快照完成的。RDB程序将当前内存中的数据快照保存到磁盘中,在Redis重启时,RDB程序可以通过载入RDB文件来还原数据库的状态。
AOF(append only file),是以独立日志的方式记录每次的写命令,重启时在执行文件中的命令来达到恢复数据的目的。
混合模式就是同时结合了RDB持久化和AOF持久化混合写入AOF文件。这样就可以结合2者的优点了,快速的加载持久化文件,同时避免数据丢失过多。
3. RDB 持久化
3.1 介绍
RDB(Redis DataBase)是将某一个时刻的内存快照(Snapshot),以二进制的方式写入磁盘的过程。
触发方式
触发rdb持久化的方式有2种,分别是手动触发和自动触发
(1)手动触发
手动触发分别对应save和bgsave命令
bgsave流程图如下所示
具体流程如下:
- redis客户端执行
bgsave 命令或者自动触发 bgsave 命令; - 主进程判断当前是否已经存在正在执行的子进程,如果存在,那么主进程直接返回;
- 如果不存在正在执行的子进程,那么就fork一个新的子进程进行持久化数据,fork过程是阻塞的,fork操作完成后主进程即可执行其他操作;
- 子进程先将数据写入到临时的rdb文件中,待快照数据写入完成后再原子替换旧的rdb文件;
- 同时发送信号给主进程,通知主进程rdb持久化完成,主进程更新相关的统计信息(info Persitence下的rdb_*相关选项)。
自动触发
在以下4种情况时会自动触发
- redis.conf中配置
save m n ,即在m秒内有n次修改时,自动触发bgsave生成rdb文件; - 主从复制时,从节点要从主节点进行全量复制时也会触发bgsave操作,生成当时的快照发送到从节点;
- 执行debug reload命令重新加载redis时也会触发bgsave操作;
- 默认情况下执行shutdown命令时,如果没有开启aof持久化,那么也会触发bgsave操作
3.2 配置说明
快照周期:内存快照虽然可以通过技术人员手动执行SAVE或BGSAVE命令来进行,但生产环境下多数情况都会设置其周期性执行条件。
save <seconds> <changes>
save 900 1
save 300 10
save 60 10000
save ""
其它相关配置
dbfilename dump.rdb
dir /home/work/app/redis/data/
stop-writes-on-bgsave-error yes
rdbcompression yes
rdbchecksum yes
配置查询
127.0.0.1:6379> config get dbfilename
127.0.0.1:6379> config get dir
3.3 RDB优缺点
优点
- RDB 的内容为二进制的数据,占用内存更小,更紧凑,更适合做为备份文件;
- RDB 对灾难恢复非常有用,它是一个紧凑的文件,可以更快的传输到远程服务器进行 Redis 服务恢复;
- RDB 可以更大程度的提高 Redis 的运行速度,因为每次持久化时 Redis 主进程都会 fork() 一个子进程,进行数据持久化到磁盘,Redis 主进程并不会执行磁盘 I/O 等操作;
- 与 AOF 格式的文件相比,RDB 文件可以更快的重启。
缺点
- 因为 RDB 只能保存某个时间间隔的数据,如果中途 Redis 服务被意外终止了,则会丢失一段时间内的 Redis 数据;
- RDB 需要经常 fork() 才能使用子进程将其持久化在磁盘上。如果数据集很大,fork() 可能很耗时,并且如果数据集很大且 CPU 性能不佳,则可能导致 Redis 停止为客户端服务几毫秒甚至一秒钟。
4. AOF 持久化
4.1 介绍
AOF(Append-Only File)记录Redis中每次的写命令,类似mysql中的binlog,服务重启时会重新执行AOF中的命令将数据恢复到内存中,RDB(按策略持久化)持久化方式记录的粒度不如AOF(记录每条写命令),因此很多生产环境都是开启AOF持久化。
AOF日志记录Redis的每个写命令,步骤分为:命令追加(append)、文件写入(write)和文件同步(sync)。
触发持久化
AOF 的触发条件分为两种:自动触发和手动触发。
(1)手动触发
在客户端执行 bgrewriteaof 命令就可以手动触发 AOF 持久化,如下图所示:
可以看出执行完 bgrewriteaof 命令之后,AOF 持久化就会被触发。
(2)自动触发
有两种情况可以自动触发 AOF 持久化,分为是:**满足 AOF 设置的策略触发 **和 **满足 AOF 重写触发。**其中,AOF 重写触发会在本文的后半部分详细介绍,这里重点来说 AOF 持久化策略,配置 Redis 多久才将数据 fsync(同步)到磁盘一次。
AOF 持久化策略,分为以下三种:
- always:每条 Redis 操作命令都会写入磁盘,最多丢失一条数据;
- everysec:每秒钟写入一次磁盘,最多丢失一秒的数据;
- no:不设置写入磁盘的规则,根据当前操作系统来决定何时写入磁盘,Linux 默认 30s 写入一次数据至磁盘。
推荐(并且也是默认)的措施为每秒 fsync 一次, 这种 fsync 策略可以兼顾速度和安全性。
注:因为每次写入磁盘都会对 Redis 的性能造成一定的影响,所以要根据用户的实际情况设置相应的策略,一般设置每秒写入一次磁盘的频率就可以满足大部分的使用场景了。
4.2 配置
appendonly yes
appendfilename "appendonly.aof"
dir ./
appendfsync always
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb
4.3 深入理解AOF重写
AOF持久化机制记录每个写命令,当服务重启的时候会复现AOF文件中的所有命令,会消耗太多的资源且重启很慢。因此为了避免AOF文件中的写命令太多文件太大,Redis引入了AOF的重写机制来压缩AOF文件体积。AOF文件重写是把Redis进程内的数据转化为写命令同步到新AOF文件的过程。
把过期的,没有用的,重复的,可优化的命令简化为很小的aof文件。实际上是redis内存中的数据回溯成aof文件。
重写流程:
bgrewriteaof 触发重写,判断是否当前有 bgsave 或 bgrewriteaof 在运行,如果有,则等待该命令结束后再继续执行。- 主进程fork出子进程执行重写操作,保证主进程不会阻塞。
- 子进程遍历redis内存中数据到临时文件,客户端的写请求同时写入
aof_buf 缓冲区和 aof_rewrite_buf 重写缓冲区 保证原AOF文件完整以及新AOF文件生成期间的新的数据修改动作不会丢失。 - 子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。主进程把aof_rewrite_buf中的数据写入到新的AOF文件。
- 使用新的AOF文件覆盖旧的AOF文件,完成AOF重写。
5. RDB和AOF混合方式(4.0版本)
Redis 4.0 中提出了一个混合使用 AOF 日志和内存快照的方法。简单来说,内存快照以一定的频率执行,在两次快照之间,使用 AOF 日志记录这期间的所有命令操作。
原理:混合持久化同样也是通过 bgrewriteaof 重写命令完成的,不同的是当开启混合持久化时,fork出的子进程先将共享的内存副本全量的以RDB方式写入aof文件,然后在将重写缓冲区的增量命令以AOF方式写入到文件,写入完成后通知主进程更新统计信息,并将新的含有RDB格式和AOF格式的AOF文件替换旧的的AOF文件。
简单的说:新的AOF文件前半段是RDB格式的全量数据后半段是AOF格式的增量数据。如图所示
配置
aof-use-rdb-preamble yes
6. 数据恢复实战操作
本次实验redis版本由3.2.12升级到4.0.0,并开启混合持久化,迁移RDB数据,验证数据是否正常
6.1 AOF和RDB的恢复顺序
当Redis服务重启时数据恢复的顺序如下:
- 判断是否开启AOF持久化,若开启了AOF,则使用AOF持久化文件恢复数据,否则使用RDB持久化文件恢复数据;
- 若AOF文件不存在则从RDB文件恢复【其实并没有】;若AOF文件存在则使用AOF文件恢复;
- 若AOF文件和RDB文件都不存在则直接启动Redis;
- 若AOF或RDB文件出现错误,则启动失败返回错误信息;
6.2 恢复流程
流程较为复杂,需要严格按照以下步骤
-
修改配置文件方式关闭aof备份功能,但要开启rdb备份功能; -
一定要开启热修改配置功能,这步很重要,所以单独列一条来写 -
把备份的rdb文件拷贝过去,同时重启redis -
通过命令config set appendonly yes 开启aof备份功能,执行命令后就会自动产生appendon ly.aof这个文件,此时rdb和aof文件数据同步了 -
然后关闭redis,修改配置文件开启aof备份功能; -
然后开启redis,此时才叫数据恢复成功。
6.3 安装3.2.12并备份数据
tar -zxvf redis-3.2.12.tar.gz -C /data/
mv /data/redis-3.2.12 /data/redis
mkdir /data/redis/data
yum install -y gcc gcc-c++ make tcl-devel
cd /data/redis && make &&
cd /data/redis/src && make install && make test
cp /data/redis/redis.conf /data/redis/redis.conf.bak
supervised systemd
dir /data/redis/data
daemonize yes
pidfile /data/redis/redis.pid
port 6379
bind 0.0.0.0
requirepass w4RedisService
loglevel warning
maxclients 65535
tcp-backlog 10240
appendonly no
save 900 1
save 300 10
save 60 10000
maxmemory 50499420160
[Unit]
Description=Redis Single Service
After=network.target
[Service]
Type=notify
User=root
Group=root
TimeoutStartSec=120s
ExecStart=/data/redis/src/redis-server /data/redis/redis.conf
ExecStop=/data/redis/src/redis-cli shutdown -a w4RedisService
Restart=on-failure
RestartSec=30s
LimitNOFILE=100000
LimitNPROC=65535
[Install]
WantedBy=multi-user.target
插入数据
[root@localhost redis]
127.0.0.1:6379>set company1 huanle1
127.0.0.1:6379>set company2 huanle2
127.0.0.1:6379>set company3 huanle3
127.0.0.1:6379>bgsave
127.0.0.1:6379>exit
[root@localhost redis]
6.4 升级4.0.0并恢复数据
tar -zxvf redis-4.0.0.tar.gz
cd redis-4.0.0
make
cd src && make install
make test
supervised systemd
daemonize no
dir /data/redis/data
port 6379
bind 0.0.0.0
requirepass w4RedisService
loglevel warning
maxclients 65535
tcp-backlog 10240
save 900 1
save 300 10
save 60 10000
maxmemory 50499420160
appendonly yes
aof-use-rdb-preamble yes
# 重命名旧的目录和新版本目录
mv redis redis.bak
mv redis-4.0.0 redis
cd /data/redis/data
cp dump.rdb-bak dump.rdb
systemctl start redis
[root@localhost redis]
127.0.0.1:6379> keys *
1) "company1"
2) "company2"
3) "company3"
127.0.0.1:6379> config set appendonly yes
127.0.0.1:6379> exit
[root@localhost redis]
[root@localhost redis]
appendonly yes
[root@localhost redis]
[root@localhost redis]
127.0.0.1:6379> config set aof-use-rdb-preamble yes
OK
127.0.0.1:6379> bgrewriteaof
Background append only file rewriting started
127.0.0.1:6379> set name hanjianjuan
OK
127.0.0.1:6379> quit
[root@localhost redis]
[root@localhost redis]
aof-use-rdb-preamble yes
[root@localhost redis]
结论:aof文件再经过bgrewriteaof之后,再次执行的命令会按照aof的方式进行存储,等下次再bgrewriteaof之后,再进行二进制存储。redis后台再进行bgrewriteaof的时候,这时候如果有客户端命令进来,会再后面进行追加。
|