Redis学习笔记(十一)——Redis持久化

redis通常被我们用作缓存,而很多场合我们也只把他作为缓存使用。关于Redis的各种用法,我前面也已经介绍了一遍,有兴趣的可以点回去看下。

很多时候,我们的一些数据没有做比如Mysql的持久化,就是想要全部存到Redis里面,这时候Redis也提供了相应的持久化支持。

Redis支持的持久化方式

定时快照方式(snapshot)
基于命令追加方式(AOF)
虚拟内存(vm)
Diskstore方式

快照方式

快照是默认的持久化方式,其通过配置文件中的save参数来配置,支持多种配置方式组合。

save 600 10
save 60 5

上述配置中,当600秒有10个key被修改了,或者60秒内有5个key被修改了,都会触发快照。

快照保存方式为操作系统fork出主进程的一个子进程,父进程继续处理client请求,子进程读取全部数据写入到临时文件中,由于os的copy on write机制,父子进程会共享相同的物理页面,当父进程处理写请求时os会为父进程要修改的内存页创建副本,而不是写共享的页。所以子进程的地址空间内的数据是fork时整个数据库的一个快照。

快照方式的缺点:

非增量写文件,所以每次都会重新读取所有内存数据写文件,当数据很大的时候,虽然因为有两个进程不会导致子进程影响主进程,但是这也会导致大量的磁盘IO,导致系统性能下降。
快照方式是定时快照,所以当服务down掉的时候,恢复起来不一定是最新的数据。一般这种应用用于可以接受不一致数据的情况。

AOF方式

本身Redis是不打算做AOF方式的,但是应好多网友要求,官方还是出了AOF的方式持久化。AOF全程是Append-only file,这是一种实时持久化的方式。

配置为appendonly yes

Redis当收到命令之后,会调用write函数把命令写道文件中(默认是appendonly.aof文件)。当数据库重启之后,其会读取文件并把内容全部执行一遍来重建数据。不过由于操作系统的内核会缓存write的修改,正常情况下不会立即写道文件中,所以我们重启之后还是会有一定的数据丢失。不过我们可以通过配置appendfsync always来让操作系统调用fsync函数强制操作系统不缓存,直接写文件。但是这样性能可能会比较差。

另外还提供appendfsync everysec配置,提供每秒持久化。另外当参数为no的时候就完全依赖操作系统了,这个就不好说了。

AOF方式同样也是使用操作系统的fork,主进程继续处理client请求,子进程在持久化的时候把内存的命令写入一个新文件中,同时主进程接收到的其他命令缓存起来在子进程完成之后把缓存的命令也写入进去。然后通过重命名替换老文件。

问题:

这里有个问题就是,对一个key进行inc命令100次,这个日志文件就会记录100个命令。实际上这个数据我们在恢复的时候并不需要那么多命令的。这还会导致aof文件非常大。
另外就是在重启恢复的时候也会比较慢,因为是记录的命令,而不是数据。在恢复的时候需要把aof文件中的数据全部执行一遍,就像上面说的,inc100次,需要执行100次命令,这样会非常慢。有时候几十G的数据需要恢复好几个小时。

虚拟内存方式

这种其实已经废弃了。

主要原因就是重启慢、纪录慢、程序也很复杂。

作者博客在这里。

这个大家知道有这个方式就好了,我们也不会去使用。

diskstore方式

这种方式也是一个实验性方式。使用的是B-Tree(未来可能使用B+-Tree实现)。

总结

使用Redis尽量不要使用持久化,如果非要使用的话,优先使用快照,其次是AOF。

fork进程这点大家了解一下会知道实际上,当操作系统调用fork函数创建子进程之后,操作系统会给子进程和主进程一样的存储数据和空间。所以当持久化的时候,实际上内存基本上来说是会翻倍的。所以常规建议是redis的内存使用尽量保持在系统物理内存的3/5以内。

你可能感兴趣的:(redis)