redis如何持久化?
redis持久化又俩种方式,AOF和RDB,默认使用RDB持久化。可以修改配置文件手动开启AOF持久化
RDB:
RDB 将数据库的快照以二进制的方式保存到磁盘中。文件可读性差,拥挤,但是体积小。是redis某一时刻的全数据持久化,支持手动和自动俩种方式
手动触发:执行SAVE或者BGSAVE指令,生成RDB持久化文件
save:是一个同步保存指令,在持久化期间会造成redis线程阻塞,直到持久化结束,(没人用了吧)
bgsave:bgsave指令执行,redis会调用系统fork函数创建一个子进程(创建子子进程期间redis会阻塞,但是很快),子进程程创建后,redis继续处理客户端请求。子进程程进行RDB持久化
fork函数:是linux操作系统的一个api
自动触发:在配置文件中添加或修改save m n, 指定当m秒内发生n次变化时,会触发bgsave。配置多个满足一个就会触发 原理:serverCron是Redis服务器的周期性操作函数,默认每隔100ms执行一次;该函数会检查 save m n 配置的条件是否满足,如果满足就执行bgsave。
bgsave持久化流程:
1,先判断是否有子进程在执行save,bgsave,bgrewriteaof,如果有忽略掉这次bgsave(忽略掉这次bgsave可以防止多次指令堆积),所以不会有多个子进程(多个子进程也会影响服务器性能)
2,没有则执行bgsave指令,调用fork创建子进程(主进程副本;创建子进程期间redis会阻塞)执行RDB持久化。fork出来的子进程会共享fork那一时刻父进程的内存数据,之后主进程修改了指令,子进程不可见。所以子进程挂了不影响主进程,主进程可以继续出来业务
3,子进程创建好之后会通知父进程,父进程不在阻塞,时间很短
4,redis进行持久化时,会先将redis中得所有数据写到一个临时文件中,待持久化结束后,再用临时文件替换原持久化得文件(所以文件总是完整得,而且存储得时二进制)
5,子进程结束之后会通知父进程持久化完成
配置RDB文件:
默认是Redis根目录下的dump.rdb文件
dir:配置指定目录, dbfilename:指定文件名。 配置:top-writes-on-bgsave-error yes持久化 rdb文件遇到问题时,主进程是否接受写入,yes 表示停止写入,如果是no 表示redis继续提供服务
rdbcompression yes 在进行快照镜像时,是否进行压缩。yes:压缩,但是需要一些cpu的消耗。no:不压缩,需要更多的磁盘空间
服务重启:
服务重启h时会加载RDB文件,但是服务器会进入阻塞状态,如果开启了AOF会优先加载AOF,通常AOF会比RDB更完成 加载RDB文件也会校验RDB文件是否可用,如果不可用,会打印日志信息,redis服务启动失败 (Redis在载入RBD文件时,会计算前面的校验和并与check_sum值比较,判断文件是否损坏。)
正常退出redis会进行一次RDB持久化
RDB 损坏数据恢复:
RDB 文件的载入工作是在服务器启动时自动加载的,如果在 Redis 服务器中没有设置 AOF,那么 Redis 服务器在启动是就会检测RDB文件(redis-check-rdb命令),并自动载入。在载入期间,Redis 服务器会一直处于阻塞状态,直到完成为止。如果载入的DB文件损坏了,则会载入失败,Redis 服务会启动失败,我们可以通过 redis-check-rdb 来完成对 RDB 文件的检测和修复。
AOF:
1,当AOF持久化功能处于打开状态时-->执行写指令-->会以Resp协议格式将被执行的写命令追加到缓冲区aof_bug的末尾-->调用flushAppendOnlyFile函数-->并根据redis配置文件中配置的同步策略,将缓存区的新指令存入硬盘AOF文件中-->当文件大小到达配置文件中的阈值触发重写机制
flushAppendOnlyFile函数:考虑是否需要将 aof_buf 缓冲区中的内容写入和保存到 AOF 文件里面,是否调用由是否开启了aof决定,开启就调用
Resp协议格式:会显有几组数据,每个数据长度,执行的命令等可读性好
同步策略:
always: 每个写指令都同步到磁盘AOF文件中,效率最慢,但是最安全,最多丢一次指令
everysec:专门一个线程,一秒钟同步一次,也快最多丢一秒指令
no:会将指令写入缓存区,何时同步数据到aof文件有系统决定
文件重写:
AOF文件中的内容会越来越多,aof文件过大可能降低redis服务器性能,并且写入和还原时间会更久
重写规则:
多条命令合并为一条,RPUSH list "C",RPUSH list "D" 合并为RPUSH list "C" "D" 多次命令取最新一条:SET A 111,SET A 222 重写后只有SET A 222
重写流程:
1,执行AOF重写请求。
2,如果当前进程正在执行AOF重写,请求不执行,直接返回。
3,如果当前进程正在执行bgsave操作,重写命令延迟到bgsave完成之后再执行。
4,在重写时:redis会fork创建一个重写子进程,这个子进程会读取现有的AOF文件,并将包含的指令重写压缩到一个临时文件中,
5, 同时主进程会将新收到的写指令一边累积到内存缓冲区,一边继续写入到原AOF文件中,这样可以保证原AOF文件的可用性,避免重写时出现意外
6,当重写子进程,完成重写后,会给父进程发送一个信号,父进程收到信号就会将内存中缓存的写指令追加到新AOF文件中,当追加结束后,redis就会用新AOF文件替换旧AOF文件,之后的写指令都会追加到新的AOF文件中
AOF重写触发条件:
手动触发:直接调用bgrewriteaof命令。
自动触发:根据auto-aof-rewrite-min-size和auto-aof-rewrite-percentage参数确定自动触发
aof文件配置:
打开aof:appendonly no
文件名称:appendfilename "appendonly.aof"
同步策略:appendfsync everysec
重写:no-appendfsync-on-rewrite yes, yes表示在重写时,新的写指令存入缓存中,等重写完在写入文件,可以避免IO阻塞,但是如果redis挂了,就会丢失数据 no表示在重写时,新的指令先存入缓存,在同步到aof文件中,有可能造成IO阻塞,但是最安全
auto-aof-rewrite-percentage 100 代表当前AOF文件空间(aof_current_size)和上一次重写后AOF文件空间(aof_base_size)的百分比(如auto-aof-rewrite-percentage 100 当为两倍大小是重写)。:
auto-aof-rewrite-min-size 64mb 表示运行AOF重写时文件最小体积,默认为64MB: