单点问题 是分布式系统一个非常关键的问题
如果某个服务器只有一个节点,来部署服务,那对于 可用性 和 性能 都是一个很大的挑战
引入分布式系统就是为了解决这一问题
在分布式系统中,往往希望有多个服务器来部署 redis 服务,从而构成一个 redis 集群,此时就可以让这个集群给整个分布式系统中的其他服务 提供 更稳定 且 更为高效的数据存储功能
在分布式系统中,希望使用多个服务器来部署 redis,存在一下几种
redis 部署方式
1.主从模式
2.主从 + 哨兵模式
3.集群模式
一.主从模式
在若个阶段中,会有一个 主节点 和 一堆 从节点
主节点 负责进行接收接收 读写操作,而 从节点 来负责分担主节点的 读操作,也就是把主节点的数据复制到从节点上,让主节点来同步从节点的数据,但需要注意的是,从节点不能让主节点同步自己的数据,它只能读,不能写。
在实际的场景中,往往是 读 比 写 更为频繁,这些从节点就分担了并发量
那么此时还有一个问题,那 主节点要是挂了呢?
那就只能读数据,不能写数据了,可用性是提高了,但还是不够
配置 redis 主从结构,就要启动多个 redis 服务器
我们在此处以 一机多节点 来进行举例
一机多节点
如何指定 redis-server 的端口号呢?
1.在启动时 加上 -p
2.也可以在配置文件中,来设定端口

首先我们创建一个文件夹,然后把 redis 的配置文件复制过来,并检查一下是否是空文件的情况



修改了端口号之后,我们要想让他们称为真正的主从结构还得加一个配置
slaveof
1.在配置文件中加入 slaveof (master host)(masterPort)
2.在 redis -server 启动命令时加入 --slaveof(masterHost)(masterPort)生效
3.直接使用 redis 命令,slaveof(masterHost)(masterPort)

启动方式

这种启动方式直接用 kill -9 来结束就行
但是 如果是 service redis-server start 这种就必须要用 service redis-server stop 来进行停止
因为如果时直接杀死的话,就会出现一个问题,redis-server 就会自动启动
试想一下,主节点我们主动的 kill 了一下,然后丛节点就会慌了,赶紧重新选举一下老大,可是在这个时候因为我们时 把它直接 kill 了,他会自动重启,他一重启,服务器就死机了。
为了服务的高可用和稳定性,服务器难免会出现挂了的情况吧,这个时候服务器挂了我们就需要它自动重启,对于整体服务来说不算是太又严重的影响

通过这张图我们可以看到 主节点 和 每个从节点是有连接的,也确实是的,是 TCP 连接
此时的主节点就相当于是服务器,而从节点就相当于是客户端
最关键的是 主节点这边有什么修改从节点这边第一时间就会知道
通过 info replication 就可以知道当前节点的一些信息
主节点信息

以及查看从节点的状态,lag 是延迟的意思,offset 表示数据同步的进度
slaveof no one
直接在客户端使用这个命令,就可以断开节点之间的主从关系,里面的数据是不会抛弃的
从节点信息

虽然断开了主从结构但是此处的修改却只是临时的,重新启动又会重新与主节点建立主从结构
主节点和从节点之间通过网络传输(TCP)
TCP 内部支持了 nagle 算法
开启了,就会增加 tcp 的传输延迟,节省了网络带宽
关闭了,就会减少 tcp 的传输延迟,增加了网络带宽
开启了就相当于对于一些数据进行打包,然后统一传输,当然数据的及时性没有那么保证,但是传输的次数少了
rep-disable-tcp-nodelay 这个选项可以用于在主从同步通信过程中,关闭 tcp 的nagle算法
从节点更快速的和主节点进行同步
拓扑结构
一主一丛拓扑

如果写的请求太多,此时会给主节点造成一些压力
可以通过关闭主节点的 AOF,只在从节点上开启 AOF
这种操作有一个问题,主节点要是挂了,如果自动重启,此时没有 AOF 文件,就会丢失数据,接着主从同步,从节点的数据也被删了
办法是当主节点挂了之后,主节点主动的从 从节点 那里获取到 AOF 文件,再启动
一主多从拓扑

主节点上的数据发生改变,就会把改变的 数据同时,同步给所有的从节点
随着从节点的增多,同一条数据就会传输多次
一旦数据修改了,同步延时会比较长
树形拓扑

其实就是让子节点依次往下传输数据
主从节点复制流程图

redis 提供了 psync 命令,完成数据同步的过程
redis 服务器在建立好主从同步关系之后,自动执行 psync
从节点在执行了 psync 之后会主动的从主节点来去数据
replication 复制
主节点在启动的时候就会生成,从节点在晋升为主节点的时候也会生成
从节点和主节点建立了复制关系,就会从主节点这边获取到 replication id

这个replid2主要是为了应对一些突发情况,平常用不到
如果 主节点出现了网络抖动,让从节点误以为它挂了,从节点们就会重新选举主节点,后续第一次的主节点它网络稳定了,由于他之前的从节点还是记得它的 replid,所以又会投入它的怀抱,但是需要手动干预,哨兵机制可以自动完成这个过程
offset 偏移量
主节点和从节点都会维护 偏移量
主节点偏移量,主节点上会收到很多修改操作的命令,主节点会把这些修改命令的字节数进行累加
从节点的偏移量,就描述了,现在从节点数据同步的进度
relication id 和 offset 共同描述了一个 "数据集合"
如果两个机器的 replication id 一样,offset 也一样,就可以认为这俩 redis 机器上数据也是一样的
psync 可以从主节点获取全量数据,也可以获取一部分数据
offset 写作 -1,就是获取全量数据
offset 写成具体的整数,就是从偏移量位置来进行获取
获取所有的数据最为稳妥,可还是会比较低效,如果只从节点之前已经复制了一段数据之后现在只需要复制那没有的部分数据就不会这样了
主节点会判定看当前是否合适给部分数据,不合适的话就只能给全量了

进行全量复制的时机
1.首次和主节点进行数据同步
2.主节点不方便进行部分复制的时候
进行部分复制的时机
从节点之前已经从主节点上复制过数据了,因为网络抖动或者从节点重启了
从节点需要重新从主节点这边同步数据,此时看看能不能只同步一小部分

1)从节点发送psync命令给主节点进⾏数据同步,由于是第⼀次进⾏复制,从节点没有主节点的运 ⾏ID和复制偏移量,所以发送psync?-1。
2)主节点根据命令,解析出要进⾏全量复制,回复+FULLRESYNC响应。
3)从节点接收主节点的运⾏信息进⾏保存。
4)主节点执⾏bgsave进⾏RDB⽂件的持久化。
5)从节点发送RDB⽂件给从节点,从节点保存RDB数据到本地硬盘。
6)主节点将从⽣成RDB到接收完成期间执⾏的写命令,写⼊缓冲区中,等从节点保存完RDB⽂件 后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照rdb的⼆进制格式追加写⼊到收 到的rdb⽂件中.保持主从⼀致性。
7)从节点清空⾃⾝原有旧数据。
8)从节点加载RDB⽂件得到与主节点⼀致的数据。
9)如果从节点加载RDB完成之后,并且开启了AOF持久化功能,它会进⾏bgrewrite操作,得到最 近的AOF⽂件
在主节点生成 rdb 文件 和 传输 rdb 文件的过程中,还会收到很多新的修改操作
当从节点在接收主节点发来的rdb之后,主节点就会把这些新的修改操作发给从节点
主节点在进行全量复制的时候,也支持 "无硬盘模式"
主节点 生成的 rdb 的二进制数据,不是直接保存到文件中了,而是直接进行网络传输(省下了一系列读写硬盘的操作)
从节点 之前是把收到的 rdb 数据写入到硬盘中,然后再加载,现在可以直接省略这个过程,直接把收到的数据进行加载了
即使引入了无硬盘模式,但还是比较耗时的,全量复制的网络传输是无法省的
replication id/repid
主节点
info replication

info server

run id 是每个节点都不相同的
replid 是具有主从关系的节点,是相同的
从节点 6380


按照前面的说法,全量复制的开销是很大的,在有的时候比如出现了网络抖动,主从节点暂时断开连接了,网络恢复之后主从重新建立了连接,这个时候从节点实际上已经持有了主节点大部分数据,这个时候选择部分复制,那么这一过程具体化是怎样的呢?
psync 带有具体的replid 和 offset 值
主节点就会根据 psync 的参数进行判定,是全量复制合适还是部分复制合适

挤压缓冲区作为一个内存中的简单队列,会记录最近一段时间修改的数据,随着时间的推移,就会把之前旧的数据逐渐删除
实时复制:从节点已经和主节点同步好了数据,主节点在这之前一直收到修改命令,现在就会同步给从节点
从节点会与主节点建立长TCP连接,主节点会把自己收到的修改数据请求通过这个连接发送给从节点,从节点再进行修改
心跳包机制
在进行实时复制的时候,需要保证连接是处于可用状态的
主节点 默认 每隔 10s 给从节点发送一个 ping 命令,从节点收到就返回 pong
从节点 默认 每隔 1s 就会给主节点发起一个特定的请求,会上报当前从节点复制数据的进度
主从复制的问题出于主节点如果挂了之后,从节点就需要人为的恢复主节点
redis 哨兵
自动对挂了的主节点进行替换
从节点和主节点之间断开连接,有两种情况
1.从节点主动和主节点断开连接
slaveof no one
这个时候从节点就能够晋升为主节点
2.主节点挂了
这个时候从节点要想成功晋升为主节点,就得人为恢复主节点

通过 service redis-server start 启动的 redis 服务器,是通过 redis 用户来启动的,给予过高的权限有时也是一种负担
解决方案:把三个 redis 服务器生成的文件给区分开来,也可以直接把 三个 redis服务器的工作目录区分开(修改配置文件的 dir)
1.停止之前的 redis 服务器
2.删除之前工作目录下 已生成的 aof 文件,也可以通过 chown 命令修改 aof 文件所属用户
shown redis:redis appendonly.aof
3.给从节点创建出新的目录用来作为从节点的工作目录,并且修改从节点的配置文件,设定成新的目录为工作目录
4.启动 redis 服务器
我们需要通过自动化的方式来解决主节点挂了的问题
哨兵机制 是一个独立的进程 和 redis-server 是不同进程
redis-sentinel 不负责存储数据,只是对其他 redis-server 进程起到监控作用
通常情况下哨兵节点是一个集合,而不是单个
恢复主节点的一些判断
1.先看看主节点能不能抢救
2.如果主节点挂掉的原因暂时找不到或者说需要花费的时间达不到我们心中的预期的话,就需要重新的去挑选一个从节点,设置为新的主节点
具体的操作为:
a.把选中的节点通过 slaveof no one 脱离主节点控制
b.修改其他从节点的 slaveof 的 ip 和 port,连接上新的主节点
c.告知客户端,让客户端能够连接新的主节点用来完成修改数据的操作
如果这时候主节点被复活之后,就可以作为这个新主节点的从节点了

单独的 redis-sentinel 进程提供了多个哨兵
这三个哨兵进程就会监控现有的 redis master 和 slave
这些进程之间会建立 tcp长连接,通过这样的长连接定期发送心跳包,可以第一时间知道哪个节点挂了
1.主节点挂了需要多个哨兵节点进行共同判断其是否挂了,以保证了准确性
2.要是主节点是真的挂的不能再挂了,这时候哨兵节点们会选出一个 leader,让他来选择一个主节点继承点
3.挑选出这个继承点之后就会自动控制被选中的节点执行 slaveof no one,并且控制其他从修改 slaveof 到新的主节点上
4.哨兵节点会自动的通知客户端程序,告诉他新的主节点是谁,后续客户端再进行写操作,就会针对新的主节点进行操作了
redis 哨兵核心功能
1.监控
2.自动的故障转移
3.通知
在分布式系统中,要避免使用'单点',最好是奇数个