教你怎么用一篇文章彻底看懂Redis的持久化
mhr18 2024-10-23 11:34 31 浏览 0 评论
为什么需要持久化
很简单,因为 Redis 是基于内存的。数据如果不进行持久化,当服务器重启或者宕机的时候数据是无法恢复的,所以为了保证数据的安全性,我们需要将内存中的数据持久化到磁盘中。
Redis的持久化
Redis 提供了两种持久化的方式,分别是 RDB 和 AOF。
- RDB : Redis的默认持久化方式,是基于 快照 来实现的,当符合一定条件的时候 Redis 会自动将内存中的数据进行快照然后持久化到磁盘中。
- AOF : Redis默认没有开启 AOF 持久化,需要在配置文件中设置 appendonly true 开启。它存储的是 Redis 的 顺序指令序列 。
RDB方式的持久化
save 阻塞方式
在 Redis 中有一个命令可以触发 RDB 持久化,但是这个操作会阻塞 Redis。
这个命令是 save,我们都知道 Redis 是单线程的,如果持久化进行 特殊的处理 的话,那么就会阻塞其他命令导致 Redis 短时间内不可用,如果 RDB 文件很大,那么刷盘操作将会数十秒,严重影响可用性,所以我们一般都不会使用 save 命令。
bgsave 后台方式
bgsave 顾名思义,就是 后台进行保存 。当执行这条命令的时候 Redis 就会进行一些 特殊处理 。
什么特殊处理呢?
首先 Redis 的主进程会调用 glibc 的函数 fork 产生一个子进程,此时会将文件 持久化全部交给子进程去处理,那么这时父进程就可以继续处理用户的请求了(bgsave执行之后直接会返回)。当然,在主进程进行 fork 操作的时候可能也会对用户请求命令 产生短暂的阻塞 。
凡事有利必有弊,你看 bgsave 这么好,难道没有缺点么? 答案是有的,在哪呢?我们先来了解一下 COW 机制吧。
COW
COW (copy on write),也就是 写时复制 。我们知道 RDB 持久化需要遍历内存中的数据,就像下面那张图一样。
因为我们需要的是在子进程产生的那一瞬间的数据(快照),如果此时因为用户请求在主进程修改了内存中的数据,那么子进程遍历的内存就会被更改,这个时候就不是快照数据了。
所以这里就使用了产生快照的一种机制—— COW 。我们知道上面的数据段其实由很多操作系统的页组合而成的。COW 其实就是在主进程需要修改内存中的数据的时候,首先将需要修改的数据所在的页进行复制,然后再复制的页面上进行修改。当进行页的复制的时候就会占用额外的内存,这也是 bgsave 占用内存比 save 多的原因,但是不用过分担心,因为再保存期间不会出现大量的用户请求来修改数据,额外使用的内存也不会很多。
自动触发RDB
在 Redis 中会有几种情况下进行 RDB 的持久化,所以即使你在配置文件中关闭了 RDB ,Redis 还是会进行 RDB 的持久化。
- 满足条件时 在 Redis 的配置文件中有这么三条配置。
save 900 1 save 300 10 save 60 10000
这其实就是 RDB 中默认开启的原因,它的格式是这样的 save seconds changeTimes,save 后面的第一个数字是时间,第二个数字是修改次数,这三条配置的意思就是 在900秒内进行了1次修改或者在300秒内进行了10次修改或者在60秒内进行了10000次修改 会进行 RDB 的自动持久化。
- shutdown 当 Redis 正常关闭的时候会进行 RDB 持久化。
- flushall 会产生一个空的 RDB 文件
- 主从复制进行全量复制的时候(目前做了解就行,我在后面的文章会讲到 Redis 集群)
RDB的优点
- RDB 文件,其中做了些压缩,存储的是数据,可以快速的进行灾难恢复。
- 适合做冷备。
RDB的缺点
- 容易丢失数据,因为 RDB 需要遍历整个内存中的所有数据,所以进行一次 RDB 操作是一个费事费力的操作,为了保证 Redis 的高性能,你需要尽量减少 RDB 的持久化,所以你可能会丢失一段时间的数据。
AOF方式的持久化
默认情况下 Redis 是没有开启 AOF 持久化的,你需要在配置文件中进行相应的配置。
appendonly yes # 默认为no这里设置yes开启 dir ./ # aof文件目录 appendfilename "appendonly-6379.aof" #aof文件名
开启 AOF 持久化之后,Redis 会根据 AOF 持久化策略 来进行相应的持久化操作,具体配置是在 appendfsync 配置。
# appendfsync always 每次进行修改操作就进行写盘 appendfsync everysec 每秒进行一些写盘 # appendfsync no 从不
Redis一共提供了三个参数,一般考虑设置 everysec 每秒写盘,这样既能少影响效率也能减少数据丢失量。
AOF原理
AOF 日志中存放的是对于 Redis 的操作指令,有了 AOF 日志我们就可以使用它进行对 Redis 的重放。
比如此时我们 AOF 日志中记录了 set hello world 和 sadd userset FancisQ 这两条命令,我们就可以对一个空的 Redis 实例进行此 AOF 文件的重放,最终这个空的 Redis 就有了上面两条记录。
你可能会发现 Redis 中的这两个持久化方式很像 MySQL 中的 bin log 和 redo log,但是你需要注意的是 Redis 中的 AOF 是先执行命令再存日志的。这和 MySQL 中的 WAL 机制截然相反。
为什么呢? 我觉得有两点。
- Redis 是弱事务的,我们不需要保证数据的强一致。在 MySQL 中我们使用了 redo log 两阶段提交 来保证了 save-crash 能力,而在 Redis 中我们显然不需要这么做,假设这条命令执行完之后还没来得及写日志就宕机了,那就没了,因为弱事务,我们大可不必保证数据必须存在。
- 为了避免错误指令的日志存储,如果先写日志也就意味着我们一开始没有做相应的 逻辑处理和参数校验 ,所以这样会 先记录到很多错误指令 ,但是我们知道 AOF 文件是需要 瘦身 的,这些错误指令会给 AOF 瘦身带来很多麻烦。
AOF重写
上面提到的 瘦身 其实就是 AOF重写 ,我们知道 AOF 文件中存储的是指令顺序,当 Redis 长时间运行时会产生很多指令。
比如 set a b,set a c,set a d.....
其实上面三条就是对 key 为 a 的数据进行操作了,在 RDB 中它可能只存了 a = d ,但是因为 AOF 的指令机制,它必须存在三条,但前面的是无意义的,这样会浪费很多空间并且给 AOF 重放带来麻烦。
所以 Redis 会在 AOF文件过大(符合某种条件)的时候进行自动的 AOF 重写。对应的在配置文件中有这样两条配置。
# 下面两条需要同时满足 # 表示当前 aof 文件超过上次 aof文件大小的百分之多少时会进行重写,如果没有重写过则以启动时的大小为标准 auto-aof-rewrite-percentage 100 # 文件大于多少的时候进行重写 auto-aof-rewrite-min-size 64mb
那么,AOF 是如何重写的呢?
bgrewriteaof
这是一条 AOF 重写命令(上述的重写过程其实就是 bgrewriteaof),和 bgsave 一样,Redis 也是会 fork 一个子进程,让子进程去负责 AOF 文件的重写。大致流程如下:
AOF的优缺点
- 缺点: 在同等数据量的情况下,AOF 文件的大小要比 RDB 文件大得多,如果使用它进行内存状态恢复需要花费很长时间。
- 优点: 持久化快,能减少数据丢失的量,在配置 everysec 的情况下最多只会丢失秒级的数据。
Redis混合持久化
在 Redis 4.0之前,我们一般会开启 AOF 然后再需要恢复内存状态的时候弃用 AOF日志重放 ( 如果使用RDB的话会丢失大量数据 )。但如果 Redis 实例很大,AOF 文件也很大的时候会导致 Redis 重启非常慢。
为了解决这个问题,在 Redis 4.0之后我们可以将 RDB文件和 AOF增量日志存储在一起。如果这个时候我们进行内存状态恢复可以先使用前面的 RDB 部分,然后再使用 RDB 持久化之后产生的增量AOF日志 来进行内存状态恢复以减少时间。
如何选择 RDB 和 AOF
- 一般来说如果对数据的安全性还是有一定要求的话,应该同时使用两种持久化功能。
- 如果可以承受分钟级别的数据丢失可以仅仅使用 RDB。
- AOF 尽量使用 everysec 配置,既能保证数据安全又能保证性能效率。
- RDB 下关闭 save seconds changeTimes 这个自动持久化机制,或者合理使用参数。
分享思维导图
最后
如果本文章对你看完之后有所帮助,帮忙关注转发一下,谢谢
喜欢更多的技术文,面试文、可以关注我的公众号:java小瓜哥的分享平台,我平时整理的文章和资料全放在里面了。谢谢!
相关推荐
- 订单超时自动取消业务的 N 种实现方案,从原理到落地全解析
-
在分布式系统架构中,订单超时自动取消机制是保障业务一致性的关键组件。某电商平台曾因超时处理机制缺陷导致日均3000+订单库存锁定异常,直接损失超50万元/天。本文将从技术原理、实现细节、...
- 使用Spring Boot 3开发时,如何选择合适的分布式技术?
-
作为互联网大厂的后端开发人员,当你满怀期待地用上SpringBoot3,准备在项目中大显身手时,却发现一个棘手的问题摆在面前:面对众多分布式技术,究竟该如何选择,才能让SpringBoot...
- 数据库内存爆满怎么办?99%的程序员都踩过这个坑!
-
你的数据库是不是又双叒叕内存爆满了?!服务器监控一片红色警告,老板在群里@所有人,运维同事的电话打爆了手机...这种场景是不是特别熟悉?别慌!作为一个在数据库优化这条路上摸爬滚打了10年的老司机,今天...
- springboot利用Redisson 实现缓存与数据库双写不一致问题
-
使用了Redisson来操作Redis分布式锁,主要功能是从缓存和数据库中获取商品信息,以下是针对并发时更新缓存和数据库带来不一致问题的解决方案1.基于读写锁和删除缓存策略在并发更新场景下,...
- 外贸独立站数据库炸了?对象缓存让你起死回生
-
上周黑五,一个客户眼睁睁看着服务器CPU飙到100%——每次页面加载要查87次数据库。这让我想起2024年Pantheon的测试:Redis缓存能把WooCommerce查询速度提升20倍。跨境电商最...
- 手把手教你在 Spring Boot3 里纯编码实现自定义分布式锁
-
为什么要自己实现分布式锁?你是不是早就受够了引入各种第三方依赖时的繁琐?尤其是分布式锁这块,每次集成Redisson或者Zookeeper,都得额外维护一堆配置,有时候还会因为版本兼容问题头疼半...
- 如何设计一个支持百万级实时数据推送的WebSocket集群架构?
-
面试解答:要设计一个支持百万级实时数据推送的WebSocket集群架构,需从**连接管理、负载均衡、水平扩展、容灾恢复**四个维度切入:连接层设计-**长连接优化**:采用Netty或Und...
- Redis数据结构总结——面试最常问到的知识点
-
Redis作为主流的nosql存储,面试时经常会问到。其主要场景是用作缓存,分布式锁,分布式session,消息队列,发布订阅等等。其存储结构主要有String,List,Set,Hash,Sort...
- skynet服务的缺陷 lua死循环
-
服务端高级架构—云风的skynet这边有一个关于云风skynet的视频推荐给大家观看点击就可以观看了!skynet是一套多人在线游戏的轻量级服务端框架,使用C+Lua开发。skynet的显著优点是,...
- 七年Java开发的一路辛酸史:分享面试京东、阿里、美团后的心得
-
前言我觉得有一个能够找一份大厂的offer的想法,这是很正常的,这并不是我们的饭后谈资而是每个技术人的追求。像阿里、腾讯、美团、字节跳动、京东等等的技术氛围与技术规范度还是要明显优于一些创业型公司...
- mysql mogodb es redis数据库之间的区别
-
1.MySQL应用场景概念:关系型数据库,基于关系模型,使用表和行存储数据。优点:支持ACID事务,数据具有很高的一致性和完整性。缺点:垂直扩展能力有限,需要分库分表等方式扩展。对于复杂的查询和大量的...
- redis,memcached,nginx网络组件
-
1.理解阻塞io,非阻塞io,同步io,异步io的区别2.理解BIO和AIO的区别io多路复用只负责io检测,不负责io操作阻塞io中的write,能写多少是多少,只要写成功就返回,譬如准备写500字...
- SpringBoot+Vue+Redis实现验证码功能
-
一个小时只允许发三次验证码。一次验证码有效期二分钟。SpringBoot整合Redis...
- AWS MemoryDB 可观测最佳实践
-
AWSMemoryDB介绍AmazonMemoryDB是一种完全托管的、内存中数据存储服务,专为需要极低延迟和高吞吐量的应用程序而设计。它与Redis和Memcached相似,但具有更...
- 从0构建大型AI推荐系统:实时化引擎从工具到生态的演进
-
在AI浪潮席卷各行各业的今天,推荐系统正从幕后走向前台,成为用户体验的核心驱动力。本文将带你深入探索一个大型AI推荐系统从零起步的全过程,揭示实时化引擎如何从单一工具演进为复杂生态的关键路径。无论你是...
你 发表评论:
欢迎- 一周热门
-
-
Redis客户端 Jedis 与 Lettuce
-
高并发架构系列:Redis并发竞争key的解决方案详解
-
redis如何防止并发(redis如何防止高并发)
-
Java SE Development Kit 8u441下载地址【windows版本】
-
开源推荐:如何实现的一个高性能 Redis 服务器
-
redis安装与调优部署文档(WinServer)
-
Redis 入门 - 安装最全讲解(Windows、Linux、Docker)
-
一文带你了解 Redis 的发布与订阅的底层原理
-
Redis如何应对并发访问(redis控制并发量)
-
Oracle如何创建用户,表空间(oracle19c创建表空间用户)
-
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle主从同步 (56)
- oracle 乐观锁 (53)
- redis 命令 (83)
- php redis (97)
- redis 存储 (67)
- redis 锁 (74)
- 启动 redis (73)
- redis 时间 (60)
- redis 删除 (69)
- redis内存 (64)
- redis并发 (53)
- redis 主从 (71)
- redis同步 (53)
- redis结构 (53)
- redis 订阅 (54)
- redis 登录 (62)
- redis 面试 (58)
- redis问题 (54)
- 阿里 redis (67)
- redis的缓存 (57)
- lua redis (59)
- redis 连接池 (64)