Redis的主从模式架构如下
主从复制的流程
redis的主从模式主要是为了解决redis单机模式的一些问题,那么我们先来说说单机版的redis都有什么问题。
单机版的redis存在的问题
那么主从模式下的redis又有什么特点呢?
这里是将8000作为主机配置,另外两个作为从机,主机和从机的配置也有所不同,首先配置主机。
主机的配置
首先配置ip,这里直接配置呢0.0.0.0,允许任意ip访问
因为我们配置呢ip所以这个保护模式是没用的
配置端口,注意这里因为是在一台机器上搭建的主从redis,所以端口不能一样,但是如果是在不同的机器上可以配置一样的
开启守护进程模式
每个redis的pid也不能相同
配置日志文件
去掉RDB持久化机制,主机不需要做备份操作
这里因为在同一台机器上运行所以rdb文件也不能相同
配置数据文件存放的地址
主机配置密码,从机想要连接主机必须得有密码
主机也不需要做AOF备份
从机的配置
因为在一台机器上启动,首先还是端口
pid
日志
RDB
dir
最重要的配置,连接的主机
如果主机设置了密码从机也得设置,而且是一样的才能连接
从机做AOF备份
我们可以连接任意一个redis的客户端
[root@hadoop-master redis-conf]# /usr/local/bin/redis-cli -p 8000
127.0.0.1:8000>
我们可以通过下面的语句查看redis的状态
127.0.0.1:8000> info
我们发现这是一个主机
另外两个redis实例则都是从机而且主机是8000
我们可以通过下面的命令获得当前redis的配置,这个配置就是配置文件中的配置
127.0.0.1:8002> config get appendonly
1) "appendonly"
2) "yes"
同样我们也可以动态改变这些参数
127.0.0.1:8002> config set appendonly no
OK
127.0.0.1:8002> config get appendonly
1) "appendonly"
2) "no"
不过需要注意的是这种配置的参数如果重启redis实例就会失效,所以如果想要真正改变配置还需要更改配置文件中的参数。
全量复制一般很少会发生,因为消耗很高,一般只在从机第一次连接主机同步数据的时候发生,流程如下。
全量复制的消耗
在Redis 2.8版本开始引入。哨兵的核心功能是主节点的自动故障转移。
通俗来讲哨兵模式的出现是就是为了解决我们主从复制模式中需要我们人为操作的东西变为自动版,并且它比人为要更及时。
它是基于主从模式存在的,主从模式有的还是一样,只不过会多出来一个哨兵redis。
其中,监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移;而配置提供者和通知功能,则需要在与客户端的交互中才能体现。
首先之前的主从模式不变,我们需要添加一个或多个哨兵节点。
这里的主从节点就是刚刚在上面部署的主从节点,哨兵模式的主从节点的部署没有什么特别的地方,可以直接参考上面的方式。
唯一需要注意的是主机也需要配置连接主机的密码,因为可能主机挂掉就会更换主机,这样如果原先的注解重新启动也可以连接新的主机。
哨兵节点本质上是特殊的Redis节点。这里会部署三个哨兵节点,哨兵节点的配置文件和普通节点不同,是sentinel.conf
文件。
下面是sentinel.conf配置文件的一些注释
https://pan.baidu.com/s/12r0GfAg87JQuzWPrsw5CnQ
这里只介绍比较特殊的配置,其他的配置同主从节点
主要需要注意这个配置,这里的意思是该哨兵节点监192.168.123.19 8000这个主节点,该主节点的名称是mymaster,最后的2的含义与主节点的故障判定有关:至少需要2个哨兵节点同意,才能判定主节点故障并进行故障转移。
如果主机设置了密码,这里同样要配置密码
主从节点还是和之前一样启动
这里哨兵节点有两种方式启动,两者并无区别
redis-sentinel sentinel-26379.conf
redis-server sentinel-26379.conf --sentinel
这里我们来演示一下故障转转移
首先我们查看一下各个节点的状态
然后我们将主节点杀掉
接着查看其他节点状态
会发现8002节点变成了主机节点,这里会有些许延迟
8001还是从机,而且我们发现它的主机节点变成了8002
这时如果我们重新启动8000节点
它会变成从机节点,而且它的主机节点变成了8002
那么这时如何做到的呢?其实哨兵模式下如果重新选择了主机哨兵会动态配置每个节点,而且会直接从配置文件上做更改。我们可以看看这些节点它们现在的配置文件。
我们发现配置文件中的主机ip和端口变成8002了
而且在哨兵节点的配置文件中也发生了改变
public static void main(String[] args) {
Logger logger= LoggerFactory.getLogger(TestJedisSentinel.class);
Set<String> set=new HashSet<>();
set.add("192.168.0.104:28000");
set.add("192.168.0.104:28001");
set.add("192.168.0.104:28002");
JedisSentinelPool jedisSentinelPool=new JedisSentinelPool("mymaster",set,"123456");
while (true) {
Jedis jedis=null;
try {
jedis = jedisSentinelPool.getResource();
String s = UUID.randomUUID().toString();
jedis.set("k" + s, "v" + s);
System.out.println(jedis.get("k" + s));
Thread.sleep(1000);
}catch (Exception e){
logger.error(e.getMessage());
}finally {
if(jedis!=null){
jedis.close();
}
}
}
}
关于哨兵的原理,关键是了解以下几个概念:
主观下线:在心跳检测的定时任务中,如果其他节点超过一定时间没有回复,哨兵节点就会将其进行主观下线。顾名思义,主观下线的意思是一个哨兵节点“主观地”判断下线;与主观下线相对应的是客观下线。
客观下线:哨兵节点在对主节点进行主观下线后,会通过sentinel is-master-down-by-addr命令询问其他哨兵节点该主节点的状态;如果判断主节点下线的哨兵数量达到一定数值,则对该主节点进行客观下线。
需要特别注意的是,客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作。
每10秒通过向主从节点发送info命令获取最新的主从结构;
发现slave节点
确定主从关系
每2秒通过发布订阅功能获取其他哨兵节点的信息;SUBSCRIBE c2 PUBLISH c2 hello-redis交互对节点的“看法”和自身情况
每1秒通过向其他节点发送ping命令进行心跳检测,判断是否下线(monitor)。心跳检测,失败判断依据
选举领导者哨兵节点:当主节点被判断客观下线以后,各个哨兵节点会进行协商,选举出一个领导者哨兵节点,并由该领导者节点对其进行故障转移操作。
监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法;Raft算法的基本思路是先到先得:即在一轮选举中,哨兵A向B发送成为领导者的申请,如果B没有同意过其他哨兵,则会同意A成为领导者。选举的具体过程这里不做详细描述,一般来说,哨兵选择的过程很快,谁先完成客观下线,一般就能成为领导者。
故障转移:选举出的领导者哨兵,开始进行故障转移操作,该操作大体可以分为3个步骤:
在从节点中选择新的主节点,选择的原则是:
①首先过滤掉不健康的从节点;
②然后选择优先级最高的从节点(由replica-priority指定);
③如果优先级无法区分,则选择复制偏移量最大的从节点;
④如果仍无法区分,则选择runid最小的从节点。
更新主从状态:通过slaveof no one命令,让选出来的从节点成为主节点;并通过slaveof命令让其他节点成为其从节点。
将已经下线的主节点(即6379)保持关注,当6379从新上线后设置为新的主节点的从节点。
在主从复制的基础上,哨兵引入了主节点的自动故障转移,进一步提高了Redis的高可用性;但是哨兵的缺陷同样很明显:哨兵无法对从节点进行自动故障转移,在读写分离场景下,从节点故障会导致读服务不可用,需要我们对从节点做额外的监控、切换操作。此外,哨兵仍然没有解决写操作无法负载均衡、及存储能力受到单机限制的问题。