redis入门学习(二) 数据持久化

通过前面的学习,了解了redis的各个数据类型后,知晓了为何使用redis

它的优势主要是数据存储和查询比关系型数据库快,

这是因为redis的数据都是存储在内存中的原因,并且具有较多的数据类型,

使得在访问查询高频数据时我们可以放置在redis进行缓存,进而减小mysql的访问压力,

而正因为redis存储在内存中的原因,

导致在redis服务关闭前,如果未将内存中的数据存在磁盘上会导致数据的丢失

redis也在这方面进行了处理,尽最大可能的减少数据丢失的概率

这章也主要学习的就是redis的数据持久化方面的处理操作

主要分两类处理:RDB 和 AOF

前者将根据指定的规则"定时"将内存中的数据存储在硬盘上

后者则是在每次执行命令后将命令本身记录下来

首先学习第一种

RDB

RDB方式的持久化是通过快照完成的,当符合一定条件时Redis会自动将内存中的所有数据生成一份副本并存储在硬盘上,这个过程即为"快照" 

那么什么为其符合的条件呢:

· 根据配置规则进行自动快照

· 用户执行SAVE 或 BGSAVE命令

· 执行FLUSHALL 命令

· 执行复制时

1》 根据配置规则进行自动快照

首先找到配置文件

redis入门学习(二) 数据持久化

该配置是用户自定义其快照条件,规则:时间窗口M 和 改动键的个数N  即当在M的时间段内更改键的个数大于N,即为符合自动快照的条件,如: save 900  1 

                              save 300 10 

                              save 60 1000

可以存在多个条件,它们之间的关系为 ”或“ , save 900 1 即为在900S(15min)内有一个或者一个以上的键进行更改,那么会进行快照

2》用户执行SAVE或者BGSAVE命令

   1. SAVE命令   

    用户手动输入命令进行快照操作,redis同步地进行快照操作

    而save会阻塞所有来自客户端的请求,存在问题是 如果reids中的数据比较多时,这一过程会导致redis服务较长时间不响应

所有尽量避免在生产环境中使用这一命令

  2. BGSAVE命令

    需要手动执行快照时推荐使用BGSAVE命令,BGSAVE命令后可以在后台异步地进行快照操作,快照的同时服务器不受影响,会继续接收来自客户端的请求,使用BGSAVE后redis会立即返回一个OK状态并开始进行快照,这一期间如需知晓快照是否完成,通过LASTSAVE命令获取最近依次成功执行快照的时间,返回结果是一个Unix时间戳:

redis入门学习(二) 数据持久化

3》执行FLUSHALL命令

当执行FLUSHALL命令时,redis会清除数据库中所有的数据,只要自动快照条件不为空,即会触发自动快照。

redis入门学习(二) 数据持久化

5 快照原理

每次快照都会将其数据存储在redis目录下的dump.rdb文件中

通过配置dir和dbfilename两个参数分别指定快照文件的存储路径和文件名

快照的过程如下:

1.redis使用fork函数复制一份当前进程(父进程)的副本(子进程)

2.父进程继续接收客户端发来的命令,而子进程开始将内存中的数据写入硬盘中的临时文件

3.当子进程写入完所有的数据后会用该临时文件替换旧的RDB文件,至此依次快照完成

当下次进入redis服务后,会使用硬盘中最近一次快照数据dump.rdb中的数据加载

 

在fork时操作系统(类Unix操作系统)会使用写时拷贝(copy-on-write)策略

即fork函数发生的一刻父子进程共享同一内存数据,当父进程要更改其中某片数据时操作系统会将该片数据复制一份以保证子进程的数据不受影响,所以新的rdb文件存储的是执行fork一刻的内存数据。

所以这说明了在fork时虽然有两个内存副本,但是内存占用量不会翻倍, 所以如果在快照时,写入的数据较多时内存的占用量也是上升,因为fork时内存中保存的修改数据片增加了,内存相应也会增加。

 

通过上述可以发现redis在快照时并不会修改rdb文件,只有快照结束时才会替换旧的文件成为新文件,所以不论任何时候rdb中的数据都是完整的,并且rdb文件是经过压缩的二进制文件,占用的空间会小于内存的数据大小,更加利于传输。

Redis启动读取1000万个字符串类型键,大小为1GB的快照文件载入到内存需要20~30S

 

那么RDB存在的问题是:如果在快照时发生redis退出(可能是断电或其他原因) 那么这次的快照会导致失败,并且rdb中的数据还是上次的数据,部分数据会丢失,但如果对于丢失近几秒或者最近几十个更新键不会有很大的影响, 如果数据相对重要,可以使用AOF方式进程持久化。

 

 

AOF方式

使用redis存储非临时数据时,一般需要打开AOF持久化来降低进程中止导致的数据丢失,AOF可以将redis执行的每一条写命令追加到硬盘文件中,这一过程显然会降低redis的性能,但是大部分情况下这个影响是可以接受的

 

默认情况下AOF是关闭的

redis入门学习(二) 数据持久化

 

flushall之后重启redis发现键名依旧为空,这是因为redis退出时会先保存当前缓存数据到dump.rdb中

如果不需要保存并退出redis需要在客户端进行shutdown nosave  这样 上次保存的数据还在

重启之后尽管flushall 了  还会加载出来

 

 

默认情况下redis安装目录会生成 appendonly.aof文件,如果没有则

执行以下两条命令:

redis-cli config set appendonly yes

 

双击打开:redis入门学习(二) 数据持久化

之前我们查询的键值都保存在这里

 

还有就是数据命令覆盖,修改命令多了之前的也会造成冗余,我们可以设置:

redis入门学习(二) 数据持久化

auto-aof-rewrite-percentage 100就是目前的aof文件大小超过上一次重写时的AOF大小多少时会进行重写,

auto-aof-rewrite-min-size 64mb则限制了允许重写的最小AOF文件大小

 

同步硬盘问题:

每次执行更改数据库内容的操作时,AOF都会将命令记录在AOF文件中,但事实上,由于操作系统的缓存机制,数据并没有真正的写入硬盘,而是进入了系统硬盘缓存,系统每30s会执行一次同步,这期间如果系统异常会导致数据丢失,一般来说启用AOF不能容忍这样的损失,所以在redis写入aof文件后会主动要求系统将缓存内容同步到硬盘,我们在redis中可以这样设置:

 

redis入门学习(二) 数据持久化