先看mysql事务的四种特性:
1.原子性(核心目标)
2.一致性
3.持久性(持久化)
4.隔离性
Redis是一个内存级的数据库,内存数据易失 -> 存储到硬盘中
Redis相对于mysql这样的关系型数据库,最重要的是快(既存内存,又存硬盘);
硬盘和内存上的数据理论上是相同的;
硬盘上数据只负责在Redis重启后,用来恢复数据;
持久化的两种策略
1.RDB(Redis Database)
2.AOF(Append Only File)
两种都是独立的文件,备份;
RDB定期备份,AOF实时备份,AOF的数据会更新一点;
1.RDB
1.1 RDB结构
RDB定期把Redis内存中的数据,都给写入到硬盘中,生成一个"快照";
Redis一旦重启,可以根据rdb文件来恢复;
定期有两种方式:
1.手动触发;
redis客户端通过执行命令触发快照生成;
save 直接在redis命令处理的单线程执行保存操作,会阻塞其他客户端命令的执行,不建议;bgsave 后台异步执行,不影响其他客户端命令的执行;
redis命令执行不是单线程的吗,如何做到异步的?并发编程不仅有多线程一种方式,还有多进程,bgsave是通过多进程方式实现的;
2.自动触发;
在redis配置文件进行设置,让redis每隔多长时间/每产生多少次修改就触发;Normally the OK code is immediately returned. Redis forks, the parent continues to serve the clients, the child saves the DB on disk then exits.
An error is returned if there is already a background save running or if there is another non-background-save process running, specifically an in-progress AOF rewrite.
bgsave总结:父进程判断是否有其他子进程(正在执行生成RDB文件的进程,正在进行重写AOF的进程);如果没有,则创建子进程执行生成RDB文件,父进程继续处理其他命令,当子进程执行完,通过信号通知父进程;RDB文件存放位置:dir /var/lib/redis,文件名dump.rdb
文件存储的是压缩后的2进制内容,不要乱修改(后续启动时若格式错误,可能导致数据错误或者服务器启动不起来)
压缩:Redis 默认采用 LZF 算法对生成的 RDB ⽂件做压缩处理,压缩后的文件远远小于内存大小,默认开启,可以通过参数 config set rdbcompression {yes|no} 动态修改。
RDB优势:
1)占用空间小,非常适合用于备份
2)redis加载RDB恢复数据远快于AOF
RDB劣势:1)生成RDB文件是个重量级操作,频繁执行成本过高 -> 导致执行不频繁,RDB实时性不强(核心劣势)
2)RDB文件使用特定2进制存储,且受版本影响,有兼容性问题
传输时可能因为网络问题导致文件内容被破坏,可以使用rdb文件的检查工具redis-check-rdb,本质还是redis-server;
rdb文件始终只有一个,生成的新rdb文件会直接覆盖旧的;
1.2 RDB自动触发
虽然这些数据都可以自由修改,但是需要注意:生成快照是一个开销很大的事情,避免频繁生成;但执行频率不高的话,数据不够及时 -> AOF解决;
1.3 RDB手动触发
1.手动执行 save & bgsave 触发生成一次快照
2.插入新的key,不手动执行bgsave
redis自动触发:
1)配置文件,指定时间修改指定次;
2)shutdown命令关闭redis-server;或(service redis-server stop);
3)redis进行主从复制时,主节点也会自动生成rdb快照,然后把rdb快照内容给从节点;
3.bgsave操作,如何观察?
数据少时,观察子进程是很难的,可以通过对比rdb文件前后的inode来判断是否进行(stat命令);4.如果故意把rdb文件改坏了,怎么办?
1)在末尾追加新行
依旧可以再次启动,key没有收到影响;
2)在中间进行修改通过查看日志文件来观察问题:
启动redis-server前应先通过redis-check-rdb来检查rdb文件是否能正常读取;
2.AOF(Append Only File)
2.1 AOF简介
AOF类似于mysql的binlog,把用户的操作都记录到文件中;
redis重新启动,读取aof文件,恢复数据;
与rdb冲突?不冲突,当aof开启时,启动时就不再读取rdb文件内容了,只读取aof文件;
aof默认关闭,需要修改配置文件打开;默认存放路径也是:/var/lib/redis,和rdb相同,可配置;
AOF是一个文本文件,每次进行的操作都会记录到文本文件,通过一些特殊符号,对命令细节做出区分;
Redis写aof文件对于处理命令线程并没有性能消耗;
1.AOF机制并非是直接让工作线程把数据写入到硬盘,而是先写入一个内存的缓冲区,积累到一定量后,在写入到文件中;
2.硬盘随机写入,速度较慢;顺序写入,文件结尾追加,速度快;
内存缓冲区存在的问题:断电就没了,因此需要做出一些取舍,在刷新频率和性能之间找平衡;
always:一写入缓冲区就刷新到文件中;
everysec:每秒刷;
no:由操作系统决定;潜在问题:AOF文件一直追加,体积会越来越大,里面会包含很多冗余的操作,导致redis服务器启动变慢;
解决:redis存在AOF文件重写机制,重写后可以达到文件瘦身效果,启动速度变快(只关注结果);
2.2 AOF重写机制
**重写过程:执行bgrewriteaof命令,父进程创建子进程;
子进程视角:子进程执行重写操作(本质也是一次生成快照行为)生成aof文件,执行完之后信号通知父进程;
父进程视角:父进程fork后,**主进程 fork 之后,继续响应其他命令。所有修改操作写入AOF 缓冲区并根据 appendfsync 策 **略同步到硬盘,保证旧 AOF 文件机制正确。****将接受到的命令操作既写到aof_buf中,又写到aof_rewrite_buf中;**当收到子进程退出信号时,父进程把aof_rewrite_buf内容追加写入到aof文件末尾,覆盖旧的aof文件;最终aof文件内容:子进程重写的快照 + 父进程追加的aof_rewrite_buf内容(混合持久化)
细节点:为什么要有两个缓冲区?
旧的AOF文件也需要保证机制正确,新的需要另通过 aof_rewrite_buf;如果执行bgrewriteaof时,redis已经在执行aof重写了,则直接返回;
如果执行bgrewriteaof时,redis已经在执行rdb快照生成,会等rdb执行完后,再执行aof重写;
aof混合持久化:


















