持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第25天,点击查看活动详情
1、 redis的持久化
因为redis本身是基于内存的,那要是服务器突然崩了,数据不是全没了吗,redis是怎么解决这个问题的呢,就是用了持久化机制 redis提供了两种持久化机制:RDB和AOF
1.1 RDB
redis的RDB简单来讲就是定时去对当前所有的key-value做一个快照,以二进制数据的形式将快照存储到rdb文件中,然后永久存储在磁盘上。因为是快照形式的,所以这个文件相对较小。那么具体的持久化流程是怎么样的呢,这里面的亮点在哪儿?
RDB提供了两种触发持久化的方式: 1、手动触发:通过指令 有两种指令: (1)save: 这个指令执行的持久化会阻塞当前redis服务器,直到持久化完成,也就是说他的持久化实现是在当前redis线程下进行的,而redis又是单线程的,除非把它完成否则别的工作就无法进行。所以这个指令在线上系统的时候要禁用!!!发现同事用了这个指令直接送到衙门!更多是在测试或者自己研究redis的时使用。 (2)bgsave:这个指令和save有很大的区别,它会以fork的方式创建一个新的子进程来完成持久化,阻塞只会发生在通过fork创建创建子进程的这个时间段,而fork是很高效的,这也是redis持久化亮点所在,后面会详细说明。所以实际阻塞的时间很短。 2、自动触发:通过配置文件 真正使用的时候不可能手动去调用指令吧,哪怕自己写一个脚本触发也很麻烦,所以提供了自动触发的方式。配置文件中使用的是save关键字,但是实际上关联的是bgsave指令,由此也看出,官方是不推荐使用save指令的 在redis.conf中配置如下:
# save <secends> <changes>
# 在seconds秒内操作数达到changes了,就执行保存,可以配置多条,默认是开启的
# 思考一下为什么要配置多条?
save 900 1
save 300 10
save 60 10000
# 其他相关配置
# 是否开启压缩
rdbcompression yes
# rdb文件名
dbfilename dump.rdb
# rdb文件路径
dir /var/lib/redis/6379
rdb在持久化时为什么采用fork来创建子进程?
fork使用了copy-on-write(写时复制)机制: 创建子进程的时候并不会拷贝父进程的内存空间,而是拷贝了一个虚拟空间,这个虚拟空间指向的是父进程的物理空间。可以理解为是拷贝了一个内存空间的引用,因此拷贝速度很快,但是又可以通过这个引用访问到内存中间中的数据。 只有当父进程发生写操作修改内存数据时,子进程才会真正去复制物理内存数据,并且也只是复制被修改的内存页中的数据,不是全部的内存数据 所有fork占用的空间更小、更快 最后通过fork创建出来的子进程来进行数据的持久化操作
rdb的优点缺点
优点: 采用快照的方式存入的,类似于java的序列化,所以通过它恢复数据时很快 缺点: 1、不支持拉链:通俗讲就是只能备份一个rdb文件,不能每天都单独生成一个,这样就没办法进行版本重制 2、不实时:因为是定期备份的,所有会存在数据缺失,因此也就引入了AOF实时备份方式
1.2 AOF
直接实时将写操作记录到aof文件中,备份的就是写操作,因此aof文件中记录的实际上是写操作,而不是二进制数据,因此占用空间大,用其恢复数据时实际就是将这些指令重新执行一遍,所以速度很慢
能不能把RDB和AOF的优点集合一下开发出一个新的持久化方案呢? 答案是可以!但并不是新的,redis4.0版本后AOF做了优化,这也是redis持久化亮点之一,那就是AOF中包含了RDB全量数据,再加上AOF在RDB备份时间后的实时操作(增量)记录
这样就及利用了RDB的快,又保证了实时性
开启AOF
# redis.conf
# 文件名,可以看到这里有*,也就是说aof支持
appendfilename *appendonly.aof
# appendfsync always
appendfsync everysec
# appendfsync no
redis是内存数据库,写操作持久化会触发IO,所以有三个级别可以调: no:缓冲区什么时候满了什么时候向磁盘写入数据 always:每次操作都会将缓冲区的数据向磁盘写入 everysec:每秒,默认项,每秒将缓冲区的数据向磁盘写入