一、单机redis存在的问题
1.数据安全问题,当redis宕机时会存在数据丢失问题:数据持久化
2.并发能力低,不能承载很大的并发量:主从集群
3.故障恢复问题:哨兵集群
4.存储能力问题,提高存储量:分片集群,利用散列插槽动态扩容
二、数据持久化
1.RDB持久化
RDB方式是利用了数据快照的方式,将内存中的所有数据读入到磁盘中,存放数据的文件为RDB文件。当redis重启后,会读取该RDB文件做数据恢复。
执行RDB的条件:
(1)关机自动执行;
(2)手动用save命令;
(3)手动用bgsave命令;
(4)通过配置执行条件,满足条件时触发;
bgsave的基本流程:
(1)fork主进程创建一个子进程,它们共享内存空间
(2)子进程读取内存数据写到新的RDB文件中
(3)将新的RDB文件替换旧的RDB文件
RDB方式的缺点:
(1)两次RDB操作间隔比较长,如果在这之间发生宕机,数据会丢失
(2)因为涉及到磁盘IO,再加上数据量可能也很大,都会导致RDB文件的写操作比较耗时
2.AOF持久化
AOF是追加文件。redis在每执行一个命令之后,就会把该命令写入到AOF文件中保存,也叫做命令日志文件。
AOF功能默认不开启,需要在配置文件中设置。写入AOF文件的频率也可配置,有三种:
文件重写:因为是记录命令,AOF文件会比RDB文件大的多。而且AOF会记录对同一个key的多次写操作,但只有最后一次写操作才有意义。通过执行bgrewriteaof命令,可以让AOF文件执行重写功能,用最少的命令达到相同效果。
3.RDB和AOF的区别
两者结合,yyds
三、主从集群
单节点Redis的并发能力是有上限的,要进一步提高Redis的并发能力,就需要搭建主从集群,实现读写分离。
1.主从集群搭建(略)
2.主从同步原理
(1)全量同步
自己描述一遍:首先,slave携带自己的replid和offset向master请求建立连接,master根据发来replid和自己的replid比较来判断是不是第一次连接,如果不一样则代表第一次连接(返回master的id和offset),就做全量同步。然后通过bgsave命令将master的内存数据写入到一个RDB文件中,写入完成后将RDB文件发给slave做数据同步。在此期间master会有新的命令请求,master都会记录这些命令到baklog中,随后发给slave继续同步数据。
完整流程描述:
-
slave节点请求增量同步
-
master节点判断replid,发现不一致,拒绝增量同步
-
master将完整内存数据生成RDB,发送RDB到slave
-
slave清空本地数据,加载master的RDB
-
master将RDB期间的命令记录在repl_baklog,并持续将log中的命令发送给slave
-
slave执行接收到的命令,保持与master之间的同步
(2)增量同步
全量同步需要先做RDB,然后将RDB文件通过网络传输个slave,成本太高了。因此除了第一次做全量同步,其它大多数时候slave与master都是做增量同步。
增量同步就是就是只更新slave与master存在差异的部分数据。就是master收到slave发来的replid和offset后,判断是不是第一次,不是则提醒slave继续干活!然后master去baklog中获取offset后的命令数据,将这些命令发送给slave做同步
(3)repl-baklog原理
底层是一个类似于环形的数组,当写入的数据到末尾时会重新从头开始写。
总的来说,master和slave都有自己的偏移量,slave的偏移量永远不超过master的偏移量,当它们的偏移量不相等时,slave就要不断的做增量同步。如果数组写满了数据,后面新的数据就会覆盖数组前面的数据,只要被覆盖的部分slave已经同步过了就没事,如果slave没同步,那就要做全量同步。
(4)主从同步优化
-
在master中配置repl-diskless-sync yes启用无磁盘复制,避免全量同步时的磁盘IO。
-
Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO
-
适当提高repl_baklog的大小,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
-
限制一个master上的slave节点数量,如果实在是太多slave,则可以采用主-从-从链式结构,减少master压力
(5)小结
简述全量同步和增量同步区别?
-
全量同步:master将完整内存数据生成RDB,发送RDB到slave。后续命令则记录在repl_baklog,逐个发送给slave。
-
增量同步:slave提交自己的offset到master,master获取repl_baklog中从offset之后的命令给slave
什么时候执行全量同步?
-
slave节点第一次连接master节点时
-
slave节点断开时间太久,repl_baklog中的offset已经被覆盖时
什么时候执行增量同步?
-
slave节点断开又恢复,并且在repl_baklog中能找到offset时
四、哨兵集群
哨兵集群:解决自动故障恢复问题,就是出问题了,可以自己恢复正常
三大作用:
(1)监控:监控集群的健康状态
(2)自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
(3)通知:通知客户端redis集群的变化
1.哨兵集群搭建(略)
2.哨兵原理
(1)集群监控原理
Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:
主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好超过Sentinel实例数量的一半。
客观下线才被认为是出故障了。
(2)自动故障恢复原理
当检测到master出故障了,哨兵会选一个slave做master,流程如下:
先看哪个slave和master断开的时间超过规定时间,超过就排除
再看优先级,优先级越小越优先
优先级一样,再看offset,offset越大代表未同步的数据的越少,数据越新
最后看id,越小越优先
当选出一个新的master后,该如何实现切换呢?
流程如下:
-
sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master
-
sentinel给所有其它slave发送slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
-
最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点
五、分片集群
分片集群解决问题:
-
海量数据存储问题
-
高并发写的问题
1.分片集群的特点
-
集群中有多个master,每个master保存不同数据
-
每个master都可以有多个slave节点
-
master之间通过ping监测彼此健康状态
-
客户端请求可以访问集群任意节点,最终都会被转发到正确节点
2.散列插槽
redis会将每个redis节点映射到0~16383共16384个插槽上。
数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分两种情况:
-
key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分
-
key中不包含“{}”,整个key都是有效部分
3.小结
Redis如何判断某个key应该在哪个实例?
-
将16384个插槽分配到不同的实例
-
根据key的有效部分计算哈希值,对16384取余
-
余数作为插槽,寻找插槽所在实例即可
如何将同一类数据固定的保存在同一个Redis实例?
-
这一类数据使用相同的有效部分,例如key都以{typeId}为前缀
以上图片和部分文字均来自虎哥资料