十三、Redis的持久化
RDB
rdb保存的文件是dump.rdb都在我们的配置文件快照中进行配置的!
触发机制
1、save的规则满足的情况下,会自动触发rdb规则
2、执行了flushall命令也会触发我们的rdb规则
3、退出redis,也会产生rdb文件
备份就自动生成一个dump.rdb
比如save 10 100表示10秒内有n次修改时,自动触发bgsave,还有其他配置。
stop-writes-on-bgsave-error:设置yes表示bgsave失败时redis停止接收数据
rdbcompression:是否压缩
rdbchecksum:持久化时是否进行数据校验
如何恢复rdb文件!
1、只需要将rdb文件放在我们redis启动目录就可以,redis启动的时候会自动检查dump.rdb恢复其中的数据!
2、查看需要存放的位置
127.0.0.1:6379> CONFIG GET dir
1) "dir"
2) "/usr/local/bin" # 如果在这个目录下存在dump.rdb文件,启动就会自动恢复其中的数据
优点:
1、适合大规模的数据恢复!
2、对数据的完整性要求不高!
缺点:
1、需要一定的时间间隔进行操作如果redis意外宕机了这个最后一次的修改数据就没了
2、fork进程的时候,会占用一定的内存空间
AOF
AOF是指Redis将每一条指令(这里指可能对数据状态产生变化的写指令)通过write写入到AOF文件中。为了解决aof文件越来越大问题,redis提供bgrewriteaof命令,将内存数据先写入到内存文件,再fork线程将文件重写到新的aof文件。
AOF的三种触发机制
1、always:每次修改立即写入磁盘,性能最差数据完整性最好
2、everysec:每秒将内存指令写入磁盘,可能会造成数据丢失
3、no:由操作系统决定将内存指令写入磁盘
append
默认时不开启的,需要我们进行手动配置! 我们只需要将appendonly 改为yes就开启了 aof !
重启,redis就可以生效了!
如果这个aof文件有错误,这时候redis是启动不起来的,我们需要修复这个aof文件
redis 给我们提供了一个工具redis-check-aof --fix
优点和缺点!
appendonly no # 默认是不开启aof模式的
appendfilename "appendonly.aof" # 持久化的文件的名字
# appendfsync always # 每次修改都会写入 sync
appendfsync everysec # 美妙执行一次 sync,可能会丢失着一秒的数据
# appendfsync no # 不执行 sync,这个时候操作系统自己同步数据,速度最快
优点:
1、每一次修改都会同步,文件的完整会更加好!
2、每秒同步一次,可能会丢失一秒的数据
3、从不同步,效率是最高的
缺点:
1、相对于数据文件来说,aof远远大于rdb,修复的速度也比rdb慢
2、aof运行的效率也要比 rdb 慢,所以我们redis默认的配置就是 rdb 持久化
十四、Redis发布订阅
Redis 发布订阅 (pub/sub) 是一种消息通信模式:发送者 (pub) 发送消息,订阅者 (sub) 接收消息。
Redis 客户端可以订阅任意数量的频道。
发布与订阅相关命令
- 订阅
subscribe channel [channel ...]
订阅一个或多个频道,返回订阅的频道数
- 发布
publish channel message
向一个频道发布消息,返回向多少个客户端发送了消息
- 按照模式订阅
psubscribe pattern [pattern ...]
如果 publish 命令发送的频道和订阅的模式成功匹配,那么客户端就会接收到发布的消息
- 查看频道
pubsub channels [pattern]
返回有客户端订阅的频道,是用 pattern 参数,只返回与模式匹配的有客户端订阅的频道
- 查看频道的订阅数
pubsub numsub [channel ...]
返回频道和其订阅数
- 查看模式的订阅数
pubsub numpat
实现原理:
Redis将订阅关系保存在一个字典里面(Redis的字典是用哈希表实现的,基本可以认为字典就是哈希表),其中键是字符串类型就是频道名,值是一个链表存着所有订阅了该频道的客户端指针。

如上图所示,有三个频道:aaa,bbb和ccc。其中client-1订阅了全部三个频道,client-2订阅了 aaa 和 bbb,client-3订阅了 aaa。其中客户端指针指向客户端状态结构,这个结构中保存着套接字描述符以及各种其他信息,Redis可以通过此结构提供的信息向客户端发送数据。
- 频道订阅
当订阅一个频道的时候,只需要将客户端指针添加到该频道对应的链表的末尾即可,如果该频道还不是字典的键,那么创建键和对应的链表,并将客户端指针添加到链表末尾。比如,client-3 执行了subscribe ccc,那么字典结构将如下图所示:

- 退订频道
当一个客户端使用 unsubscribe 命令时,就会将客户端指针从要退订的频道对应的列表中删除。比如,在图二基础上,client-3 执行unsubscribe ccc,那么字典结构将由图二变为图一。如果将客户端指针删去后,频道对应的列表为空了,那么也会将频道删去。比如,在图一基础上,client-1 执行unsubscribe ccc,那么字典结构将如下图所示:

- 查看频道
当执行pubsub channels时,只需要遍历字典的所有键,将其返回即可。如果给了模式参数,只需要将与模式匹配的键返回即可。如果对图一结构的字典,使用pubsub channels命令,返回值将是:
1) "aaa"
2) "bbb"
3) "ccc"
- 查看频道的订阅数
当执行pubsub numsub [channel ...]命令时,只需要返回频道对应的列表的长度即可,如果键值不存在返回0即可,如果对图一结构的字典,使用pubsub numsub aaa,返回值将是:
1) "aaa"
2) (integer) 3
- 订阅模式
订阅模式和客户端的关系存在一个链表中,每一个节点都会保存模式字符串和客户端指针,链表结构如下图所示:

如果此时 client-4 执行psubscribe c*,那么链表结构将如下图所示:

- 模式退订
当执行punsubscribe pattern命令时,就会将链表中模式和客户端指针都对应相等的节点删去,比如,client-3 执行punsubscribe b*,那么链表结构将如下图所示:
b
- 发布信息
在发布信息的时候,需要分别将信息发送给订阅频道的客户端和订阅模式的客户端。
- 在将信息发送给订阅频道的客户端时,只需要在字典中找到该频道对应的链表,然后将信息发送给链表中的所有客户端。
- 在将信息发送给订阅模式的客户端时,需要遍历整个保存模式订阅的链表,如果发布的频道和模式匹配,则将其发送给这个客户端
以图一和图五为例,如果执行命令publish bbb message,那么首先在字典中找到频道 bbb 对应的客户端链表,将其发送给 client-1,client-2,然后遍历模式链表,发现之后模式 b* 匹配,那么再将信息发送给 client-3。
测试
订阅端:
# 订阅
127.0.0.1:6379> SUBSCRIBE chenhao # 订阅一个频道 chenhao
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "chenhao"
3) (integer) 1
# 等待读取推送的信息
1) "message" # 消息
2) "chenhao" # 频道名称
3) "Hey,hello!" # 消息的内容
发布端:
# 发布
127.0.0.1:6379> ping
PONG
127.0.0.1:6379> PUBLISH chenhao Hey,hello! # 发布者发布消息到频道!
(integer) 1
127.0.0.1:6379>

本文介绍了Redis的两种持久化方式RDB和AOF的工作原理、配置及优缺点,并详细阐述了Redis发布订阅机制的实现原理及其相关命令。

2414

被折叠的 条评论
为什么被折叠?



