redis——持久化
拓展:
内存存储器属于DRAM(动态随机存取存储器),DRAM采用电荷存储信息,是易失性存储器,断电丢失信息。
磁盘属于ROM,采用存储介质存储信息,是非易失性存储器,断电不会丢失信息。
持久化就是将内存中易失性的数据刻写到磁盘中的存储介质中,保证断电后也能够长久保存。
Redis持久化的两种方式:RDB快照与AOF日志
一、RDB——快照
1、原理
①fork一个子进程生成快照。由于Redis是单线程的,同时处理请求和生成快照,会严重影响处理请求的效率,所以在进行RDB持久化时会调用glibc的fork函数产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端读写请求。子进程会生成一个临时快照文件,当RDB结束时,会替换原来的快照文件dump.rdb
②COW写时复制策略。fork的子进程刚刚产生时,和父进程共享内存;当子进程生成快照的同时,如果父进程接受写请求,需要对数据进行修改时,就会复制需要修改数据所在的页(内存管理方式——页式存储,1页4KB),然后父进程在复制页上修改,子进程根据原来的页生成快照。理论上不会超过原来内存的两倍,redis中冷数据比例较高,远达不到两倍。
2、RDB的时机
①调用指令SAVE与BGSAVE时,会生成快照。区别在于BGSAVE会fork子进程,子进程执行RDB工作;SAVE不会fork子进程,由主进程执行RDB工作(严重降低请求效率)。
②调用shutdown时如果没有开启AOF日志持久化,会触发RDB持久化。
③调用flushall清除所有缓存时,也会触发RDB持久化,此时RDB是空的。
3、RDB的相关配置
启动时的配置文件redis.conf
①自动触发RDB:仅利用redis的缓存功能时,可写死save "" 生成空的rdb文件。
save 900 1 //每900秒内至少有一个key值变化,默认BGSAVE触发RDB save 300 10 //每900秒内至少有一个key值变化,默认BGSAVE触发RDB save 60 10000 //每900秒内至少有一个key值变化,默认BGSAVE触发RDB
②stop-writes-on-bgsave-error:当BGSAVE触发RDB报错时是否停止写操作,提醒开发人员redisRDB持久化出错了。
③rdbcompression:生成的dump.rdb文件是否压缩
④rdbchecksum :dump.rdb文件生成后是否校验准确性
⑤dbfilename:生成的持久化文件名称,默认dump.rdb
⑥dir:生成持久化文件路径,也是rdb启动时读取文件目录
二、AOF——日志
RDB快照是全量备份,AOF日志是连续的增量备份。
1、原理
①redis在接收到客户端写操作指令后,进行参数校验、逻辑处理,如果没问题,就立即将该指令文本存储到AOF日志中,即先执行指令后将日志存盘。
②fsync : 增量备份,所以需要不停的对AOF文件进行写操作,一般的写操作,内存将该存储的数据直接分配到一个内存缓存区,然后由操作系统异步将数据写入回磁盘,如果机器突然宕机了,可能导致缓存区数据没有写回磁盘,导致AOF日志内容丢失。Linux的glibc提供fsync函数强制将内存缓存区的数据写到磁盘,将写操作变成一个同步操作。同步IO操作会导致磁盘读写速度拖累内存读写处理速度,很慢,如果redis执行一条指令fsync一次,那么就跟MySQL等磁盘数据库差不多,丢失内存数据库的高性能优势。所以一般生产环境每个1s左右执行一次fsync操作。异步IO——>同步IO:写入缓存区--等待--写回磁盘——> 写入缓存区-->强制直接写回磁盘不需等待。
2、AOF日志文件重写
AOF是增量备份,所以日志文件会越来越大,AOF重启会非常耗时,需要对AOF日志重写。
redis提供了bgrewriteaof指令用于对AOF日志进行瘦身,原理开辟一个子进程对内存进行遍历,转换成一系列redis的操作指令,序列化到一个新的AOF日志文件中,代替旧的AOF日志文件。
rpush list 1 // 1 rpush list 2 // 1 2 rpush list 3 // 1 2 rpush list 4 // 1 2 3 4 lpop // 2 3 4 //会根据内存实际数据2 3 4,将上面一系列指令重写 rpush list 2 3 4
3、AOF的时机
每个写操作都会触发AOF
但由于内存缓存和fsync执行频率受到限制,一般生产机器中,通常是1s左右执行一次fsync,即可能会导致1s左右的日志丢失。
4、AOF的相关配置
①appendonly : 是否启用AOF持久化,默认不启用
②appendfilename : AOF日志名称
③appendfsync :fsync发生频率,默认每秒一次;另有总是和不执行
④no-appendfsync-on-rewrite:后台进程是否同步,rdb的save与aof的fsync同步,即save时会阻塞fsync,fsync时会阻塞save
⑤auto-aof-rewrite-percentage :自动触发AOF重写的条件 :与上一次重写文件大小的比值
auto-aof-rewrite-min-size : 自动触发AOF重写的条件:文件需要>64mb
只有两个都满足,才会触发AOF重写
⑥aof-load-truncated : AOF启动redis时是否忽略最后一条可能存在问题的指令(宕机导致)。
⑦aof-use-rdb-preamble : 是否启用rdb+aof混合持久化。先rdb然后aof提高redis启动效率
5.AOF采用RESP协议存储日志文件。
RESP是Redis序列化协议(Redis Serialization Protocol)的简写,直观的文本协议,优势在于实现过程异常简单,解析性能好
RDB快照是二进制文件,AOF采用的RESP协议存储日志,RESP也是redis的客户端与服务端的通讯协议。
Redis协议将传输的结构数据分为5种最小单位类型,单元结束时统一加上回车换行符号\r\n。
① 单行字符串以“+”符号开头。
+hello world\r\n
② 多行字符串以“$”符号开头,后跟字符串长度。
$11\r\n\hello world\r\n $-1\r\n //特殊字符:NULL $0\r\n\r\n //空字符串:""
③ 整数值以“:”符号开头,后跟整数的字符串形式
:1024\r\n
④ 错误消息以“-”符号开头
-WRONGTYPE Operation against a key holding the wrong kind of value\r\n
⑤ 数组以“*”号开头,后跟数组的长度
*3\r\n:1\r\n:2\r\n:3\r\n
简单测试一下
三、总结
1.rdb是全量备份,aof是增量备份
2.rdb存储某一时刻的内存状态(二进制文件),aof存储是所有写操作的日志(RESP协议保存写指令),
3.rdb启动redis速度比aof快,但数据精确度没有aof准确,rbd适用于灾难恢复,aof适用于日常恢复
4.redis4.0后支持混合持久化,是两种持久化的折中。在aof重写时生成rdb文件和aof文件,然后aof文件继续增量更新。重新启动时先加载rdb后再加载aof日志,提高启动效率和数据精确度。
拓展:
设置中的bind参数:绑定的是当前服务器网卡接口,用哪一个网卡接受请求,不设置则默认全部,注意
①设置不存在的网卡接口会启动报错。
②设置监听两个网卡并不是两个网卡生效,仅后面一个网卡生效
仅监听192.168.0.114