百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

教你怎么用一篇文章彻底看懂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 机制截然相反。

为什么呢? 我觉得有两点。

  1. Redis 是弱事务的,我们不需要保证数据的强一致。在 MySQL 中我们使用了 redo log 两阶段提交 来保证了 save-crash 能力,而在 Redis 中我们显然不需要这么做,假设这条命令执行完之后还没来得及写日志就宕机了,那就没了,因为弱事务,我们大可不必保证数据必须存在。
  2. 为了避免错误指令的日志存储,如果先写日志也就意味着我们一开始没有做相应的 逻辑处理和参数校验 ,所以这样会 先记录到很多错误指令 ,但是我们知道 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推荐系统从零起步的全过程,揭示实时化引擎如何从单一工具演进为复杂生态的关键路径。无论你是...

取消回复欢迎 发表评论: