redis持久化
redis持久化
- AOF 日志:记录写操作命令,读操作命令不被记录(如何避免文件过大:添加AOF重写机制[后台子进程干]:读取当前数据库中的所有kv对,然后将每一个kv对用一条命令记录到新的AOF文件,等到全部记录完后就将新文件替换掉现有的AOF文件)
- RDB 快照:将某一时刻的内存数据以二进制方式写入磁盘;
- 混合持久化方式:前半部分是 RDB 格式的全量数据,后半部分是 AOF 格式的增量数据。(优点:结合RDB和AOF持久化的优点,开头为 RDB 的格式,使得 Redis 可以更快的启动,同时结合 AOF 的优点,有减低了大量数据丢失的风险。缺点:AOF 文件中添加了RDB格式内容使得文件可读性变差;兼容性差,如果开启混合持久化,那么此混合持久化 AOF 文件就不能用Redis4.0前版本)
大Key对AOF日志的影响
AOF日志写回磁盘策略
- Always:每次写操作命令执行完后,同步将 AOF 日志数据写回硬盘(每次写入 AOF文件数据后就执行 fsync())
- Everysec:每次写操作命令执行完后,先将命令写入到 AOF 文件的内核缓冲区,然后每隔一秒将缓冲区里的内容写回到硬盘(创建一个异步任务来执行fsync())
- No:每次写操作命令执行完后,先将命令写入到 AOF 文件的内核缓冲区,再由操作系统决定何时将缓冲区内容写回硬盘(永不执行fsync())
1、影响持久化
用Always策略时,如果写入是一个大 Key,主线程在执行 fsync() 函数的时候,阻塞的时间会比较久,因为当写入的数据量很大的时候,数据同步到硬盘这个过程是很耗时的
用Everysec策略时,由于是异步执行 fsync() 函数,所以大 Key 持久化的过程(数据同步磁盘)不会影响主线程
用No策略时,由于永不执行fsync() 函数,所以大 Key 持久化的过程不会影响主线程。
并且:
AOF重写机制和RDB快照都会分别通过 fork()
创一个子进程来处理任务。有两个阶段会导致阻塞主线程:
- 创建子进程途中由于要复制父进程的页表等数据结构,页表越大阻塞的时间也越长
- 创完子进程后如果父进程修改了共享数据中的大Key,就会发生写时复制,会拷贝物理内存,会比较耗时
2、客户端超时阻塞
由于Redis执行命令是单线程处理,然后在操作大 key 时会比较耗时,那么就会阻塞 Redis,从客户端这一视角看,就是很久很久都没有响应
3、引发网络阻塞
每次获取大key产生的网络流量较大,如果一个 key 的大小是1 MB,每秒访问量为1000,那么每秒会产生1000MB流量,这对于普通千兆网卡的服务器来说是灾难性的
4、阻塞工作线程
如果使用 del 删除大 key 时,会阻塞工作线程,这样就没办法处理后续的命令
5、内存分布不均
集群模型在槽分片均匀情况下会出现数据和查询倾斜情况,部分有大key的Redis节点占用内存多,QPS吞吐量也会比较大
如何避免大Key
在设计阶段就把大key拆分成一个个小key,或者定时检查Redis是否存在大 key 。如果该大key可删除,不要用DEL命令删除,因为该命令删除过程会阻塞主线程。应该用 unlink命令删除大key,因为该命令的删除过程是异步的,不会阻塞主线程。