Redis --- 第八讲 --- 关于主从复制哨兵

时间:2024-10-23 19:42:25

主从复制的补充问题

从节点和主节点之间断开连接,有两种情况:

1、从节点和主节点断开连接

slaveof no one 命令。这个时候,从节点就能能够晋升成主节点。意味着我们程序员要主动修改redis的组成结构。,

2、主节点挂了

这个时候从节点不会晋升成主节点的。必须通过人工干预的方式恢复主节点。

这个是脱离咱们掌控的。

Redis主节点无法重启的问题:

通过service redis-server start 启动的redis服务器,是通过一个redis这样的用户,来启动的。而redis server需要按照可读可写的方式打开aof文件,而这个文件对于root之外的用户只有读权限。因此service redis-server start启动的redis服务器无法打开appendonly.aof文件。因为这里我们的三个服务器是使用的同一个appendonly.aof文件。

解决方案:把三个redis服务器的生成的文件,也给区分开。更靠谱的是,直接把三个redis服务器的工作目录区分开。(修改配置文件中的dir选项)

1、停止之前的redis服务器

2、删除之前工作目录下,已经生成的aof文件或者通过也可以通过chown命令修改以下所属用户。

3、给从节点创建出新的目录,用来作为从节点的工作目录。并且修改从节点的配置文件,设定成新的目录为工作目录。

4、启动redis服务器。

一、哨兵机制

人工,大部分是不太靠谱的。通过自动化的手段来解决主节点挂了的问题。也就是哨兵机制。

更哨兵机制有关的概念

哨兵机制是通过独立的进程来体现的和之前的redis-server是不同的进程。redis-sentinel不负责存储数据,只是对其他的redis-server起到监控的作用。通常哨兵节点,也会搞一个集合。单个哨兵节点挂了咋办。

Redis sentinel架构

单独的redis sentinel进程,提供了多个。并且这三个哨兵进程就会自动监控现有的redis master和slave。监控:这些进程之间,会建立tcp长连接,通过这样的长连接,定期发送心跳包。借助上述的监控机制,就可以即使发现某个主机是否是挂了。如果是从节点挂了,其实没有关系。如果是主节点挂了,哨兵就要发挥作用了。

第一步:此时一个哨兵节点发现主节点挂了,还不够,需要多个哨兵节点来共同认同这件事情,主要是为了防止出现误判。

第二步:主节点确实是挂了,这些哨兵节点中,就会推举一个leader,有这个leader负责从现有从节点中挑一个作为新的主节点。

第三步:挑选出新的主节点之后,哨兵节点,就会自动控制该被选中的节点,执行slaveof no one,并且控制其他从节点,修改slaveof到新的主节点上。

第四步:哨兵节点会自动的通知客户端程序,告知新的主节点是谁,并且后续客户端再进行写操作,就会针对新的主节点进行操作了。

Redis哨兵的核心功能:

1、监控

2、自动的故障转移

3、进行通知

注意,redis哨兵节点有一个也是可以的。

1、如果哨兵节点只有一个,它自身也是容易出现问题的。万一这个哨兵节点挂了,后续redis节点也挂了,就无法进行自动的恢复过程了。

2、出现误判的概率也比较高。毕竟网络传输数据也是容易出现抖动或者延迟或者丢包的。如果只有一个哨兵节点,出现上述问题之后,影响就比较大了。

基本原则:在分布式系统中,应该避免使用单点。也就是冗余。哨兵节点最后要搞奇数个,最少也应该是3个。

使用docker搭建环境

一个主节点和两个从节点,和三个哨兵的节点。

按理说,这6个节点,是要在6个不同的服务器主机上的。此时,只有一个云服务器,就在一个云服务器上,来完成这里的环境搭建。在实际工作中,把上述节点放到一个服务器上,是没有意义的。当前这么做只是迫于无奈的。

由于这些节点还挺多的,相互之间容易打架,依赖的端口号/配置文件/数据文件。如果咱们直接部署,就需要小心翼翼的去避开这些冲突。这种方式比较繁琐。也会和不同主机上部署,存在较大差异。

但是我们使用docker就可以有效的解决上述的问题。

简单介绍:虚拟机,通过软件,在一个电脑上模拟出另外的一些硬件。构造了另一个虚拟的电脑。虚拟机这样的软件就可以使用一个计算机。来模拟出多个电脑的情况。但是虚拟机有一个很大的问题,比较吃配置。这个事情对咱们的云服务器来说,压力山大。docker可以认为是一个轻量级的虚拟机,起到了虚拟机这样的隔离环境的效果,但是又没有吃很多的硬件资源。即使是配置比较拉跨的云服务器,也能构造出好几个这样的虚拟的环境。docker现在后端开发这块非常流行的组件。

docker中关键概念:容器,看作一个轻量级的虚拟机。

1、需要安装docker和docker-compose。

2、停止之前的redis服务器。

3、使用docker获取到redis的镜像。docker中的镜像和容器类似于可执行程序和进程的关系。镜像可以自己构建,也可以直接拿别人已经构建好的。docker hub。包含了很多其他大佬们构建好的镜像。

git pull使用git从*仓库拉取代码。docker pull使用docker从*仓库(默认是从docker hub)来拉取镜像。拉取到的镜像,里面包含一个精简的Linux操作系统,并且上面会安装redis。只要直接基于这个镜像创建一个容器跑起来,此时,redis服务器就搭建好了。

查看镜像。

基于docker来搭建redis哨兵环境了。

通过docker-compose来进行容器编排,此处涉及到多个redis server 也有多个redis哨兵节点。每一个redis server或者每一个redis哨兵节点都是作为一个单独的容器了。我们现在又6个容器了。

通过一个配置文件,把具体创建哪些容器,每个容器运行的各种参数,描述清楚。后续通过一个简单的命令,就能够批量的启动/停止这些容器了。使用yml这样的格式来作为配置文件。经典的配置文件格式:xml通过标签的格式进行组织的。

<>中成对出现的标签。html中的标签,都是标准规定的。xml中的标签,都是自定义的。写起来特别啰嗦。并且也比较占用空间。后来,又有了json这样的格式。

yml格式和json有一些相似之处,yml虽然没有json格式这么火,也还是挺广泛使用的。

和json都是这种比较直观的键值对结构,json是使用{}来表示层级结构,yml则是使用缩进来表示。yml相对于json的优势。对于格式要求的更严格,可读性会更好。更有助于人来理解。

编排工作:

1)创建三个容器,作为redis的数据节点(一个主,两个从)

2)创建三个容器,作为redis的哨兵节点。

文件名必须是固定的。

书写以下信息

version版本号

services启动哪些服务器

master,slave1,slave2 主从服务器名。

image:容器基于哪一个镜像。

command:启动redis服务器的选项。

ports:端口映射,docker容器,可以理解成是一个轻量的虚拟机。在这个容器里,端口号和外面宿主机的端口号是两个体系。如果容器外面使用了5000端口,在容器内部也可以使用5000彼此不会冲突。有的时候,希望在容器外面能够访问到容器里面的端口号。就可以把容器内部的端口映射成宿主机的端口。

有的端口,希望在容器外访问容器内部的端口,需要进行端口映射,把容器里的端口映射到宿舍主机上,后续访问宿主机的这个端口,就相当于在访问对应容器的对应端口了。站在宿主的角度,访问上述几个端口的时候,也不知道这个端口实际上是一个宿主机上的服务,还是一个来自于一个容器内部的服务。只要正常去使用即可。这里的映射过程非常像NAT一样。

启动容器。

查看对应的日志。

redis哨兵节点,是单独的redis服务器进程。

文件映射:哨兵节点,会在运行过程中,对配置文件进行自动的修改。因此,就不能拿一个配置文件,给三个容器分别映射。

接下里再来看这三个配置文件的具体细节。初始情况下,这三个配置文件内容可以是一样的。

bind 绑定ip,port 端口号,sentinel monitor告诉哨兵节点监控哪个redis服务器。ip,端口号,法定票数。这里的票数就是为了更稳健的确认当前redis-server是否挂了,不能只听一个哨兵的一面之词。

down-after-milliseconds 心跳包的超时时间。

创建redis-sentinel1文件。把上述的内容写到该文件中。复制出2和3文件。但是这里报了一个错误。

docker-compose以下启动了N个容器。此时N个容器都处于同一个局域网中,可以使者N个容器之间可以相互访问。三个redis-server节点是一个局域网。三个哨兵节点,是另一个局域网。默认情况下,这两网络似乎不能互通的。解决方案:可以使用docker-compose把此处的两组服务给放到同一个局域网中,docker network ls 列出当前docker中的局域网。

此处先启动了三个redis server节点,就相当于自动创建了第一个局域网。在启动后面三个哨兵节点,就直接让这三个节点加入到上面的局域网中,而不是创建新的局域网。

通过上述的操作,就完成了此处的配置。

启动后我们发现sentinel1文件里的内容已经被我们的程序自动配置重写了。

哨兵存在的意义,能够在redis主从结构出现问题的时候,此时哨兵节点就能够自动的帮我们重新选出一个主节点,来代替之前挂了的节点,保证整个redis仍然是可用的状态。

手动把主节点干掉

当主节点挂了之后,哨兵节点就开始工作了。

sdown主观下线,本哨兵节点,认为该主节点挂了,odown客观下线:好几个哨兵都认为该节点挂了,达成了一致,此时主节点挂了这个事情就被实锤了。

此时就需要哨兵节点选出一个从节点,作为新的主节点,此处就需要提拔出一个新的主节点。

切换过程。

如果主节点挂了之后,恢复过来,作为了一个从节点。

主从切换具体流程

哨兵重新选取主节点的流程(经典面试题)

1、主观下线

哨兵节点通过心跳包,判定redis服务器是否正常工作。如果心跳包没有如约而至,就说明redis服务器挂了。此时还不能排除网络波动的影响,因此就只能单方面认为这个redis节点挂了。

2、客观下线

多个哨兵都认为主节点挂了,认为挂了哨兵节点数目达到法定票数。哨兵们就认为这个主节点是客观下线。

3、要让多个哨兵节点,选出一个leader节点,由这个leader负责选一个从节点,作为新的主节点。

每个哨兵手里只有一票。当哨兵1第一个发现当前是客观下线之后,就立即给自己投了一票,并且告诉了2,3我来负责这个事情,2 3反应慢了半拍,才发现是客观下线,一看1乐意负责这个事情,立即投了赞成票。如果总的票数超过哨兵总数的一半,选举完成了。上面的投票过程看谁反应快。谁的网络延时小。

4、此时leader选举完毕,leader就需要挑选一个从节点,作为新的主节点。

1)比较一个优先级,每个redis数据节点,都会在配置文件中,有一个优先级的设置,slave-priority,优先级高的从节点,就会胜出。

2)offset最大,就胜出。offset从节点 从主节点同步数据的进度,数值越大,说明从节点的数据和主节点的数据就越接近。

3)run-id每个redis节点启动的时候,都会随机生成一串数字。(大小全凭缘分了)此时选谁都可以了,随便挑一个。

把新的主节点指定好了之后,leader就会控制这个节点,执行slave no one,成为master。在控制其他的节点,执行slave of,让其他节点,以新的master作为主节点了。

总结:

哨兵节点不能只有一个。

哨兵节点最好是奇数个。大部分情况下3个就够了。

哨兵节点不负责存储数据,仍然是redis主从节点负责存储。哨兵节点就可以使用一些配置不高的机器来部署。但是不能搞一个机器部署三个哨兵。

哨兵 + 主从复制 提高可用性。

哨兵 + 主从复制 不能提高数据的存储容量,当我们需要存的数据接近或者超过机器的物理内存,这样的结构就难以胜任了。redis集群可以来解决存储容量问题的有效方案。