网站首页 > java教程 正文
前言
Redis是一款基于内存的高性能缓存中间件,所有的数据都在内存中存储,所以性能比较高(当然这只是其中一个原因)。但是如果运行Redis的节点突然宕机,或者Redis本身出现故障,那么内存中的缓存数据将全部丢失,因此我们需要一种持久化机制来保证Redis的数据不会因为意外而丢失。而Redis为我们提供了两种持久化的方式:快照(RDB文件)和追加式文件(AOF文件)。
一、RDB(Redis DataBase)
RDB持久化是在指定的时间间隔内将内存中的数据集快照写入磁盘。也是默认的持久化方式,这种方式是将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。在我们安装了Redis之后,所有的配置都是在redis.conf文件中,里面保存了RDB和AOF两种持久化机制的各种配置。当符合一定条件时Redis会自动将内存中的数据进行快照并持久化到硬盘。
1.1触发时机
我们可以通过redis.conf配置文件配置触发的条件,还可以通过指令主动触发持久化的过程。
配置文件中配置触发规则
save 900 1
save 300 10
save 60 10000
配置解释:
900秒内,如果超过1个key被修改,则发起快照保存
300秒内,如果超过10个key被修改,则发起快照保存
60秒内,如果1万个key被修改,则发起快照保存
---- 可以自己修改成合适的数值
除了通过配置文件配置触发规则,也可以通过命令主动触发。
1)save:sava指令会阻塞Redis的主线程,所以一定要谨慎使用
2)bgsave:bg其实就是 background,表示后台的,所以bgsave可以理解为后台进行持久化操作,不会阻塞Redis的主进程。当执行这个命令的时候,Redis会fork出一个子进程,子进程在后台默默运行,不会阻塞主进程,这也是Redis默认使用的方式。
3)执行flushall命令也会生成dump.rdb文件,但是里面是空的。
4)客户端执行shutdown关闭Redis时,也会触发快照。
1.2bgsave的运行原理
这种方式是Redis使用RDB快照时默认采用的持久化方式,Redis的主线程会fork出来一个子进程,被fork出来的子进程会共享主进程内的所有内存数据。当这个子进程开启之后,会开始读取主进程内的数据,并把他们写入RDB文件中。也就是持久化的操作不会影响主进程的工作,这样可以提高效率。但是还有一种情况,就是如果主进程执行写入命令时,那么这一块儿数据就会被复制一份,然后主进程去修改原来的数据 ,子进程备份复制出来的数据副本,这个地方其实利用的是写时复制的思想。
1.3优缺点分析
优点
1)父进程fork出子进程之后不需要再做任何操作,所以持久化过程不会阻塞父进程的操作。需要注意的是,fork一个子进程出来是会阻塞主进程的,如果内存中数据量比较大的时候,fork花费的时间可能会变长,这点需要注意。
2)整个Redis数据库只包含一个文件,方便进行文件备份,适合大规模的数据恢复。
缺点
1)无法保证数据的高可用性,如果Redis在下一次持久化开始之前出现故障,那么就会丢失最近一次持久化到故障发生期间的所有数据。
2)如果数据相对来说比较重要,希望将损失降到最小,则可以使用AOF方式进行持久化。
二、AOF(Append Only File)
全量备份总是耗时的,Redis为我们提供了一种更加高效的持久化方式,即AOF(appendonlyfile)。此方式工作机制很简单,Redis会将每一个收到的写命令都通过write函数追加到文件中。默认情况下Redis没有开启AOF方式的持久化。
开启AOF持久化后,每执行一条会更改Redis中的数据的命令,Redis就会将该命令写入硬盘中的AOF文件,这一过程显然会降低Redis的性能,但大部分情况下这个影响是能够接受的,另外使用较快的硬盘可以提高AOF的性能。
2.1开启方式
# 可以通过修改redis.conf配置文件中的appendonly参数开启
appendonly yes
# AOF文件的保存位置和RDB文件的位置相同,都是通过dir参数设置的。
dir ./
# 默认的文件名是appendonly.aof,可以通过appendfilename参数修改
appendfilename appendonly.aof
2.2AOF 保存模式
Redis目前支持三种AOF保存模式,它们分别是:不保存、每秒钟保存一次、每执行一个命令保存一次。
可以修改以下配置项配置AOF的保存模式。
# appendfsync always
appendfsync everyse
AOF_FSYNC_NO(不保存):在这种模式下,每次调用ushAppendOnlyFile函数,WRITE都会被执行,但SAVE会被略过。在这种模式下,SAVE只会在以下情况中被执行:1.Redis被关闭;2.AOF功能被关闭;3.系统的写缓存被刷新(可能是缓存已经被写满,或者定期保存操作被执行)。这三种情况下的SAVE操作都会引起Redis主进程阻塞。
AOF_FSYNC_EVERYSEC(每一秒钟保存一次):在这种模式中,SAVE原则上每隔一秒钟就会执行一次,因为SAVE操作是由后台子线程调用的,所以它不会引起服务器主进程阻塞。
AOF_FSYNC_ALWAYS(每执行一个命令保存一次(不推荐)):在这种模式下,每次执行完一个命令之后,WRITE和SAVE都会被执行。另外,因为SAVE是由Redis主进程执行的,所以在SAVE执行期间,主进程会被阻塞,不能接受命令请求。
AOF保存模式对性能和安全性的影响
对于三种AOF保存模式,它们对服务器主进程的阻塞情况如下:
AOF_FSYNC_NO:写入和保存都由主进程执行,两个操作都会阻塞主进程。
AOF_FSYNC_EVERYSEC:写入操作由主进程执行,阻塞主进程。保存操作由子线程执行,不直接阻塞主进程,但保存操作完成的快慢会影响写入操作的阻塞时长。
AOF_FSYNC_ALWAYS:和AOF_FSYNC_NO模式一样。
因为阻塞操作会让Redis主进程无法持续处理请求,所以一般说来,阻塞操作执行得越少,完成得越快,Redis的性能就越好。
2.3AOF重写(瘦身)
AOF 持久化是通过保存被执行的写命令来记录数据库状态的,所以AOF文件的大小随着时间的流逝一定会越来越大。影响包括但不限于:对于Redis服务器,计算机的存储压力;AOF还原出数据库状态的时间增加。
为了解决AOF文件体积膨胀的问题,Redis提供了AOF重写功能:Redis服务器可以创建一个新的AOF文件来替代现有的AOF文件,新旧两个文件所保存的数据库状态是相同的,但是新的AOF文件不会包含任何浪费空间的冗余命令,通常体积会较旧AOF文件小很多。这个操作相当于对 AOF 文件“瘦身”。在重写的时候,是根据这个键值对当前的最新状态,为它生成对应的写入命令。这样一来,一个键值对在重写日志中只用一条命令就行了,而且,在日志恢复时,只用执行这条命令,就可以直接完成这个键值对的写入了。
2.4从 RDB 持久化切换到 AOF 持久化
在 Redis 2.2 或以上版本,可以在不重启的情况下,从 RDB 切换到 AOF :
- 为最新的 dump.rdb 文件创建一个备份。
- 将备份放到一个安全的地方。
- 执行以下两条命令:
redis-cli> CONFIG SET appendonly yes
redis-cli> CONFIG SET save ""
4. 确保命令执行之后,数据库的键的数量没有改变。
5. 确保写命令会被正确地追加到 AOF 文件的末尾。
步骤 3 执行的第一条命令开启了 AOF 功能:Redis 会阻塞直到初始 AOF 文件创建完成为止, 之后 Redis 会继续处理命令请求, 并开始将写入命令追加到 AOF 文件末尾。
步骤 3 执行的第二条命令用于关闭 RDB 功能。这一步是可选的, 如果你愿意的话, 也可以同时使用 RDB 和 AOF 这两种持久化功能。
别忘了在 redis.conf 中打开 AOF 功能!否则的话, 服务器重启之后, 之前通过 CONFIG SET 设置的配置就会被遗忘, 程序会按原来的配置来启动服务器。
猜你喜欢
- 2025-05-28 学习笔记:深入浅出redis
- 2025-05-28 Vue3 + Nest 实现权限管理系统 后端篇:如何在 NestJS 中使用 redis
- 2025-05-28 Redis 中地理位置功能 Geospatial 了解一下?
- 2025-05-28 推荐几个好用Redis图形化客户端工具
- 2025-05-28 因为不会Redis的scan命令,我被开除了
- 2025-05-28 Redis中9种基本数据类型及常用操作命令和应用场景
- 2025-05-28 一连问了好几个大佬,竟然都不知道Redis为什么默认16个数据库?
- 2025-05-28 Java实现Redis发布订阅
- 2025-05-28 快!做对这 10 点,让你的 Redis 性能更上一层楼
- 2025-05-28 字节三面远程,Java+Redis+网络+数据库+算法,轻松反杀面试官?
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- java反编译工具 (77)
- java反射 (57)
- java接口 (61)
- java随机数 (63)
- java7下载 (59)
- java数据结构 (61)
- java 三目运算符 (65)
- java对象转map (63)
- Java继承 (69)
- java字符串替换 (60)
- 快速排序java (59)
- java并发编程 (58)
- java api文档 (60)
- centos安装java (57)
- java调用webservice接口 (61)
- java深拷贝 (61)
- 工厂模式java (59)
- java代理模式 (59)
- java.lang (57)
- java连接mysql数据库 (67)
- java重载 (68)
- java 循环语句 (66)
- java反序列化 (58)
- java时间函数 (60)
- java是值传递还是引用传递 (62)
本文暂时没有评论,来添加一个吧(●'◡'●)