Redis的高级特性

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Sugar_map/article/details/80874406

本文的核心内容:Redis的事务、Redis的发布订阅、Redis的持久化机制【RDB和AOF】


一:Redis中的事务

Redis 事务可以一次执行多个命令, 并且带有以下两个重要的保证:

1.事务是一个单独的隔离操作:事务中的所有命令都会序列化、按顺序地执行。事务在执行的过程中,不会被其他客户端发送来的命令请求所打断。

2.事务是一个原子操作:事务中的命令要么全部被执行,要么全部都不执行。

一个事务从开始到执行会经历以下三个阶段:

 开始事务

 命令入队

 执行事务

①事务的提交:

 

从输出中可以看到,当输入MULTI命令后,服务器返回OK表示事务开始成功,然后依次输入需要在本次事务中执行的所有命令,每次输入一个命令服务器并不会马上执行,而是返回”QUEUED”,这表示命令已经被服务器接受并且暂时保存起来,最后输入EXEC命令后,本次事务中的所有命令才会被依次执行,可以看到最后服务器一次性返回了三个OK,这里返回的结果与发送的命令是按顺序一一对应的,这说明这次事务中的命令全都执行成功了。

②事务的回滚

 

先输入MULTI最后输入EXEC表示中间的命令属于一个事务,不同的是中间输入的命令有一个错误(set写成了sett),这样因为有一个错误的命令导致事务中的其他命令都不执行了(通过后续的get命令可以验证)。

注意:指令语法本身没错,但适用对象有问题,Exec之后,会执行正确的语句,并跳过有不适当的语句。这个问题是调用了错误的类型,事务不回滚。

③watch命令【乐观锁】

Redis的事务中,启用的是乐观锁,只负责监控key是否被改动。如果改动回滚事务,

未改动提交事务。

 

 

unwatch

取消 WATCH 命令对所有 key 的监视。

二:订阅与发布【多对多,即时通信】

Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。Redis作为一个pub/sub server,在订阅者和发布者之间起到了消息路由的功能。订阅者可以通过subscribepsubscribe命令向redis server订阅自己感兴趣的消息类型,redis将消息类型称为通道(channel)。当发布者通过publish命令向redis server发送特定类型的消息时。订阅该消息类型的全部client都会收到此消息。这里消息的传递是多对多的。一个client可以订阅多个 channel,也可以向多个channel发送消息。

工作流程如上图:当有新消息通过 PUBLISH 命令发送给频道 channel1 时, 这个消息就会被发送给订阅它的三个客户端。

相关命令

命令

说明

subscribe

订阅给定的一个或多个频道的信息。

publish

将信息 message 发送到指定的频道 channel

psubscribe

订阅一个或多个符合给定模式的频道

punsubscribe

退订所有给定模式的频道

unsubscribe

指退订给定的频道

pubsub

    查看订阅与发布系统状态

 订阅频道与发布

三:Redis的持久化机制【RDB和AOF】

概述:Redis提供了两种不同的持久化方法来将数据存储到硬盘里面 

快照(snapshotting) 快照文件

这种方式可以将某一时刻的所有数据都写入硬盘中,当然这也是redis的默认持久化方式,保存的文件是以.rdb形式结尾的文件因此这种方式也称之为RDB快照文件持久化方式。

AOF(append only file) 追加文件

这种方式可以将所有客户端执行的写命令记录到日志文件中,保存的日志文件以.aof结尾。

RDB快照持久化【Redis默认持久化方式】

快照持久化也是redis中的默认开启的持久化方案,根据redis.conf中的配置,快照将被写入dbfilename指定的文件里面(默认写入到名为dump.rdb文件中)

 

指定dump.rdb快照文件的保存目录(默认保存在配置文件所属目录,aof日志文件默认也保存在此目录)

 

RDB持久化原理

每隔几分钟或者N次写操作后,将内存中数据以快照的方式写入到二进制文件中,默认的文件名为dump.rdb。压缩放在备份目录。当因为宕机或者 断电等原因造成redis内存数据丢失时,再将rdb快照文件中保存数据载入到内存中。

 

RDB持久化触发时机【手动/自动】

①手动触发(客户端命令bgsave或者save)  【了解即可】

save命令(不推荐使用):save操作是在主线程中保存快照,由于redis是用一个主线程来处理所有客户端请求,这种方式会阻塞所有客户端请求。

bgsave命令:当接收到客户端的bgsave命令时,redis会调用fork来创建一个子进程,父进程继续处理client请求,子进程负责将内存内容写入到临时文件。 当子进程将快照写入临时文件完毕后,用临时文件替换原来的快照文件,然后子进程退出。

②自动触发

触发条件:

 

执行机制:

如果用户在redis.conf中设置了save配置选项,redis会在save选项条件满足之后自动触发一次bgsave命令,如果设置多个save配置选,当任意一个save配置选项条件满足,redis也会触发一次bgsave命令。

注意:每次快照持久化都是将内存数据完整写入到磁盘一次,并不是增量的只同步脏数据。如果数据量大的话,而且写操作比较多,必然会引起大量的磁盘io操作,可能会严重影响性能。

缺点:

由于快照方式是在一定间隔时间做一次的,所以如果redis意外down掉的话,就会丢失最后一次快照后的所有修改。如果应用要求不能丢失任何修改的话,可以采用aof持久化方式。

AOF追加日志持久化【重点:AOF文件的重写】

AOF持久化机制默认没有开启,使用aof持久化方式时,redis会将每一个收到的写命令都通过write函数追加到文件中(默认是appendonly.aof)。当redis重启时会通过重新执行文件中保存的写命令来在内存中重建整个数据库的内容。

原理图:

 

①开启AOF持久化机制,需要修改redis.conf的配置文件

l通过修改redis.conf配置中appendonly yes来开启AOF持久化

l通过appendfilename指定日志文件名字(默认为:appendonly.aof)

l通过appendfsync指定日志记录频率

②AOF日志记录频率的选项

 

③AOF日志文件重写

aof 的方式也同时带来了另一个问题。持久化文件会变的越来越大。例如我们调用incr test命令100次,文件中必须保存全部的100条命令,其实有99条都是多余的。因为要恢复数据库的状态其实文件中保存一条set test 100就够了。为了压缩aof的持久化文件Redis提供了AOF重写机制。

aof重写是指把内存中的数据,逆化成命令,写入到.aof日志里

手动重写aof文件

客户端执行命令bgrewriteaof

自动重写aof文件

配置redis.conf

华丽的分割线------------------------------------------------------------------------------------------

AOF日志文件重写原理【重点】

redis调用fork,创建子进程。子进程根据内存中的数据库快照,往临时文件中写入重建数据库状态的命令。 父进程继续处理client请求,除了把写命令写入到原来的aof文件中。同时把收到的写命令缓存起来。这样就能保证如果子进程重写失败的话并不会出问题。当子进程把快照内容写入已命令方式写到临时文件中后,子进程发信号通知父进程。然后父进程把缓存的写命令也写入到临时文件。现在父进程可以使用临时文件替换老的aof文件,并重命名,后面收到的写命令也开始往新的aof文件中追加。

注意:重写aof文件的操作,并没有读取旧的aof文件,而是将整个内存中的数据库内容用命令的方式重写了一个新的aof文件,这点和快照有点类似。

常见问题

问:恢复时rdb和aof哪个恢复数据快

答:rdb快,因为其是数据的内存映射二进制文件,直接载入到内存,而aof是命令,需要逐条执行

问:如果rdb文件,和aof文件都存在,优先用谁来恢复数据

答:aof

问:在dump rdb过程中,aof如果停止同步,会不会丢失数据

答:会,所有的操作缓存在内存的队列里, dump完成后,统一操作。

AOF损坏时的对策  【补充  18年-8月-3日】


1.若在写AOF文件时Server崩溃则可能导致AOF文件损坏而不能被Redis载入。可通过如下步骤修复:
创建一个AOF文件的备份; 

cp appendonly.aof appendonly.aof.bak

2.使用redis-check-aof工具修复原始的AOF文件;

3.重启redis  ,查看进程


4.使用diff -u 检查备份文件和修复后文件的异同(可选步骤);
使用修复后的AOF文件重启Redis。

猜你喜欢

转载自blog.csdn.net/Sugar_map/article/details/80874406
今日推荐