!说明:近6天学了一下Redis,笔记分享,mark,mark!
一、持久化
- 持久化就是把内存的数据写到磁盘中去,防止服务宕机而导致内存数据丢失
- 提供两种持久化机制
RDB
(默认)和AOF
1、RDB
1)原理
- 指在指定的时间间隔内将内存中的数据集快照写入磁盘(
dump.rdb
文件) - 实际操作为fork一个子进程,先将数据集写入临时文件,写入成功后,再替换之前的文件,用二进制压缩存储
2)优点
- 只有一个文件
dump.rdb
,方便持久化 - 容灾性好,一个文件很容易保存到安全的磁盘上
- 性能最大化,
fork
子进程来完成写操作,让主进程继续处理命令,所以是I/O
最大化。使用单独子进程来持久化,主进程不会进行I/O
操作,保证了redis的高性能 - 相比于
AOF
机制,如果数据集很大,RDB
的启动效率会更高
3)缺点
- 数据安全性较低,
RDB
是间隔一段时间进行持久化,如果持久化之间redis发生故障,会发生数据丢失。因而这种方式不适合数据要求很严谨的持久化 - 由于
RDB
是通过fork
子进程来协助完成数据持久化工作的,因而在数据集较大时,可能会导致整个服务器停止服务几百毫秒
4)触发机制
- save规则满足时,会自动触发RDB
- 执行flushall命令,会触发RDB
- 退出redis服务,会触发RDB
2、AOF
1)原理
- 以日志的形式记录服务器所处理的每一个写操作,查询操作不会记录,以文本的方式记录,可以打开文件看到详细的操作记录
- 如果AOF文件有错误,这个时候redis服务是无法启动的,可以通过
redis-check-aof --fix
进行修复,可能会有一定的数据的损失
2)优点
- 数据安全,提供3种同步策略,即每秒同步、每修改同步和不同步。其中每修改同步可以将其视为同步持久化,即每次发生的数据变化都会立即被记录到磁盘中
- 对日志文件的写入操作是
append
模式,因此在写入过程中即使出现宕机,也不会破坏日志文件中已经存在的内容;即使写入时中途宕机,也可以通过redis-check-aof
工具解决数据一致性问题 - 对于日志文件过大,
AOF
采用rewrite
模式,将日志文件中的所有数据都重新写到另外一个新的日志文件中,但是不同的是,对于老日志文件中对于Key的多次操作,只保留最终的值的那次操作记录到日志文件中,从而缩小日志文件的大小 AOF
包含一个格式清晰、易于理解的日志文件用于记录所有的修改操作。也可以通过该文件完成数据的重建
3)缺点
AOF
文件比RDB
文件大,且恢复速度慢- 根据同步策略的不同,
AOF
在运行效率上往往会慢于RDB
3、持久化方式的选择
- 如果业务场景需要很高的性能,或者宕机之后能够尽快的恢复,而对数据完整性的要求不是很高,可以采用
RDB
方式 - 如果业务场景对数据完整性的要求很高,那么可以采用
AOF
的持久化方式,而采用的回写策略,取决于对数据完整性的要求程度 - 如果业务场景既要兼顾性能,又要注重数据完整性,那么可以采用混合持久化的方式
- 不要求数据的完整性,追求性能最大化,可以禁用持久化
4、Redis扩容
- 做缓存,使用一致性Hash实现动态扩容缩容
- 做持久化存储,必须使用固定的keys-to-nodes映射关系,节点的数量一旦确定不能变化,否则(即redis节点需要动态变化),必须正确使用可以在运行时进行数据再平衡的一套系统,而当前只有redis集群可以做到
二、发布与订阅
- 发布订阅模式又称为观察者模式,发布订阅为了就发布者和订阅者之间的关系,Redis使用了channel(频道)作为两者的中介,发布者将信息直接发布给channel,而channel负责将信息发送给适当的订阅者,发布者与订阅者间没有相互关系,也不知道对方的存在
- 采用事件作为基本的通信机制,提供大规模系统所要求的松散耦合的交互模式
1、订阅
SUBCRIBE channel1...
:订阅给定的一个或多个频道的信息
2、发布
PUBLISH channel message
:将信息发送到指定的频道
3、底层数据结构
- 订阅者和频道是通过一个字典(pubsub_channels)和链表的结构保存的
- 在这个字典中,key代表的是频道名称,value是一个链表,这个链表里面存放的是所有订阅这个频道的订阅者
- 该频道首次订阅,会创建对应的key,并且赋值一个空链表,然后将对应的订阅者加入到链表中
- 该频道已经被订阅过,此时直接将对应的订阅者信息添加到链表的末尾
3、应用
- 广泛应用于即时通信应用,如网络聊天室和实时广播、实时提醒等
- 订阅、关注场景
三、Redis集群
- 多数据库之间的集群操作,包括redis的主从模式、哨兵模式及redis集群
- 作用
1、主从模式
1)特点 / 说明
- 主服务器可以进行读写操作,当读写操作导致数据变化时会自动将数据同步给从数据库
- 从服务器一般只读,并接收主服务器同步的数据
- 一个
master
可以有多个slave
,一个slave
只有一个master
- 数据流向是单向的,从
master
到slave
- redis2.8之后,redis采取异步复制,从服务器会以每秒一次的频率向主服务器报告复制的处理进度
- 从服务器也可以有自己的从服务器,多个从服务器之间可以构成一个网状结构,它们之间具有传递关系
- 在主从服务器同步过程中,复制功能不会阻塞主服务器,即使多个从服务器正在进行初次同步,主服务器仍可以处理来自客户端的其他请求
2)工作机制
- 当
slave
启动后,主动向master
发送SYNC
命令 master
接收到SYNC
命令后在后台保存快照(RDB
持久化)和缓存保存快照这段时间的命令master
将保存的快照文件和缓存的命令发送给slave
slave
接收到快照文件和命令后加载快照文件和缓存的执行命令- 复制初始化后,
master
每次接受到写命令都会同步给slave
,从而保证一致性 - 出现断连,2.8之后的版本将断线期间的命令传入
slave
,增量复制 - 主从刚连接,进行全量同步;之后的为增量同步。如果有需要,
slave
可以在任何时候发起全量同步
3)全量同步和部分同步
- 全量同步:用于第一次复制的情况(初始化),通过让
master
创建并发送RDB
文件,以及向服务器发送保存在缓冲区里面的写命令来进行同步 - 增量同步:用于处理
slave
断开重连的情况,当slave
重连时,master
将断开期间的写命令发送给slave
4)优点
5)缺点
- redis不具备自动容错和恢复功能,主从服务器的宕机都会导致部分读写请求失败,需要等待机器的重启或手动切换
IP
- 主机宕机,宕机前有部分数据未能及时同步到从机,切换
IP
后可能会引入数据不一致的问题 - 较难支持在线扩容,在集群容量达到上限时在线扩容变得很复杂
- 主从节点的数据是一样的,降低了内存的可用性
6)redis心跳机制
- 在主从服务器之间进行命令传播时,从服务器默认会以每秒一次的频率发送
REPLCONF ACK
到主服务器 - 可以检测主从服务器之间的网络连接情况
- 设置
min-slaves
属性配置 - 检测在命令传播过程中是否有命令丢失
2、哨兵模式
1)特点 / 说明
- sentinel建立在主从模式的基础上
- 当master挂了之后,sentinel会在slave中投票选举出一个新的master,并修改他们的配置文件
- 当挂了的master重新启动后,它将作为slave,接受新master的同步
- sentinel也是一个进程,所以也有可能会挂掉,因而启动多个sentinel形成一个sentinel集群
- 多sentinel配置时,sentinel之间也会自动监控
2)工作机制
- 每个sentinel进程以每秒钟1次的频率向整个集群中的master、slave以及其他的sentinel发送一个PING命令
- 如果一个实例距离最后一次有效恢复PING的时间超过down-after-milliseconds选项所指定的值,则会被这个sentinel标记为主观下线
- 如果一个master被标记为主观下线,则正在监视这个master的所有sentinel以每秒一次的频率确认master的确进入了主观下线状态
- 当在指定时间范围内,有足够数量的sentinel(配置文件设定)确认master进入主观下线,则master会被标记为客观下线
- 一般情况下,每个sentinel会以10秒1次的频率向集群所有的master、slave发送INFO命令
- 当master被标记为客观下线,sentinel对下线的所有master和其所有的slave发送INFO的频率改为1秒1次
- 当master被标记为客观下线,监控它的所有sentinel会进行协商,采用一定规则和方法选举出一个sentinel领导,由它对下线的master进行故障迁移
3)故障迁移
- 在已下线的master属下的所有slave里面,挑选出一个slave,将其转换成新的master
- 将已下线的master属下的所有slave全部改为复制新的master
- 将已下线的master设置为新的master的slave,当这个旧的master重新上线时,它便成为新的master的slave
3、集群
- 当数据量过大到一台服务器存放不下的时候,sentinel模式也无法满足要求,这时候需要对存储的数据分片,将数据存储到多个Redis实例中
- 集群(cluster)就是解决Redis容量有限的问题的,将Redis的数据根据一定的规则分配到多台机器
1)特点 / 说明
- Redis集群采取去中心化的思想,没有中心节点,对于客户端,整个集群可以看成一个整体,可以连接任意一个节点进行操作,就像操作单个Redis实例一样,不需要任何代理中间件,当客户端操作的key没有分配到该结点上时,redis会返回转向指令,指向正确的节点
- redis也内置了高可用机制,支持N个master节点,每个master可以有多个salve,当master挂掉时,集群会提升它的某个slave作为新的master
- redis集群的读写都是在master上进行的,不支持slave的读写,主要使用slave做数据的热备份,以及master故障时的主备切换,实现高可用性
2)哈希槽算法
- redis集群有0-16384个哈希槽,将不同的哈希槽分布在不同的redis结点上进行管理,即每个redis节点只负责一部分的哈希槽
- 在对数据操作时,使用哈希槽算法(CRC16(key) mod 16384),来得到key对应的槽,从而找到管理这个槽的redis节点,然后再在这个结点上进行数据的读写操作
- 算法特点:
- 解耦数据和节点之间的关系,简化了扩容和收缩难度
- 节点自身维护槽的映射关系,不需要客户端代理服务维护槽分区元数据
- 支持节点、槽、key之间的映射查询
3)请求重定向
- 当redis节点接收到对某个key的命令时,如果这个key对应的槽不在自己负责范围,则返回MOVED重定向错误,通知客户端到正确的节点去访问数据
- 如果要访问的节点正在做数据迁移,所使用的重定向就是ASK,这是一种临时的重定向
- 频繁出现重定向错误,势必会影响访问的性能。由于key映射到槽的算法是固定公开的,客户端可以在内部维护槽到节点的映射关系,访问数据时可以自己通过key计算槽,然后找到正确的节点,减少重定向错误
4)故障恢复
- 一个持有槽的master客观下线后,集群会在其slave中找出一个替换它。
- redis集群采取选举-投票的算法来挑选新的master节点,一个slave必须至少获取包括故障节点在内的多数master节点投票后才能被提升为新的master
- 默认情况下,redis集群如果有master节点不可用,即有一些槽没有负责的节点,则整个集群不可用。即当一个master节点故障,到故障回复结束的这段时间内,整个集群都处于不可用状态。可以配置cluster-require-full-coverage配置为0,那么master节点故障时只会影响它负责的相关槽的数据,不影响其他节点的访问