数据库

详解 Redis-4.x 持久化机制

2019-01-29  本文已影响151人  CoderJed

1. redis 持久化的意义

redis的数据全部在内存中,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证redis的数据在遇到突发状况的时候不会丢失,或者只丢失少量,于是必须根据一些策略来把redis内存中的数据写到磁盘中,这样当redis服务重启中,就可以根据磁盘中的数据来恢复数据到内存中。

redis持久化的意义

2. redis 持久化机制介绍

redis有两种持久化机制:AOF和RDB

(1) RDB

RDB是一次的全量备份,即周期性的把redis当前内存中的全量数据写入到一个快照文件中。redis是单线程程序,这个线程要同时负责多个客户端的读写请求,还要负责周期性的把当前内存中的数据写到快照文件中RDB中,数据写到RDB文件是IO操作,IO操作会严重影响redis的性能,甚至在持久化的过程中,读写请求会阻塞,为了解决这些问题,redis需要同时进行读写请求和持久化操作,这样又会导致另外的问题,持久化的过程中,内存中的数据还在改变,假如redis正在进行持久化一个大的数据结构,在这个过程中客户端发送一个删除请求,把这个大的数据结构删掉了,这时候持久化的动作还没有完成,那么redis该怎么办呢?

redis使用操作系统的多进程COW机制(Copy On Write)机制来实现快照的持久化,在持久化过程中调用 glibc(Linux下的C函数库) 的函数fork()产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端的读写请求。子进程刚刚产生时,和父进程共享内存里面的代码段和数据段,这是Linux操作系统的机制,为了节约内存资源,所以尽可能让父子进程共享内存,这样在进程分离的一瞬间,内存的增长几乎没有明显变化。

子进程对当前内存中的数据进行持久化,并不会修改当前的数据结构,如果父进程收到了读写请求,那么会把处理的那一部分数据复制一份到内存,对复制后的数据进行修改,所以即使对某个数据进行了修改,redis持久化到RDB中的数据也是未修改的数据,这也是把RDB文件称为"快照"文件的原因,子进程所看到的数据在它被创建的一瞬间就固定下来了,父进程修改的某个数据只是该数据的复制品。

实际上,内存中的全量数据由一个个的"数据段页面"组成,每个数据段页面的大小为4K,客户端要修改的数据在哪个页面中,就会复制一份这个页面到内存中,这个复制的过程称为"页面分离",在持久化过程中,随着分离出的页面越来越多,内存就会持续增长,但是不会超过原内存的2倍,因为在一次持久化的过程中,几乎不会出现所有的页面都会分离的情况,读写请求针对的只是原数据中的小部分,大部分redis数据还是"冷数据"。

RDB过程

(2) AOF

AOF日志存储的是redis服务器的顺序指令序列,即对内存中数据进行修改的指令记录。当redis收到客户端修改指令后,先进行参数校验,如果校验通过,先把该指令存储到AOF日志文件中,也就是先存到磁盘,然后再执行该修改指令。

当redis宕机后重启后,可以读取该AOF文件中的指令,进行数据恢复,恢复的过程就是把记录的指令再顺序执行一次,这样就可以恢复到宕机之前的状态。

redis在长期运行过程中,AOF日志会越来越大,如果redis服务重启后根据很大的AOF文件来顺序执行指令,将会非常耗时,导致redis服务长时间无法对外提供服务,所以需要对AOF文件进行"瘦身"。"瘦身"的过程称作AOF重写(rewrite)。

AOF Rewrite 的原理是,主进程fork一个子进程,对当前内存中的数据进行遍历,转换成一系列的redis操作指令,并序列化到一个新的AOF日志中,然后把序列化操作期间新收到的操作指令追加到新的AOF文件中,追加完毕后就立即替换旧的AOF文件,这样就完成了"瘦身"工作,即AOF Rewrite。

redis把操作指令追加到AOF文件这个过程,并不是直接写到AOF文件中,而是先写到操作系统的内存缓存中,这个内存缓存是由操作系统内核分配的,然后操作系统内核会异步地把内存缓存中的redis操作指令刷写到AOF文件中。

一个新问题是,假如内存缓存中的redis指令还没有来得及刷写到AOF文件中就宕机了,那么这部分未刷写的指令就会丢失,不过,glibc函数库提供了 fsync() 函数,该函数可以将指定文件的内容强制从内存缓存中刷写到磁盘上。fsync操作的周期对redis的性能有很大影响,如何配置将在本文后续的内容中给出建议。

AOF过程 AOF Rewrite过程

(3) redis-4.x 混合持久化

重启redis时,我们很少使用RDB来恢复内存状态,因为会丢失大量数据。我们通常使用AOF日志重放,但是重放AOF日志性能相对RDB来说要慢很多,这样在redis实例很大的情况下,启动需要花费很长的时间。redis-4.0为了解决这个问题,带来了一个新的持久化选项——混合持久化。将RDB文件的内容和增量的AOF日志文件存在一起。这里的AOF日志不再是全量
的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF日志,通常这部分AOF日志很小。

redis-4.x混合持久化机制

redis重启的时候,可以先加载RDB的内容,然后再重放增量AOF日志,就可以完全替代之前的AOF全量文件重放,恢复效率因此大幅得到提升。

3. redis 持久化机制对比

(1) RDB的优缺点

优点:

缺点:

(2) AOF的优缺点

优点:

缺点:

(3) 混合持久化的优缺点

优点:结合了RDB和AOF的优点,使得数据恢复的效率大幅提升

缺点:兼容性不好,redis-4.x新增,虽然最终的文件也是.aof格式的文件,但在4.0之前版本都不识别该aof文件,同时由于前部分是RDB格式,阅读性较差。

(4) 如何选择redis持久化机制

RDB和AOF到底该如何选择

(5) AOF和RDB同时工作

4. redis 持久化机制的配置

######################### 通用 #########################

# 持久化文件(包括RDB文件和AOF文件)的存储目录,默认.
dir dir /home/hadoop/data/redis/6379

######################### RDB #########################

# RDB文件的文件名称,默认dump.rdb
dbfilename dump.rdb

# 生成RDB文件的策略,默认为以下3种,意思是:
# 每隔60s(1min),如果有超过10000个key发生了变化,就写一份新的RDB文件
# 每隔300s(5min),如果有超过10个key发生了变化,就写一份新的RDB文件
# 每隔900s(15min),如果有超过1个key发生了变化,就写一份新的RDB文件
# 配置多种策略可以同时生效,无论满足哪一种条件都会写一份新的RDB文件
save 900 1
save 300 10
save 60 10000

# 是否开启RDB文件压缩,该功能可以节约磁盘空间,默认为yes
rdbcompression yes

# 在写入文件和读取文件时是否开启rdb文件检查,检查是否有无损坏
# 如果在启动时检查发现文件损坏,则停止启动,默认yes
rdbchecksum yes

######################### AOF #########################

# 是否开启AOF机制,默认为no
appendonly yes

# AOF文件的名称,默认为appendonly.aof
appendfilename "appendonly.aof"

# fsync的策略,默认为everysec
# everysec:每秒fsync一次
# no:redis不主动fsync,完全交由操作系统决定
# always:1条指令fsync一次
appendfsync everysec

# AOF文件rewrite策略
# 当上一次重写后的AOF文件的增长比例达到100%
# 比如上一次重写AOF文件后,新文件大小为128M
# 当新文件再次增长了100%,达到了256M
# 并且增长了100%后的文件的大小大于64M,那么开始重写AOF文件
auto-aof-rewrite-percentage 100
auto-aof-rewrite-min-size 64mb

# 是否加载破损的AOF文件,默认为yes,如果设置为no
# 那么redis启动时如果发现AOF文件破损,就会报错并且拒绝启动redis服务。
aof-load-truncated yes

######################### 混合持久化 #########################

# 是否开启混合持久化机制,默认为no
aof-use-rdb-preamble no

建议配置:把appendonly设置为yes,根据需要修改dir,其他均保持默认即可。

5. 其他相关命令

# 阻塞主进程,直到生成新的RDB文件
save 
# 异步生成RDB文件,fork子进程去生成新的RDB文件,主进程不阻塞
bgsave
bgrewriteaof
# 安全停止redis服务,在停止之前会生成一份新的RDB文件
redis-cli SHUTDOWN
# 不安全,会造成数据丢失
kill -9 redis_pid
# 检查AOF文件
redis-check-aof /your/path/appendonly.aof
# 检查RDB文件
redis-check-rdb /your/path/dump.rdb
# 如果redis在append数据到AOF文件时,机器宕机了,可能会导致AOF文件破损,使用以下命令修复AOF文件
$REDIS_HOME/bin/redis-check-aof --fix
# 查看持久化信息
info Persistence

# 查看状态信息
info stats
上一篇下一篇

猜你喜欢

热点阅读