Redis支持两种方式的持久化,一种是RDB方式、另一种是AOF(append-only-file)方式,两种持久化方式可以单独使用其中一种,也可以将这两种方式结合使用。
•RDB:根据指定的规则“定时”将内存中的数据存储在硬盘上,生成的快照
•AOF:每次执行命令后将命令本身记录下来,每次执行命令都会将命令写入到aof文件中
RDB模式
RDB的持久化方式是通过快照(snapshotting)完成的,它是Redis默认的持久化方式,
Redis允许用户自定义快照条件,当符合快照条件时,Redis会自动执行快照操作。快照的条件可以由用户在配置文件中配置。配置格式如下
save
例如:
# save 3600 1
# save 300 100
# save 60 10000
第一个参数是时间窗口,第二个是键的个数,也就是说,在第一个时间参数配置的,时间范围内被更改的键的个数大于后面配置的changes时,即符合快照条件。当触发条件时,Redis会自动将内存中的数据生成一份副本rbd文件并存储在磁盘上,进行一个数据持久化,这个过程称为快照
除了上述规则之外符合我们条件redis自动生成快照,还有以下几种方式生成快照。
1.用户执行SAVE或者GBSAVE命令
2.执行FLUSHALL命令
3.执行复制(replication)时
save 5 1 表示5秒内,有一个key发生变化,就会生成rdb文件。
save和bgsave命令
除了让Redis自动进行快照以外,当我们对服务进行重启或者服务器迁移我们需要人工去干预备份。redis提供了两条命令来完成这个任务
1,save命令,当执行save命令时,Redis同步做快照操作,在快照执行过程中会阻塞所有来自客户端的请求。当redis内存中的数据较多时,通过该命令将导致Redis较长时间的不响应。所以不建议在生产环境上使用这个命令,而是推荐使用bgsave命令
2,bgsave命令
bgsave命令,bgsave命令可以在后台异步地进行快照操作,快照的同时服务器还可以继续响应来自客户端的请求。执行BGSAVE后,Redis会立即返回ok表示开始执行快照操作,
1:redis使用fork函数开启一个子进程,
2:父进程继续接收并处理客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时rdb文件
3:当子进程写入完所有数据后会用该临时rdb文件替换旧的RDB文件,至此,一次快照操作完成。
bgsave是异步执行快照的,在调用fork函数创建子进程时,只对这个时间之前的数据集进行备份(fork函数创建的子进程,是复制该时间点的父进程的,该时间点之后的数据是没有复制的),该时间点之后客户端对redis服务端发送的命令对数据的修改,是没有持久化的没有保存到快照中,
一、优势
1.RDB是一个非常紧凑(compact)的文件,它保存了redis 在某个时间点上的数据集,这种文件非常适合用于进行备份和灾难恢复。
2.生成RDB文件的时候,redis主进程会fork()一个子进程来处理所有保存工作,主进程不需要进行任何磁盘IO操作。
3.RDB 在恢复大数据集时的速度比AOF的恢复速度要快。
二、劣势
•1、RDB方式数据没办法做到实时持久化/秒级持久化。因为bgsave每次运行都要执行fork操作创建子进程,频繁执行成本过高
•2、在一定间隔时间做一次备份,所以如果redis意外down掉的话,最后一次快照之后的修改数据会被丢失(数据有丢失)。
如果数据相对来说比较重要,希望将损失降到最小,则可以使用AOF方式进行持久化。
AOF持久化方式
AOF(Append Only File):Redis 默认不开启。AOF采用日志的形式来记录每个写操作,并追加到文件中。开启后,执行更改Redis数据的命令时,就会把命令写入到AOF文件中。
Redis 重启时会根据日志文件的内容把写指令从前到后执行一次以完成数据的恢复工作。
配置
# 开关 appendonly no /yes # 文件名 appendfilename “appendonly.aof”
AOF相关问题
问题1:数据都是实时持久化到磁盘吗?
虽然每次执行更改Redis数据库内容的操作时,AOF都会将命令记录在AOF文件中,但是事实上,由于操作系统的缓存机制,数据并没有真正地写入硬盘,而是进入了aof_buf缓存中。在默认情况下系统每30秒会执行一次同步操作。以便将aof_buf缓存中的内容真正地写入磁盘中。
在这30秒的过程中如果系统异常退出则会导致aof_buf缓存中的数据丢失。这个时候就需要Redis在写入AOF文件后主动要求系统将aof_buf缓存内容同步到磁盘中。在redis.conf中通过如下配置来设置同步机制。
fork()出一个子进程,通过子进程将aof_buf缓存中的数据同步到磁盘中
参数
说明
appendfsync everysec
AOF持久化策略(硬盘缓存到磁盘),默认
everysec
1 no 表示不执行fsync,由操作系统保证数据同步到磁盘,速度最快,但是不太安全;
2 always 表示每次写入都执行fsync,以保证数据同步到磁盘,效率很低;
3 everysec表示每秒执行一次fsync,可能会导致丢失这1s数据。通常选择 everysec ,兼顾安全性和效率。
问题2:文件越来越大,怎么办?
AOF持久化是Redis不断将写命令记录到 AOF 文件中,随着Redis不断的运行,AOF 的文件会越来越大,文件越大,
为了解决这个问题,Redis新增了重写机制,
当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩,只保留可以恢复数据的最小指令集。
AOF 文件重写并不是对原文件进行重新整理,而是直接读取服务器现有的键值对,然后用一条命令去代替之前记录这个键值对的多条命令,生成一个新的文件后去替换原来的 AOF 文件。
在启动时,Redis会逐个执行AOF文件中的命令来将硬盘中的数据载入到内存中,载入的速度相对于RDB会慢一些
AOF重写机制触发时机:
问题3:重写过程中,AOF文件被更改了怎么办?
Redis 可以在 AOF 文件体积变得过大时,自动地在后台对 AOF 进行重写:重写后的新 AOF 文件包含了重写这一时刻之前数据集所需的最小命令集合。
重写的流程是这样:
• 主进程会fork一个子进程出来进行AOF重写,并不是对原文件进行重新整理,而是直接读取redis服务内存中现有的键值对,然后用一条命令去代替每个键值对,写入到新的AOF文件中
• 在fork子进程这个过程中,服务端仍然可以对外提供服务,在子进程重写的这个时间段里面,,主进程的数据更新操作,会缓存到aof_rewrite_buf中,也就是单独开辟一块缓存来存储重写期间收到的命令,当子进程重写完以后再把缓存中的数据追加到新的aof文件。
• 当所有的数据全部追加到新的aof文件中后,会把旧的aof文件替换成新的aof文件,此后所有的操作都会被写入新的aof文件。
•如果在rewrite过程中出现故障,不会影响原来aof文件的正常工作,只有当rewrite完成后才会切换文件。因此这个rewrite过程是比较可靠的。
在aof_buf缓存到旧的aof文件中间其实还有一个子进程,将aof_buf缓存中的数据同步到aof文件中取
(3)重写子进程会将redis服务中的所有数据键值通过一条指令替代
Redis允许同时开启AOF和RDB,既保证了数据安全又使得进行备份等操作十分容易。如果同时开启后,Redis重启会使用AOF文件来恢复数据,因为AOF方式的持久化可能丢失的数据更少。
优点:
1、AOF 持久化的方法使用默认的每秒同步一次,Redis 最多也就丢失 1 秒的数据而已。
缺点:
1、对于具有相同数据的的Redis,AOF 文件通常会比 RDB 文件体积更大(RDB存的是数据快照)。
2、虽默认情况下,每秒同步一次的频率也具有较高的性能。在高并发的情况下,RDB 比 AOF 具有更好的性能保证。