五 持久化与订阅者模式
5.1 RDB
在指定的时间间隔内将内存中的数据集快照写入磁盘, 也就是行话讲的Snapshot快照,它恢复时是将快照文件直接读到内存里
原理
Redis会单独创建(fork)一个子进程来进行持久化,会先将数据写入到 一个临时文件中,待持久化过程都结束了,再用这个临时文件替换上次持久化好的文件。 整个过程中,主进程是不进行任何IO操作的,这就确保了极高的性能 如果需要进行大规模数据的恢复,且对于数据恢复的完整性不是非常敏感,那RDB方式要比AOF方式更加的高效。RDB的缺点是最后一次持久化后的数据可能丢失。
Fork
- Fork的作用是复制一个与当前进程一样的进程。新进程的所有数据(变量、环境变量、程序计数器等) 数值都和原进程一致,但是是一个全新的进程,并作为原进程的子进程
- 在Linux程序中,fork()会产生一个和父进程完全相同的子进程,但子进程在此后多会exec系统调用,出于效率考虑,Linux中引入了“写时复制技术”
- 一般情况父进程和子进程会共用同一段物理内存,只有进程空间的各段的内容要发生变化时,才会将父进程的内容复制一份给子进程。
配置
save 60 5
:60s修改了5次key就触发RDB
触发条件
- save的规则满足的情况下,会自动触发rdb规则
- 执行 flushall 命令,也会触发我们的rdb规则!
- 退出redis,也会产生 rdb 文件!
- 备份就自动生成一个 dump.rdb
恢复
当你重启Redis服务时,就自动备份完成了
优点
- 适合大规模的数据恢复!
- 对数据的完整性要不高!
缺点
-
需要一定的时间间隔进程操作!如果redis意外宕机了,这个最后一次修改数据就没有的了!
-
fork进程的时候,会占用一定的内容空间
5.2 AOF
以日志的形式来记录每个写操作(增量保存),将Redis执行过的所有写指令记录下来(读操作不记录), 只许追加文件但不可以改写文件,redis启动之初会读取该文件重新构建数据,换言之,redis 重启的话就根据日志文件的内容将写指令从前到后执行一次以完成数据的恢复工作
过程
(1)客户端的请求写命令会被append
追加到AOF缓冲区内;
(2)AOF缓冲区根据AOF持久化策略[always,everysec,no]
将操作sync同步到磁盘的AOF文件中;
(3)AOF文件大小超过重写策略或手动重写时,会对AOF
文件rewrite
重写,压缩AOF文件容量;
(4)Redis服务重启时,会重新load
加载AOF文件中的写操作达到数据恢复的目的;
重写机制
- AOF采用文件追加方式,文件会越来越大为避免出现此种情况,新增了重写机制, 当AOF文件的大小超过所设定的阈值时,Redis就会启动AOF文件的内容压缩, 只保留可以恢复数据的最小指令集.可以使用命令
bgrewriteaof
- (1)
bgrewriteaof
触发重写,判断是否当前有bgsave
或bgrewriteaof
在运行,如果有,则等待该命令结束后再继续执行。 - (2)主进程fork出子进程执行重写操作,保证主进程不会阻塞。
- (3)子进程遍历redis内存中数据到临时文件,客户端的写请求同时写入
aof_buf
缓冲区和aof_rewrite_buf
重写缓冲区保证原AOF文件完整以及新AOF文件生成期间的新的数据修改动作不会丢失。 - (4)1).子进程写完新的AOF文件后,向主进程发信号,父进程更新统计信息。2).主进程把aof_rewrite_buf中的数据写入到新的AOF文件。
- (5)使用新的AOF文件覆盖旧的AOF文件,完成AOF重写
配置
AOF和RDB同时开启,系统默认取AOF的数据(数据不会存在丢失)
异常恢复
如遇到AOF文件损坏,通过/usr/local/bin/redis-check-aof--fix appendonly.aof
进行恢复
持久频率设置
appendfsync always
始终同步,每次Redis的写入都会立刻记入日志;性能较差但数据完整性比较好
appendfsync everysec
每秒同步,每秒记入日志一次,如果宕机,本秒的数据可能丢失
appendfsync no
redis不主动进行同步,把同步时机交给操作系统
优势
1、每一次修改都同步,文件的完整会更加好!
2、每秒同步一次,可能会丢失一秒的数据
3、从不同步,效率最高的!
缺点
1、相对于数据文件来说,aof远远大于 rdb,修复的速度也比 rdb慢!
2、Aof 运行效率也要比 rdb 慢,所以我们redis默认的配置就是rdb持久化 !
总结
- RDB 持久化方式能够在指定的时间间隔内对你的数据进行快照存储 。
- AOF 持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始 的数据,
- 只做缓存,如果你只希望你的数据在服务器运行的时候存在,你也可以不使用任何持久化 。
- 同时开启两种持久化方式 在这种情况下,当redis重启的时候会优先载入AOF文件来恢复原始的数据,因为在通常情况下AOF 文件保存的数据集要比RDB文件保存的数据集要完整。
- 性能建议 因为RDB文件只用作后备用途,建议只在Slave上持久化RDB文件,而且只要15分钟备份一次就够 了,只保留 save 900 1 这条规则。
5.3 订阅者模式
Redis 发布订阅(pub/sub)是一种消息通信模式:发送者(pub)发送消息,订阅者(sub)接收消息。微信、 微博、关注系统! Redis 客户端可以订阅任意数量的频道。
订阅/发布消息图: 第一个:消息发送者, 第二个:频道 第三个:消息订阅者!
参考博客:https://www.cnblogs.com/kellynic/p/9952386.html
命令
案例
- 订阅端:
127.0.0.1:6379> SUBSCRIBE kuangshenshuo # 订阅一个频道 kuangshenshuo
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "kuangshenshuo"
3) (integer) 1
# 等待读取推送的信息
1) "message" # 消息
2) "kuangshenshuo" # 那个频道的消息
3) "hello,kuangshen" # 消息的具体内容
1) "message"
2) "kuangshenshuo"
3) "hello,redis
- 发送端
127.0.0.1:6379> PUBLISH kuangshenshuo "hello,kuangshen" # 发布者发布消息到频道!
(integer) 1
127.0.0.1:6379> PUBLISH kuangshenshuo "hello,redis" # 发布者发布消息到频道!
(integer) 1
127.0.0.1:6379>
原理
- Redis是使用C实现的,通过分析 Redis 源码里的 pubsub.c 文件,了解发布和订阅机制的底层实现,籍 此加深对 Redis 的理解。
- Redis 通过 PUBLISH 、SUBSCRIBE 和 PSUBSCRIBE 等命令实现发布和订阅功能。
- 通过 SUBSCRIBE 命令订阅某频道后,redis-server 里维护了一个字典,字典的键就是一个个 频道!, 而字典的值则是一个链表,链表中保存了所有订阅这个 channel 的客户端。SUBSCRIBE 命令的关键, 就是将客户端添加到给定 channel 的订阅链表中。
- 通过 PUBLISH 命令向订阅者发送消息,redis-server 会使用给定的频道作为键,在它所维护的 channel 字典中查找记录了订阅这个频道的所有客户端的链表,遍历这个链表,将消息发布给所有订阅者。
- Pub/Sub 从字面上理解就是发布(Publish)与订阅(Subscribe),在Redis中,你可以设定对某一个 key值进行消息发布及消息订阅,当一个key值上进行了消息发布后,所有订阅它的客户端都会收到相应 的消息。这一功能最明显的用法就是用作实时消息系统,比如普通的即时聊天,群聊等功能 。
使用场景
1、实时消息系统!
2、事实聊天!(频道当做聊天室,将信息回显给所有人即可!)
3、订阅,关注系统都是可以的!