Redis持久化

88 阅读4分钟

为什么要使用Redis

  1. 性能

    我们再碰到耗时特别久、结果基本不变的SQL时,就特别适合将运行结果放入缓存,之后再去缓存读取就能够迅速响应。

  2. 并发

    在大并发的情况下,所有的请求直接访问数据库,数据库会出现连接异常。这个时候,就需要使用的的Redis的做一个缓冲操作,让请求先访问到的Redis的的,而不是直接访问数据库。

  3. 支持丰富的数据类型

    string(字符串),list(链表),set(集合),zset(sorted set - 有序集合))和Hash(哈希类型)

  4. 拥有持久化机制

    Redis拥有RDB和AOF持久化机制,即使服务器重启数据也不会丢失。

  5. 支持扩展

    Redis具有主从、集群、哨兵模式,横向扩展容易。

RDB持久化机制

RDB是通过创建快照来获得存储在内存某个时间点上的副本。Redis创建快照之后,可以对快照进行备份,也可以将快照复制到其他服务器从而创建具有相同数据的服务器副本,还可以将快照留在原地以便重启服务的时候使用。 持久化配置:

save 900 1           #在900秒(15分钟)之后,如果至少有1个key发生变化,Redis就会自动触发bgsave命令创建快照。

save 300 10          #在300秒(5分钟)之后,如果至少有10个key发生变化,Redis就会自动触发bgsave命令创建快照。

save 60 10000        #在60秒(1分钟)之后,如果至少有10000个key发生变化,Redis就会自动触发bgsave命令创建快照。

Redis提供了两个命令用来生成RDB文件:

  • save 同步操作,会阻塞Redis主线程
  • bgsave fork出一个子线程,子线程执行,不会则色Redis主线程,默认。

AOF持久化机制

AOF之持久化的方式是追加命令,开启AOF持久化后执行的每一条会更改Redis中的数据命令,Redis就会将该命令写入到AOF缓冲区,然后再写入到AOF文件中(此时还在系统内核缓冲区未同步到硬盘),最后再依据持久化方式的配置来确定何时将系统内核缓冲区的数据同步到硬盘中。

只有同步到磁盘中才算持久化保存了,否则依然存在数据丢失的风险,比如说:系统内核缓存区的数据还未同步,磁盘机器就宕机了,那这部分数据就算丢失了。

流程如下

image.png

fync策略

  • appendfsync always:主线程write操作之后,后台线程立即调用fsyn函数同步AOF文件到磁盘,fsync 完成后线程返回,这样会严重降低 Redis 的性能。
  • ppendfsync everysec:主线程调用 write 执行写操作后立即返回,由后台线程( aof_fsync 线程)每秒钟调用 fsync 函数(系统调用)同步一次 AOF 文件(write+fsyncfsync间隔为 1 秒)。
  • appendfsync no:线程调用 write 执行写操作后立即返回,让操作系统决定何时进行同步,Linux 下一般为 30 秒一次(write但不fsyncfsync 的时机由操作系统决定)。

如何选择RDB和AOF

RDB的优点

  • RDB文件存储的内容是经过压缩的二进制数据,保存着某个时间点的数据集,文件很小,适合做数据的备份,灾难恢复。AOF文件存储的是每一次写命令,类似于MYSQL的binlog日志,通常比RDB文件大很多。当AOF文件太大时,Redis会在后台自动重写AOF,新的AOF文件和原有的AOF文件所保存的数据库状态一致,但是体积更小。
  • 使用RDB文件恢复数据,直接解析还原数据就行不需要一条条的执行命令,速度非常快。
  • RDB 的数据安全性不如 AOF,没有办法实时或者秒级持久化数据。生成 RDB 文件的过程是比较繁重的, 虽然 BGSAVE 子进程写入 RDB 文件的工作不会阻塞主线程,但会对机器的 CPU 资源和内存资源产生影响,严重的情况下甚至会直接把 Redis 服务干宕机。AOF 支持秒级数据丢失(取决 fsync 策略,如果是 everysec,最多丢失 1 秒的数据),仅仅是追加命令到 AOF 文件,操作轻量。
  • RDB 文件是以特定的二进制格式保存的,并且在 Redis 版本演进中有多个版本的 RDB,所以存在老版本的 Redis 服务不兼容新版本的 RDB 格式的问题。
  • AOF 以一种易于理解和解析的格式包含所有操作的日志。你可以轻松地导出 AOF 文件进行分析,你也可以直接操作 AOF 文件来解决一些问题。比如,如果执行FLUSHALL命令意外地刷新了所有内容后,只要 AOF 文件没有被重写,删除最新命令并重启即可恢复之前的状态。