redis rdb aof区别_Redis(三):持久化RDB,fork.copyonwrite,AOF,RDBamp;AOF混合使用

Redis的数据全部在内存里,如果突然宕机,数据就会全部丢失,因此必须有一种机制来保证Redis的数据不会因为故障而丢失,这种机制就是Redis的持久化机制。

Redis的持久化有两种,第一种是快照,第二种是AOF日志。快照是一次性全量备份,AOF日志是连续的增量备份。

第一种快照是内存数据的二进制序列化形式,在存储上非常紧凑,而第二种AOF日志记录的是内存数据修改的指令记录文本。

AOF日志在长期的运行过程中会变得无比庞大,数据库重启时需要加载AOF日志进行指令重放,这个时间就会很漫长,所以需要定期进行AOF重写,给AOF日志瘦身。


快照(RDB)的原理:

Redis是单线程程序,这个线程要同时负责:

1、多个客户端socket的并发读写操作
2、内存数据结构的逻辑重写

在服务线上请求的同时,Redis还需要进行内存快照,内存快照要求Redis必须进行文件io操作,可是文件io操作不能使用多路复用的API。

这就意味着单线程在服务器上请求的同时,还要进行文件io操作,而文件io操作会严重拖累服务器的性能。

另外,为了不阻塞线上的业务,Redis需要一边持久化,一边相应客户端的请求。持久化的同时,内存数据结构还在变化,比如一个大型的hash字典正在持久化的时候,这时一个请求过来把它给删掉了,或者修改了,可是还没持久化完毕,这怎么办?Redis使用操作系统的多进程COW(Copy on Write)机制来实现快照持久化


Fork多进程

Redis在持久化的时候会调用glicb的函数fork产生一个子进程,快照持久化完全交给子进程来处理,父进程继续处理客户端业务请求。子进程刚刚产生的时候和父进程共享内存里的代码段和数据段。

子进程做数据持久化的时候,不会修改现有内存数据结构,它只是对数据结构进行遍历读取,然后序列化写到磁盘上。

但是父进程不一样,必须持续服务客户端的请求,然后对内存数据结构进行不断的修改。这个时候就会使用OS的COW机制来进行数据段页面的分离。

9880801c55511485ec85cf27a1adcdb9.png

如上图所示,数据段是由很多操作系统的页面组合而成,当父进程对其中一个页面的数据进行修改时,会将被共享的页面复制一份分离出来,然后对复制的这个页面进行修改。这时子进程相应的页面是没有变化的,还是进程产生时那一瞬间的数据。

随着父进程修改操作的持续进行,越来越多的共享页面被分离出来,内存就会持续增长,但是也不会超过原有数据的2倍大小。另外Redis实例里的冷数据占的比例往往是比较高的,所以很少会出现所有的页面都被分离的情况,被分离的往往只有其中一部分页面。每个页面的大小只有4KB,一个Redis实例里面一般都会有成千上万个页面。

子进程因为数据没有变化,它能看到的内存里的数据在进程产生的那一瞬间就凝固了,再也不会发生改变。这也是为何Redis的持久化叫做“快照”的原因了。接下来子进程就可以安心的遍历数据,进行序列化写到磁盘中了。

那现在就有一个问题了,父进程如果占了10G,那么子进程也占10G,redis的空间够不够呢?持久化的时候速度快不快呢?其实父进程和子进程只保存了物理机的内存的地址,两份地址而已,指向的都是内存。所就不存在两个都占10G了。而父进程和子进程是通过fork()出来的,还有就是子进程也不是一下就创建出来,其中的COW是copy on write,意思是写的时候才复制地址。创建子进程并不发生复制,玩的是指针。

例如看一下fork :

输入 man 2 fork 命令

e04e661eeaca4af3405cf655626fe7ac.png

然后输入/copy

279ba0f9216a5a7f59e214166820e2d8.png

c5b8e229005641664ac621fb00bbc4c1.png

NOTES

Under Linux, fork() is implemented using copy-on-write pages, so the only

penalty that it incurs is the time and memory required to duplicate the parent’s

page tables, and to create a unique task structure for the child.

Since version 2.3.3, rather than invoking the kernel’s fork() system call, the

glibc fork() wrapper that is provided as part of the NPTL threading implementa-

tion invokes clone(2) with flags that provide the same effect as the traditional

system call. The glibc wrapper invokes any fork handlers that have been estab-

lished using pthread_atfork(3).

在Linux下,fork()是使用写时复制的页面实现的,因此它带来的唯一损失是复制父页面表和为子页面创建唯一的任务结构所需的时间和内存。自从2.3.3版本以来,作为NPTL线程实现一部分提供的glibc fork()包装器没有调用内核的fork()系统调用,而是使用提供与传统系统调用相同效果的标志调用clone(2)。glibc包装器调用使用pthread_atfork(3)建立的任何fork处理程序。

0a0000184f70b4a3f9050578c854e225.png

就是父进程进行修改的时候,会新创建一个,然后指向,而子进程还是指向原来的。

fork是系统调用,copy on write是内核机制。
redis调用fork()优点是速度快,占用空间小。

3193603c9b8dee796870e0e524f06a33.png
关机维护的时候,用save命令,其余的一般都是bgsave

5c92bfcfa9f89eaa82e27377677419cd.png

f5c6ef6e61b8648b18146f3ec336a660.png

达到60秒了 操作数达到10000,满足其中一个,就会写rdb。依次类推,如果到900秒了,操作数达到1笔的时候,满足其中一个,就会写RDB。

Redis默认是开启RDB的,如果想关闭,那么就把下图中这个删除,或者 save ""

d1575dc2770de5e567d82249049a1105.png

那么持久化的RDB文件存储在哪呢?继续往下翻:

82e0f3205a9d76e9e4e5a8559f60ca68.png

916b786824a7886470ba880dba6ffb0b.png

RDB的优缺点:

优点:1,压缩后的二进制文件,适用于备份、全量复制,用于灾难恢复

2,加载RDB恢复数据远快于AOF方式

缺点:1,无法做到实时持久化,每次都要创建子进程,频繁操作成本过高

2,保存后的二进制文件,存在老版本不兼容新版本rdb文件的问题

3,不支持拉链,只有一个dump.rdb

4,丢失数据相对较多,窗口数据容易丢失,8点做了一个rdb,假设9点又要做一个rdb,此时断电了,那么就丢了一个小时的数据。这是全量备份技术的通用的缺点。

以上是RDB。


针对RDB不适合实时持久化,redis提供了AOF持久化方式来解决

AOF(append only file )(只会向文件追加)AOF日志存储的是Redis服务器的顺序指令序列,AOF日志只记录对内存进行修改的指令记录,假设AOF日志记录了自Redis实例创建以来所有的修改性指令序列,那么就可以通过对一个空的Redis实例顺序执行所有的指令--也就是“重放”,来恢复Redis当前实例的内存数据结构的状态。

Redis会在收到客户端修改指令后,进行参数校验、逻辑处理,如果没问题,就立即将该指令文本存储到AOF日志中,也就是说,先执行指令才将日志存盘。这点不同于hbase等存储引擎,他们都是先存储日志再做逻辑处理的。

Redis在长期运行的过程中,AOF日志会越来越长,如果实例宕机重启,重放整个AOF日志会非常耗时,导致Redis长时间无法对外提供服务,所以需要对AOF日志瘦身。

AOF重写:

Redis 提供了 bgrewriteaof 指令用于对AOF日志进行瘦身,原理是开辟一个子进程对内存进行遍历,转换成一系列Redis的操作指令,序列化到一个新的AOF日志文件中。序列化完毕后再将操作期间发生增量AOF日志追加到这个新的AOF日志文件中,追加完毕后就立即替代旧的AOF日志文件了,瘦身工作就完成了。而重写的意义是以后加载速度变快,减小AOF体积,比如set k1 a set k1 b set k1 c,就会在aof文件中出现这些记录,而此时k1对应的value是C,a和b是没用的,经过bgrewriteaof命令后,aof文件中将不再有a和b的影子,就只保留了k1 c。

fsync:

AOF日志是以文件的形式存在的,当程序对AOF日志文件进行写操作时,实际上是将内容写到了内核为文件描述符(File Descriptors ,简称fd ,很多fd就是 fds)分配到一个内存缓冲中,然后内核会异步将脏数据刷回到磁盘。这就意味着如果突然宕机,AOF日志内容可能还没来得及完全刷到磁盘中,这个时候就会出现日志丢失,这怎么办?不急,Linux的glibc提供了 fsync(int fd)函数可以将指定文件的内容强制从内核缓存刷到磁盘。只要Redis进程实时调用fsync函数就可以保证AOF日志不丢失。但是fsync是磁盘io操作,很慢,如果Redis执行一条指令就要 fsync 一次,那么Redis高性能的地位就不保了。所以在生产环境的服务器中,Redis通常是每隔1s左右执行一次 fsync 操作,这个1s周期是可以配置的。这是在数据安全性和性能之间做的一个折中,在保持高性能的同时,尽可能是数据少丢失。

在Redis的主节点不会进行持久化操作,因为无论是AOF还是RDB都比较耗资源,持久化操作主要在从节点进行。从节点是备份节点,没有来自客户端请求的压力,它的操作系统资源往往比较充沛。但是如果出现网络分区,从节点长期连不上主节点,就会出现数据不一致的问题,特别是在网络分区出现的情况下,主节点一旦不小心宕机了,那么数据就会丢失,所以在生产环境下要做好实时监控工作,保证网络畅通或者能快速修复。另外还应该再增加一个从节点以降低网络分区的概率,只要有一个从节点数据同步正常,数据也就不会轻易丢失。

假设AOF文件是10T,那么恢复的时候不会内存溢出,因为只要写写写直到AOF文件成了10T,但凡能写到10个T,那肯定没有内存溢出。所以恢复的时候也不会内存溢出。如果要溢出的话,那么早就溢出了,还能把AOF文件写到10个T么?

下来说AOF的配置:

4d01890629c58244efe481ca49670db0.png

vi 6379.conf, 不是vim 用 vi 打开 上面写错了。

540f79c83a58f4272a06cf8f28976e6a.png

ed9fd9a01c1301f7f990fdd00aa124bf.png
总是,每秒,从不。红框中的,fsync上面说过了

Redis4.0混合持久化:

重启Redis时,很少使用rdb的方式恢复内存状态,因为rdb会丢失大量数据。通常使用AOF日志重放,但是重放AOF日志相对于使用rdb来说慢很多,这样在Redis实例很大的情况下,启动需要花很长的时间。

Redis4.0带来了一个新的持久化选项--混合持久化。将rdb的内容和增量的AOF日志文件存在一起。这里的AOF不再是全量的日志,而是自持久化开始到持久化结束的这段时间发生的增量AOF日志,通常这部分AOF日志很小。一定是重写之后才开始混合,比如开启了混合持久化后,set k1 v1 set k1 v2 等等 一定是输入 bgrewriteaof 命令后,前面的一系列操作就变成了 RDB形式,保存在aof文件中,后续继续set k3 v3 的时候,是以明文的形式追加到aof文件中

于是,在Redis重启的时候,可以先加载rdb的内容,然后再重放增量AOF日志,就可以完全替代之前的AOF全量文件重放,重启效率得到大幅提升。


下来演示一下redis持久化

5a66ae70044f7af692fa40023f43b3d6.png

87e143cc884421588680720e0047e86e.png

下来改配置文件:来验证rdb和aof是什么概念

vi /etc/redis/6379.conf

1c6ecbf52a81a333ab3409b6f9ca4f73.png

8f65019256c3ab4139c173cca2e54770.png

把daemonize yes改成daemonize no ,表示不让redis变成后台服务进程运行,成为前台阻塞的运行。

8f6bb07c2bdda7232ac83cae31e3e021.png

打开AOF持久化,因为RDB是默认开启的不用管

d56d9c73b92eb53c86a5b719db1eae61.png
原来是no,改成yes

然后把混合持久化关闭

5f2596e5be26e374afbe030a24e95043.png

现在准备工作已经做好了,打开了aof,打开了rdb(默认开启),关闭了混合持久化。

我现在是在root根目录:

d52d45742effb83092899bfe5ddfd7cd.png

然后把1号shell窗口切换到etc下的redis目录:

e08c04975ba68fe8820ac5af18ed845c.png

然后切换到2号shell窗口:

d7f5a7948e1266b4b6fe821297e6bf08.png

80b350d7405d1c5aff9631282c672f91.png

然后切回到1号shell窗口,启动redis

cb5251ab472bc4bd972f99e7e660ef6c.png

然后切回到2号shell窗口,LL看一下

2c1a07e62301521e2ccc828d47066ae8.png

然后 vi appendonly.aof,发现什么都没有记录

35a9ffe42ddd6683fd22e29883f14d99.png

然后在3号shell打开 redis 6379 客户端

cecb8bb0e1fb437ddbb1d4399c37ba48.png

然后设置一个kv。set k1 hello

86ca9d16db8713e6802cb7871e70efab.png

然后切回到2号shell。LL看一下,因为不满足rdb的那三个条件

d1575dc2770de5e567d82249049a1105.png

所以可以看到还是只落了一个aof文件

8b34370b23697a122f62d404aa84de3f.png

打开这个aof文件看一下

e8665c3e75e4fe12fa5ed95c63c449ce.png

*2代表:两个元素组成 一个是 select 另一个是 0号库

92bd750fd5eac2acfc3ae2de62921212.png

238b64c8942bd76aaeaf82cfe3675c20.png

然后在3号shell 继续输入 set k2 xxoo

d749b697d0fe33823c6acc63b36b23c0.png

然后切换到2号shell 查看 aof文件:

39b05745bb40169e1f7a0b7c4dcd3c42.png

然后想一下 把这两笔数据 弄到rdb里面去。在3号shell 输入 bgsave

06a9bc550cb26ce409a76c6ecab75e63.png

然后在2号shell查看:

4c5c6b2c673abc3b794a58c333386856.png

然后1号shell窗口 会发生

6a5b1e72dae510727e4c4129c7b180c2.png

然后切换到2号shell,打开这个dump.rdb

dc10d6727d7a4673a241c8d967ae666a.png

16b68e92677e93885bac98477953ccb6.png

下来看一下 aof 的重写功能:

8a541a8b38aec851f3e0517af2874b6f.png

那么aof文件会相应的增长很多对k1的操作:

54c86667659e01434f97773ab81734b7.png

那现在k1的最终value是c,所以以上k1之前的value值都是垃圾。所以给aof文件瘦身一下:瘦身前是170字节

17a62542789b971192f6fdc0bebb1a09.png

然后在3号shell 窗口 :输入bgrewriteaof

8845478902668bb87d17307076590aca.png

然后在2号shell 看一下 目前 aof的大小 :

50351d6dc7d818050537ce711bedda27.png

然后打开aof文件:

c23d67183ed31ceadac5d45721cd92f1.png

然后在1号shell 中 ctrl +c 结束:

249a6a834736cf8fd366ddba66c594c5.png

把3号shell的客户端 也退出去 exit,把2号的aof和rdb文件也全部删除 rm -fr ./*

然后切到1号shell,改配置:

25537752383dafa9dc09d34afafae3e7.png

开启混合持久化:

7b2ed906be4fd3692f6a1250af1205c3.png

保存后,启动redis:

f93008d5a2ca318792a46cfb92f90444.png

然后2号shell 里还是一个空的 aof,没毛病

3c8bb3818b48641531518d393ce62942.png

然后3号shell开启redis客户端 :set 两次

63a2a50f60a77fc8e94cbd3048d3ea0d.png

然后在2号shell 看一下:然并卵,不是混合持久化。

fbf72336d5cb2ac4da44c2d474865036.png

然后继续3号shell 写,写完后bgrewriteaof

12ff56fcef1d1163c6091f7579ad4cde.png

现在是混合持久化:所以查看2号shell:没有增量前是103字节

ac2a5305352b9e11d40de5e9b04c0c40.png

打开,可以看到变成了二进制的rdb了。和以前的aof文件不一样

36eb28efe86049afb23869db9972689e.png

然后继续set两条记录 3号shell:

2ae244ccb80695d5f1bc0ad193535874.png

然后转到2号shell:查看aof文件:变成104字节了。

a896cef0a23fa6568ecba093caf6c0ba.png

我不知道为什么,我打开看不到增量的内容,可能是io的延迟吧,不知道出什么bug了。

5f6df881744058551d57e7ad833f72a9.png

这下能看了:

cf72151b53efc051fe78d7a6ec415fa4.png

786e844eadde3c519c013ccb5e66b3f9.png

40e40c8497b758dc4659f5601f45ec6e.png

dump.rdb

048e592f1c0cc9137cd76919d6b7f95a.png

appendonly.aof

a23061db3865df4ddd1cab91d0f9d83f.png

appendonly yes (默认不开启,为no)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/512590.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

浅谈 Linux 高负载的系统化分析

简介: 浅谈 Linux 高负载的系统化分析,阿里云系统组工程师杨勇通过对线上各种问题的系统化分析。 讲解 Linux Load 高如何排查的话题属于老生常谈了,但多数文章只是聚焦了几个点,缺少整体排查思路的介绍。所谓 “授人以鱼不如授人…

AI、元宇宙技术方兴未艾,软件测试重装上阵

Larry Bernstain 曾说过“在系统测试阶段找出并修正错误,要比开发者自己完成这一工作多付出 2 倍的努力。而当系统已经交付使用之后找出并修正错误,要比系统测试阶段多付出 9 倍的努力。” 测试用例总结,图片来源:Applause以上我们…

如何快速搭建云原生企业级数据湖架构及实践分享

简介: 众所周知,数据湖技术在大数据领域炙手可热,随着在云上的广泛部署和应用,其业务价值逐渐获得业界共识。如何快搭建数据湖架构被越来越多的企业探讨。本文主要分享快速搭建云原生企业级数据湖架构及实践分享。 王震&#xff0…

5分钟搞定AlertManager接入短信、语音等10+种通知渠道

简介: Alert Manager是开源监控系统Prometheus中用于处理告警信息的服务,通过将日志服务开放告警配置为Alert Manager中的一个Receiver,可以将Alert Manager产生的告警消息发送到日志服务。 SLS告警管理 AlertManager作为Prometheus生态系统…

c语言编程输出数组元素之和,C语言 输出一个数组中,所有元素之和为0的子序列...

本程序用到了一个时间种子,来随机产生10个整数[-5~5],函数是randData( )。还有一个计算子序列为0的函数ZeroSubarray( )。randData( )如下:int arr[10];void randData(int a[], int start, int end){srand(time(NULL));for (int i start; i …

小米百万美金大奖花落机器狗团队,5 年千亿重砸研发鼓励创新

1月4日,第三届小米百万美金技术大奖公布,CyberDog铁蛋四足仿生机器人在 68个参评项目中脱颖而出,一举获得最高奖。值得一提的是,该团队拥有两名 2020 年应届毕业生成员。 小米集团创始人、董事长兼CEO雷军在微博高兴地说道&#x…

日志审计携手DDoS防护助力云上安全

简介: 本文主要介绍日志审计结合DDoS防护保障云上业务安全的新实践。 日志审计携手DDoS防护助力云上安全 1 背景介绍 设想一下,此时你正在高速公路上开车去上班,路上还有其他汽车,总体而言,大家都按照清晰的合法速度…

MySQL 深潜 - 一文详解 MySQL Data Dictionary

简介: 在 MySQL 8.0 之前,Server 层和存储引擎(比如 InnoDB)会各自保留一份元数据(schema name, table definition 等),不仅在信息存储上有着重复冗余,而且可能存在两者之间存储的元…

中国加速计算市场第二名,宁畅正领跑“智能算力定制”赛道

构建“元宇宙”最缺什么?对此,服务器新一线厂商宁畅给出的答案是“定制化算力”。 2022年1月6日,在“创立两周年媒体会”上宁畅透露,伴随IT头部企业进入“元宇宙”赛道,以及宁畅“智定”战略推进,2021年宁…

CPU Burst有副作用吗?让数学来回答!| 龙蜥技术

简介: 使用CPU Burst的副作用是什么?是否有不适用的场景呢?戳我给你答案~ 编者按:CPU Burst 特性已合入 Linux 5.14,Anolis OS 8.2、Alibaba Cloud Linux2、Alibaba Cloud Linux3也都支持CPU Burst特性。 在系列文章的…

用了 HTTPS,没想到还是被监控了!

作者 | 轩辕之风来源 | 编程技术宇宙大家好,我是轩辕。上周,微信里有个小伙伴儿给我发来了消息:随后,我让他截了一个完整的图,我一瞅,是HTTPS啊!没用HTTP!再一瞅,是www.b…

AI让边缘更智能 边缘让AI无处不在

简介: 城市管理和城市服务逐步走向智能化,智慧化。到2019底,全国100%的副省级城市,95%以上的地级市,以及50%以上的县级市均提出建设新型智慧城市,并已经有32个主要城市成立了专门的大数据管理机构&#xff…

开源自建/托管与商业化自研 Trace,如何选择?

简介: 随着微服务架构的兴起,服务端的调用依赖愈加复杂,为了快速定位异常组件与性能瓶颈,接入分布式链路追踪 Trace 已经成为 IT 运维领域的共识。但是,开源自建、开源托管或商业化自研 Trace 产品之间到底有哪些差异&…

python 覆盖list_【Python妙招】gt;gt;gt;看腻了能不能换成别的啊……当然可以啦:)...

原文作者:站在两个世界边缘 & 小象编辑:VL今天给大家介绍几个Python里(可能没那么广为人知的)小知识,希望能给大家带来帮助,让编程更有乐趣。1.如何修改解释器提示符正常情况下,我们在终端下执行Python 命令是这样…

阿里云IoT Studio升级版新增解决方案引擎 大幅提升方案交付效率

简介: 8月25日,阿里云发布IoT Studio升级版,新增了解决方案引擎,让设备方案商复用之前搭建的解决方案模板进行简单的定制化修改,即可交付。使整个物联网解决方案的交付过程由几个月,缩短到几小时&#xff0…

如何用 Nacos 构建服务网格生态

简介: Nacos 在阿里巴巴起源于 2008 年五彩石项目(该项目完成微服务拆分和业务中台建设),成长于十年的阿里双十一峰值考验,这一阶段主要帮助业务解决微服务的扩展性和高可用问题,解决了百万实例扩展性问题&…

华为oj题目c语言,华为OJ机试题目——24点游戏算法

对于这种题用程序实现只能是穷举的思想,而做法各异,如下代码是利用符号的不断变化,利用4个数计算值,默认是4个数字a,b,c,d是按顺序计算的,即默认是加了括号的,即(((a op1 b)op2 c)op3 d)。而4个数字要组合顺…

性能提升一个数量级,大杀器来了!| 文内福利

经过多年的演进,Java语言的功能和性能都在不断地发展和提高,但是冷启动开销较大的问题长期存在,难以从根本上解决。本文先讨论冷启动问题的根本原因,然后介绍一种新近提出的彻底解决Java冷启动问题的技术方案——Java静态编译技术…

快手基于 Flink 构建实时数仓场景化实践

简介: 一文了解快手基于 Flink 构建的实时数仓架构,以及一些难题的解决方案。 本文整理自快手数据技术专家李天朔在 5 月 22 日北京站 Flink Meetup 分享的议题《快手基于 Flink 构建实时数仓场景化实践》,内容包括: 快手实时计算…

PyFlink 开发环境利器:Zeppelin Notebook

简介: 在 Zeppelin notebook 里利用 Conda 来创建 Python env 自动部署到 Yarn 集群中。 PyFlink 作为 Flink 的 Python 语言入口,其 Python 语言的确很简单易学,但是 PyFlink 的开发环境却不容易搭建,稍有不慎,PyFlin…