最新:Redis持久化——如何选择合适的持久化方式
最新:Redis持久化——AOF日志
最新:Redis持久化——内存快照(RDB)
一文回顾Redis五大对象(数据类型)
Redis对象——有序集合(ZSet)
Redis对象——集合(Set)
Redis对象——列表(List)
Redis对象——哈希(Hash)
Redis数据结构——quicklist
Redis对象——字符串
Redis对象——Redis对象系统简介
Redis数据结构——压缩列表
Redis数据结构——整数集合
Redis数据结构——跳跃表
Redis数据结构——字典
Redis数据结构——链表
Redis数据结构——简单动态字符串SDS
我们都知道Redis是内存数据库,它将自己的数据存储的内存中。这样一旦服务器进程退出(断电、重启等原因),那么数据将会丢失。为了解决这个问题,Redis提供两种持久化的方式来将数据持久化到硬盘上,即内存快照(RDB)与AOF日志。
1 什么是内存快照所谓内存快照,顾名思义就是给内存拍个照,在某个时刻把内存中的数据记录下来,以文件的形式保存到硬盘上,这样即使宕机,数据依然存在。在服务器重启后只需要把“照片”中的数据恢复即可。
RDB持久化就是把当前进程的数据在某个时刻生成快照(一个压缩的二进制文件)保存到硬盘的过程,触发RDB持久化过程分为手动触发和自动触发。
1.1 RDB文件的创建RDB文件的创建可以手动触发,也可以自动触发。
1.1 手动触发手动触发分别对应save和bgsave命令:
1.1.1 save命令save命令会阻塞当前Redis服务器,直到RDB过程完成为止。在服务器进程阻塞期间,服务器不能处理任何命令请求。因此,当save命令正在执行时,客户端发送的所有命令都会被拒绝,知道save命令执行完毕。
redis>save //等待,直到RDB文件创建完毕 ok注意:
Redis的单线程模型就决定了,我们要尽量避免所有会阻塞主线程的操作,由于Save命令执行期间阻塞服务器进程,对于内存比较大的实例会造成长时间阻塞,因此线上环境不建议使用。
1.1.2 bgsave命令bgsave命令会派生出一个子进程(而不是线程),由子进程进行RDB文件创建,而父进程继续处理命令。
redis>bgsave Background saving started //直接返回,由子进程进行RDB文件创建 redis> //继续处理其它命令注意:
在bgsave命令执行的时候,为了避免父进程与子进程同时执行两个rdbSave的调用而产生竞争条件,客户端发送的save命令会被服务器拒绝。
如果bgsave命令正在执行,bgrewriteaof(aof重写)命令会被延迟到bgsave命令之后执行,如果bgrewriteaof命令正在执行,那么客户端发送的bgsave命令会被服务器拒绝。
虽然bgsave命令是由子进程进行RDB文件的生成,但是fork()创建子进程的时候会阻塞父进程(详情请往下看)。
1.2 自动触发因为bgsave命令可以在不阻塞服务器进程的情况下保存,所以redis可以通过设置服务器配置的save选项,让服务器每隔一段时间自动执行一次bgsave命令。如:我们向服务器设置如下配置(这也是redis默认的配置):
save 900 1 save 300 10 save 60 10000那么只要满足如下条件中的一个bgsave命令就会被执行:
服务器在900秒内对数据库进行了至少1次修改
服务器在300秒内对数据库进行了至少10次修改
服务器在60秒内对数据库进行了至少10000次修改
1.2 RDB文件的载入在Redis启动的时候,只要检测到RDB文件的存在,就会自动加载RDB文件。需要注意的是
因为AOF文件的更新频率通常比RDB文件的更新频率高,所以口如果服务器开启了AOF持久化功能,那么服务器会优先使用AOF文件来还原数据库状态。
只有在AOF持久化功能处于关闭状态时,服务器才会使用RDB文件来还原数据库状态。
注意:服务器在载入RDB文件期间,会一直处于阻塞状态,直到载入工作完成为止
2 内存快照的问题了解了什么是Redis的RDB持久化,我们来思考两个问题。
2.1 快照的时候数据可以修改吗Redis RDB持久化是对某一时刻的内存中的全量数据进行拍照。这让我们不得不思考,快照的时候数据可以修改吗?
首先,如果我们使用save命令做持久化,那么由于Redis单线程模型的原因,在持久化的过程中会阻塞,是不能执行其它命令的。也许有人会说可以使用bgave命令,但使用bgsave就没有问题了吗?