redis_持久化RDB和AOF

RDB

redis同步数据本地存储采用的是通过fork系统调用来创建父子进程,子进程来把数据从内存落到磁盘中子进程不是把所有数据从父进程在拷贝一份,使用的是指针引用,copy on write?什么意思?这句话叫做写时复制。事写的时候他就复制,换言之,创建子进程中并不发生复制,只有在父进程一方想修改数据的时候才会定向地去复制数据,这样会有一个优势,就是创建进程变快了。同时根据经验,不可能子进程或者是父进程,把所有数据都改一遍,也就是其实触发起复制的机会也不是很大,明白什么意思吧?就是整个Linux,为什么我fork这个东西,它其实要解决我车进门的速度,包括车也要出来,而且有数据导出这个事儿也不怕,就是把你这个数据要导出的变量那个值也给你,从子进程带过去。copy-on-write是机制,内核机制,然后fork是系统调用。备份数据的时候是有时点性的,8点开始备份数据,那么只会保留8点之前的数据,如果备份完毕,服务器死了,那么8点之后的数据会丢失。
在这里插入图片描述
开启RDB的方式有2种:save和bgsave,通过rdb备份有时点性;
save会阻塞进程服务,只有在断电关机和清理才会用,bgsave会通过fork创建子进程;
在redis的配置文件有关rdb的配置:
dir /var/lib/redis/6379 rdb文件所在目录;
dbfilename dump.rdb rdb文件名称;
rdb不支持拉链法,就一个rdb文件;
save “” 表示不开启rdb,

save 900 1
save 300 10
save 60 10000

比如说save你可以写条多条,然后时间肯定是越来越久,然后操作数是越来越少,这么一个规律,什么规律?比如说达到60秒了,然后你超过达到的操作数,一个是时间,一个是操作数,60秒了,或者是操作数达到个10000了,那么这两个满足其中一个,就会写RDB。如果说当60秒的时候还没有到1万刚到9,那么就进入61秒就进入300秒这个判断了。
那么你到9的时候还没到10,但如果到10了,他就开始触发了;或者到60秒的时候到9000,
那么也不触发。然后到300秒的时候,然后如果达到了9000已经大于10了,也会触发这个事
情。然后如果说你一直写很少,到900秒了,刚好一笔操作的时候,因为已经有900秒了,
到达900秒这时间点了发现你有一笔或两笔操作了,这时候得存一下,因为一笔、两笔操作
也挺值钱的,别丢了,因为时间不要太久了,一直没存过
在这里插入图片描述

AOF

aof很好理解,他的名字是Append Only File就是只会向文件追加,追加的东西就是服务器发生的写操作,redis的写操作记录到文件中,那么这个写操作记录到文件中,首先他的第一个好处就是,因为伴随着每一个写,都会有一个写的到达,这个增删改的到达都会写成文件,所以第一个好处就是,丢失数据会相对少,没错,像editlog就写日志,也像我们mySQL的binlog一样。
但是redis中 rdb和aof可以同时开启,但是注意了,但是如果开启了aof只会用aof恢复,这点很重要,他只会用它来做恢复。即便你rdb、aof都开了,rdb也会落,aof也会落。那么真正你重启服务器的时候,它只会拿aof恢复,因为aof恢复的相对的数据完整性好一些,他就不做rdb恢复了。
AOF中包含RDB全量,增 加记录新的写操作。那么这样在恢复的时候就有一个好处,因为AOF里面已经包了一个RDB了,所以你在做AOF的时候,rdb先一个做回复,先把二进制的恢复到内存,再把AOF文件往后新增的这些东西再一条一条执行,那么新增的数据相对少一些,速度相对快一些。没错,AOF是里面记录的日志,他等于要重新执行里面的命令,所以他的弊端就是慢。相对于我们的 rdb慢,但是它的优势就是丢失数据少。
同时开启RDB和AOF,8点开启备份,8点之前的RDB备份,二进制快,8点之后到备份完成用AOF,这样能最快恢复的最全。
即使运行了十年的redis做AOF恢复,只要十年间没有溢出,那么恢复就不会内存溢出,redis是内存存储的,我的aof文件可以很大,但是里边能写成功的这个指令,都是在我redis没有内存溢出之前写进去的,也就是说你无论怎么恢复,最终恢复完的都是内存,这个有限空间里边的东西,不可能说我这个redis内存溢出了,本来10个g,12个g的操作都写进去了,在里边有效地,不可能的,因为都会有一些抵消的在里边出现,前面创建,后面肯定有一个删除,删除掉之后,后边还能拿被删除空间再去创建一个新的数据,所以只要他线性执行这个文件,最终就可以恢复里面所有的一个数据,而没有溢出这个事!
在这里插入图片描述
AOF的一个天生的弊端,什么弊端?根据这个问题是不引出了一个弊端。第一个体量大,体量无限变大,无限变大是一个好事儿。但是无限变大之后会带来一个问题,就是恢复慢,他的优点是丢数据少,缺点也是很明显的。所以这时候一般在很多软件当中都会对日志下手。

redis用另外一种方式,4.0以前的和4.0以后的,那么4.0以前怎么去做?其实4.0以前就
是,它会有一个机制叫重写。其实根据刚才描述,10年就是创建k,删除k、创建k,删除
k,那么这时候这个文件里边记了10个t,最后如果是创建k,删除k没有发生,其实创建k前
面的都是没有意义的,是可以互相抵消掉的。
还有一个就是我这10年可能给一个list,先是push 1,push 1…比如push了10万个1,但
是这10万个1是push了10万次,那么每条记录里边除了1这个元素之外,还有push。那么说白了,其实完成这10万条记录,可以用一条记录,push,然后10万个1,参数push只会出1次,这个单词只会出现一次,是不是有这么一种场景,比较浪费空间,对不对?所以所谓重写就是抵消和整合命令,删除抵销的的命令,然后合并重复的,是归属于到一个key里面。
如果你对一个k创建+1,+1,+1,+1,incr把它加1,那么最后其实可以直接给他一个
incrby多少,这个加上去。这个文件在4.0以前,他的结果最终也是一个纯指令的日志文件。
那么相对于恢复的时候,成本还很高的,然后它偷偷地学习了,4.0以后,如果触发,这个
文件也开始记,但是它也是在重写的时候。
一旦重写了,比如那文件记到了几百兆了,他要重写了,他把几百兆的数据先用 rdb的
方式写到AR文件里边,也就是在重写的时候,将老的数据RDB到aof文件中,rdp其实做的就是二进制,所以等于aof文件里边会存一些二进制的、不方便阅读的那些字节,先存到aof文件里边,存完之后,然后将增量的以指令的方式 Append到AOF,也就是说间接的可以得出结论,AOF当中是包含rdb和增量日志的。
那么这时候就回到前面,是不是让aof当中是只记录增量不记录全量,那么这样得出一
个结论?他是一个混合体,AOF是一个混合题,然后利用了rdb的恢复快,利用了日志的全
量,数量保存得比较全,两个优点。是不是两个优点它用起来了?你8点触发的,那就把
8点内存里面数据写成rdb,写到aof文件里边,那么8点往后所有新的增删改就开始追记录
了,能听懂了吧?

appendonly no
no-yes 打开/关闭AOF,appendfilename “appendonly.aof” aof的名称;

 appendfsync always
 appendfsync everysec
 appendfsync no

No是redis来了一个增删改的操作,比如说有4笔写,那么他每笔会向那个buffer去写,然后no的时候就是redis不调flush,你内核什么时候满了,什么时候刷,就完全听天由命,听从内核。那么这样会一个问题,可能会丢失一个buffer大小的数据。然后always是什么意思,就是redis只要写了一个文件描述符,就把这个文件描述符写进去,然后并同时调一个flush,buffer没有满,你也给我往磁盘写,所以always一定是数据最可靠的,因为他每笔都立刻调了一个flush,顶多就是在调下来这瞬间,他没调成,断电了,那么它顶多就是丢一条。
缓冲区大小是可以调的,不会很大,4k左右,然后那么redis还有一个东西就是每秒级别,这是他默认的,什么都叫每秒级别,redis每一秒钟调一次flush,每秒钟调flush,那么每一秒钟调flush,它的丢失数据量是多少呢?有这么一种概率,第一、buffer肯定没满,比如差那么一点点他就满了,因为它一满,内核就把它刷刷了。所以从一秒开始,刚清完,到一秒的时候该刷flush了,在这一秒没到的前一秒钟,它里边占了99%的空间,差一点就开始触发。但是没触发,所以他最大丢失是,差一点点到内核buffer满,会丢这么多东西,也就接近丢一个buffer,但是这种概率太小,这毕竟是个概率。因为你redis可能写的比较快,可能1秒钟之内你有3次或4次的buffer满了,就全刷下去了。这时候可能buffer最后一次,就一秒刚你写了三条,结果该到一秒钟刷了,前面都已经触发过了,这三条还没有flush,那么丢了3条。所以每秒这种操作是折合在速度最慢的
always和速度最快的no之间的一种的,相对丢的数据量比较少。

就是no和Append Only File的时候,要不要调刷新这个操作,然后调成了no,意思?也就是如果你的redis抛出一个子进程,子进程可能是bgsave,在做着rdb或者在重写的时候,那么这时候你的父进程就不会向那个磁盘调刷新这个事。因为他认为自己的进程在对着磁盘发生一个疯狂的写,这时候自己就不能参与写,来争抢IO这个事了。当然这个时候就容易丢数据,所以这要不要开,要看你对数据的敏感性。然后再往下的配置当中,下边还有一个检查,待会我带你用它的命令查它的文件的时候再告诉你是什么意思?
最后看到沉底,装redis是5.0的版本,然后最后这个位置出现了这么一段描述,你看这个aof-use-rdb-preamble Yes,开启的。那么这个时候就是在when write的时候,注意看我上面画的一个图,在重写的时候,这很重要。如果触发重写的时候,做aof file 的时候,redis 就是先把rdb写到Aof文件里面去,让你redis 变得更快,因为你redis 如果不将rdb写的话,你曾经4.0运行的版本软件要遍历老的Aof文件,找那些可以抵消的底掉,找那些可以缩减的缩减,那是一个非常疯狂的CPU计算判定的过程。
然后如果用这种方式的话,就把 CPU判定的事减掉了,直接用内存对着磁盘的Aof文件先做一个卸数的过程,就是把内存的东西持久化,导成rdb这种二进制的写到Aof文件里边去,它为了加快这个重写的过程,然后等于你Aof文件里面包含的是rdb和Aof tail,后边是增量的,是一个混合体了。
然后我们loading redis 的时候,也就是说如果你看一个Aof文件,打开Aof文件看得时候,他最开始的时候出现了“redis”这个字符串,证明它是一个混合体文件。如果没有出现这个字符串,证明是老版本的Aof文件,可以通过这来区别。你看他默认也是开启了,因为这种方式是最好的,它利用了ADB和Aof两个优势。

修改redis的配置文件,deamonizeyes改成no ,不让他变成后台服务运行,让他可以在前台阻塞着执行。第二个,是把他的日志文件给他注掉,因为如果你上面开日志话,他会把东西记到日志里去,你把这个关了之后它会打到屏幕上,然后再往下走是 rdb我们也设置过了,就用这个来走。
appendonly改成 yes
aof-use-rdb-preamble 改成no
启动redis服务redis-server /etc/redis/6379.conf,打开一个客户端,set赋值操作,然后看AOF文件,appendonly.aof

[root@iZuf6ir4og87e245nh5ltuZ 6379]# tail -500f appendonly.aof 
*2    *表示后边有2个元素组成
$6  $表示下面有6个字符或者字节长度
SELECT   选择
$1 第一个变量
0 0号库
*3
$3
set 
$2
k1
$5
hello
*3
$3
set
$2
k2
$5
hello
*3
$3
set
$2
k3
$13
aaaaaaaaaaaaa
通过这种方式方便换行读取;
redis客户端通过bgsave保存至rdb文件,

```c
19827:M 05 Jan 2022 21:58:49.130 * Background saving started by pid 19886
19886:C 05 Jan 2022 21:58:49.132 * DB saved on disk
19886:C 05 Jan 2022 21:58:49.133 * RDB: 0 MB of memory used by copy-on-write
19827:M 05 Jan 2022 21:58:49.201 * Background saving terminated with success

当前父进程是19287?他是这个父进程的子进程19886,然后DB saved on disk存到磁盘当中去了,rdb大小是0兆, used by copy on write?
写时复制来完成的,完成了。保存到rdb,
tail -500f dump.rdb REDIS0009 redis-ver5.0.5 redis-bits󿿀򳨭e¤used-memP rdb文件的开头是不是就是redis这
个单词,因为混合体的时候开启之后,也是说这个文件当中开始的时候,肯定会
出现一个单词就是redis,但是老式的Aof文件当中是不是没有redis,

[root@iZuf6ir4og87e245nh5ltuZ 6379]# redis-check-rdb dump.rdb 
[offset 0] Checking RDB file dump.rdb
[offset 26] AUX FIELD redis-ver = '5.0.5'
[offset 40] AUX FIELD redis-bits = '64'
[offset 52] AUX FIELD ctime = '1641391129'
[offset 67] AUX FIELD used-mem = '853584'
[offset 83] AUX FIELD aof-preamble = '0'
[offset 85] Selecting DB ID 0
[offset 135] Checksum OK
[offset 135] \o/ RDB looks OK! \o/
[info] 3 keys read
[info] 0 expires
[info] 0 already expired

个redis check rdb dump.rdb 回车,然后他给你redis自己的自己命令接这个文件,告诉你,检查这个文件,它会告诉你,这里面如果犯了错误,会告诉你哪出错了

127.0.0.1:6379> set k1 a
OK
127.0.0.1:6379> set k1 b
OK
127.0.0.1:6379> set k1 c

127.0.0.1:6379> BGREWRITEAOF  异步重写仅追加文件
Background append only file rewriting started

[root@iZuf6ir4og87e245nh5ltuZ 6379]# tail -500f appendonly.aof 
*2
$6
SELECT
$1
0
*3
$3
SET
$2
k3
$13
aaaaaaaaaaaaa
*3
$3
SET
$2
k2
$5
hello
*3
$3
SET
$2
k1
$1
c

BGREWRITEAOF 命令整合重复操作,k1之前重复操作,现在只保留最终的数据;减少aof的体系,把没用的剔除掉,方便未来加载速度变快,不需要
执行那些没有意义的指令。
RDB就是二进制文件,aof就是保存的日志操作

aof-use-rdb-preamble

aof-use-rdb-preamble
开启rdb和AOF混合配置
重写AOF文件时,Redis可以使用RDB preamble
AOF 文件用于更快的重写和恢复。 当这个选项被打开时
重写后的 AOF 文件由两个不同的节组成:
[RDB文件][AOF尾]
加载Redis时识别到AOF文件以“REDIS”开头 字符串并加载带前缀的RDB文件,并继续加载AOF 尾巴。
aof-use-rdb-preamble改为yes,对k1重复设置v,然后执行重写命BGREWRITEAOF,
aof文件多了rdb的部分,以redis开头,aof现在是全量rdb和增量AOF日志记录的;
bgsave重写生成了rdb文件和aof文件一样大,aof和rdb内容一样
aof-use-rdb-preamble关闭,清理flushall,删除rdb和aof文件,set k1重复设置v,再重写,历史的日志被删除,只有最新的最终的日志,重写的细节没有了。
aof的重写也有一个自动的,他自动的有这么两个参数,一个是min-size,一个是百分比,然后你比如设置一个64兆,你就给了一个值,redis的启动之后,他会判断aof,如果达到64兆了,那么开始触发重写,重写之后有种可能就变成32兆或变成十几兆了,因为很多历史数据就被抵消掉了,对不对?能理解了吧,但是这个时候不可能说你就只给他一个条目,因为给一个条目会有一个问题,到64兆了,重写,压少了,再到64兆了,又重写,又压少了。但你的有效数据递增的,最后他就一直卡在64兆上了,对吧?一直重复这个,所以redis会有一个记忆能力,如果达到64兆了,然后剩下的值是什么意思?100% ,也就是64兆,100%,然后就触发重写,达到64兆不能重写了,开始让他变,再达到一个64兆,100%的时候,就达到180兆的时候才会触发第二次重写,然后再有一个记忆,然后这段,上面描述的时候应该他这么去说了。就在这儿。This is how it works:redis remembers the size of the aof file ofter the latest
rewrite?redis会记录他最后一次重写完它的体积大小。能理解什么意思吧?所以它需要两
个,一个是增长了多少之后,首先,如果在第一次开机的时候,他就定了64兆,到了64
兆之后他会rewrite,只要最后一次 rewrite之后,他会记住最后那个大小,然后他又增长了
100%,又开始触发了,然后记住它大小了,然后再增长了100%再去 rewrite,就是他有这么一个能力,是自动化的,在后台不用你去管,他来去维护了aof大小的问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值