Redis作为我们最常用的内存数据库之一,在面对高并发环境时,也需要保持高可用性。因此,通常情况下我们需要配置Redis集群。
Redis集群,通常是在多个服务器上部署Redis服务,每个服务器作为一个节点,所有的节点之间互相联系,数据互通,这样就构成了Redis集群。
不过通常我们手上可能没有这么多服务器,不足以搭建集群,因此本文就在一台电脑上运行多个Redis进程为例,模拟集群搭建过程。
Redis集群有三种模式,下面我就来一一介绍一下它们的原理和搭建方式。
主从复制模式是将多个节点中分为主节点和从属节点,通常主节点只有一台,从节点有很多台,主节点提供写入和读取功能,但是从属节点只提供读取功能。
图中就是主节点,而就是从属节点,通常我们向主节点写入数据之后,主节点就会同步到从节点中去。
可见主从复制模式有以下优点:
- 读写分离,职责明确
- 高可用,如果从属节点挂掉一个,则整个集群仍然可用
主从复制的数据同步过程如下:
- 首先主节点启动,然后从属节点启动,从属节点会连接主节点并发送命令以请求同步
- 主节点收到命令之后,就会执行命令生成文件并使用缓冲区记录此后执行的写入命令
- 执行了之后,就向所有从属节点发送快照文件
- 从属节点收到快照文件之后,会丢弃自己已有的所有旧数据并把收到的快照写入数据库
- 之后,主节点会把缓冲区中的写命令发送给所有从节点实现从节点的增量同步
这里我们搭建一个“一主二从”的集群,也就是一个主节点两个从属节点的集群,集群地址列表如下:
首先我们要安装好Redis,建议在Linux服务器上面进行搭建,确保,和命令可以正常使用。这里就不讲述Redis的安装了,对于基本安装和配置不明白的可以参考我之前写的Linux上Redis安装配置的博客。
创建三个文件夹,里面分别存放我们三个节点的Redis配置文件,三个Redis节点的运行路径也对应着我们三个目录。我这里创建如下:

我这里创建了、和文件夹,每个文件夹里面都有一个表示每个节点的配置文件。
里面是主节点配置,文件内容如下:
讯享网
可见主节点配置和平常没什么特别的地方。
和里面是从属节点配置,内容如下:
讯享网
可见从属节点中,需要配置指定其对应的主节点的地址和端口号,以及指定主节点的密码,若主节点没有配置密码就可以省略此项,否则主节点配置了密码但是不写的话,就会导致从属节点同步数据失败!
我们通常最好是设定全部节点密码都一样。
然后依次使用命令进入三个文件夹并执行命令:
讯享网
这样,三个节点就启动了!
我们可以用命令连接一下我们任意一个节点,比如这里我连接主节点:
后面是地址,后面是端口。连上后使用认证,然后就可以执行命令了!
先执行以下命令查看节点信息:
讯享网

现在在主节点写一个数据试试:
然后退出连接一个从属节点:
讯享网
在从属节点获取刚刚写的数据:

这说明主节点写入数据后,成功地同步到了从属节点。
事实上,主从复制模式的缺陷也很明显:假设主节点挂了,我们需要手动去设置一个从属节点变为主节点并修改其它节点配置。
因此,主从复制模式目前用的不是说特别广泛。但是为什么这里还要学习主从复制模式呢?因为下面的模式很大程度上都基于主从复制模式。我们接着来看。
哨兵模式事实上是上述主从复制模式的一种扩展,也就是说在主从复制模式的基础上,增加哨兵节点以监视所有节点的情况,假设主节点挂掉了,哨兵节点会从所有从属节点中选举一个节点作为新的主节点,并修改其余从属节点的配置。

哨兵节点自身不会提供任何数据的读写存储功能,仅仅是负责监视所有的节点。哨兵不仅会监视所有复制数据存储读写的主从节点,还会互相监视。
通常哨兵节点也会有好几个,不过当其中一个哨兵监视到主节点挂掉时,系统并不会马上进行选举,因为这仅仅是一个哨兵看到主节点挂掉,这时称之为主观下线。而当其它哨兵也发现主节点挂掉时,并且发现主节点挂掉的哨兵达到一定值时,哨兵之间才会进行选举过程,这时称之为客观下线。那要多少个哨兵发现主机挂掉才会触发选举呢?这个是可以配置的,我们下面来看。
哨兵模式工作过程:
- 每个哨兵进程以每秒钟一次的频率向其它所有节点发送命令
- 如果一个节点距离最后一次有效回复时间间隔超过阈值,则这个节点会被这个哨兵标记为主观下线(),这个阈值可以通过哨兵节点配置文件中的配置,单位ms
- 当主节点被任意一个哨兵标记为,则正在监视主节点的所有哨兵会以每秒一次的频率确认主服务器的确进入了状态
- 当有足够数量的哨兵在指定的时间范围内确认主节点进入了,则主节点会被标记为客观下线(),进入故障切换()过程开始选举,哨兵节点选举出新的主节点后,会以发布订阅模式通知其余从属节点修改配置文件指向新的主节点
可见哨兵模式是一个自动化版的主从复制模式。
在这里我们搭建一个“一主二从三哨兵”集群,如下:
上述我们已经启动了“一主二从”集群,这里方便起见我们只需再创建三个文件夹存放三个哨兵的配置文件并在其中启动哨兵进程即可(哨兵模式中主从节点搭建配置和上述完全一样)。现在我这里目录如下:

然后我贴出上述第一个哨兵的配置:
讯享网
这里表示指定集群中主节点的地址和端口。这个配置有四个参数意义如下:
- 自定义的主节点名称,同一个集群中所有哨兵的主节点名称应当相同
- 主节点地址
- 主节点端口
- 表示触发客观下线的哨兵节点数,这里表示只要有一个哨兵标记主节点为主观下线,就触发选举
然后用于指定主节点密码,后面表示主节点名称,就是主节点密码。
其余哨兵节点配置我不再一一列出,只需复制上述配置文件然后修改里面的端口号配置,其余不变即可。
当然注意集群中所有主从节点的密码要全部一样!否则可能出现同步和选举上的问题。
主从节点都还在运行,这时我们依次使用命令进入三个哨兵配置文件夹执行下面命令启动哨兵进程(平时需要先启动主节点,再启动从属节点,最后启动哨兵节点,注意这个顺序):
可见这里哨兵进程需要用命令启动,后面参数也是接的配置文件路径。
这时,整个哨兵模式集群搭建完毕!大家可以这个时候手动停掉主节点,然后依次连接从属节点执行查看谁被选举成了新的主节点,这里我就不再演示了。
我们很多时候使用来连接Redis,不过这里连接哨兵集群和平时配置就有所不同了,我这里配置如下:
讯享网
这里主节点名称就是上面哨兵配置中我们定义的,然后配置所有哨兵节点,格式为,多个用英文逗号隔开,然后在配置主节点密码(注意是主节点密码)。
这里我们只需配置哨兵节点地址即可,项目启动后会自动通过哨兵节点找到主节点并连接,进而执行读写操作。
这也是官方推荐的模式,是新版本Redis支持的一种集群模式。
在上述哨兵模式中,已经实现了高可用和读写分离。但是我们也可见每个节点都要储存一份完整的数据,这样很浪费内存。因此Redis官方推出了Cluster模式,这种模式下每个节点不会储存完整的内容,但是节点直接相互连通,所有节点内容加起来才是完整的内容。


上述每个节点可能储存一部分内容,但是不论某个内容存放在哪个节点,我们都可以通过任意一个节点访问到,因为它们之间互相连通。
那么,在整个集群中又是如何存放数据的呢?事实上,搭建集群的时候,Redis会根据节点数量先分配主从节点,然后根据主节点数量平均分配整个空间。
Redis会先把整个集群所使用的储存空间分为一定数量的等分,这个等分就叫做哈希槽(hash slot)。
Redis集群中有16384个哈希槽,那么假设集群中有三个主节点分别是A、B和C,每个主节点对应一个从属节点A1、B1和C1,那么主节点会被分配槽位如下:
- A包含从哈希槽位
- B包含从哈希槽位
- C包含从哈希槽位
那我们存放数据时,这个数据到底会放到哪个槽位中去?事实上,Redis也有这样的一个算法:存入数据时,就会对存入的键计算CRC16,然后拿计算出来的值对16384取模得到的结果,就是这个数据的槽位。
同样地,从属节点也会和上面一样同步主节点的内容。假设现在主节点B挂掉了,是不是意味着槽位不能再储存数据了呢?当然不是。这时其对应的从属节点B1会被自动地提升为主节点。
为了保证高可用性,Redis要求Cluster模式至少需要3个主节点,而每个主节点至少要配备一个从属节点,因此我们至少需要6个节点才能搭建起来一个Redis的Cluster集群,所以说实际情况下对我们服务器数量有所要求。
节点如下:
同样地,新建6个文件夹,里面分别存放每个节点的配置文件:

这里放出第一个节点配置:
对于Cluster模式,我们每个节点都要配置表示打开集群模式,然后注意配置所有节点密码一样!并配置选项表示该节点访问其余节点时的密码,否则也会导致节点之间互相连通时发生错误。
其余的节点配置也可以拷贝这个文件只修改里面的端口配置即可。
然后也是依次使用命令进入每个文件夹并依次执行启动命令:
讯享网
启动之后,这时所有的节点仍然还是都单独运行的,我们还是需要用命令将它们连结起来,才能完成集群搭建。
命令格式如下:
表示每个主节点分配1个从节点,因此6个节点会被计算为3主3从。如果集群都没有设置密码,可以省略参数。
我这里命令如下:
讯享网
注意实际情况下指定节点一定要指定节点服务器的外网ip而不是域名或者内网ip!否则可能会连结集群失败。
还有就是我们上述节点端口是、…等等,这个是我们设定的客户端访问端口,而集群中节点互相连通访问的端口不是这个,而对应的是、…等等,也就是在客户端访问端口上加(外网访问端口和节点之间交流的端口总是相差),因此部署在服务器上时也要对应开放节点之间交流端口的防火墙。
然后会出现这些信息,输入确认:

出现这些信息则成功:

现在,我们可以用连接集群:
其中表示以集群模式连接,指定密码,这里要说明的是集群有密码并且以集群模式连接时一定要用指定连接密码,否则如果连接后再用输密码会导致重定向失败!
连接成功,写入数据试一下:

可见连接端口节点并写入数据,结果重定向到端口为的节点写入,这是因为通过上述算法对我们存入的键进行CRC16再取模运算之后得到结果,这个槽位位于第三个节点也就是端口节点,读取也是一样,如果你连接端口节点去取刚刚存入的键,那么它也会重定向到对应位置取得到这个键的值。通过这样重定向实现各个节点连通。
注意如果想重新配置集群,需要停止每个节点并把每个节点生成的这些文件删掉再执行上述步骤!

注意这个是集群节点自动生成的配置,用于记录节点之间的信息,它默认生成在当前运行目录,和数据文件在一起,如果你配置了指定了Redis的数据存放目录,则会生成到你指定的数据存放目录中去。平时不需要手动修改,这个文件的文件名默认是,可以通过配置项自定义。
同样还是使用来连接Redis,配置如下:
讯享网
可见这里只用配置所有节点地址端口和密码即可。
1. Redisson连接Cluster集群失败
今天搭建了个外网服务器集群,并在一个Spring Boot项目中如上进行配置,这个项目使用了Redisson作为分布式锁功能。结果配置之后项目无法启动,并报错:
我寻思着我的集群已经正确配置了啊,并且配置过程中没有任何报错。为什么这里提示集群没有覆盖全部哈希槽呢?事实上,这是因为Redisson无法连接所有的节点导致。
上面我们知道了:Redis以集群模式启动时会生成一个文件记录集群信息,我打开一个节点的这个文件一看,发现问题所在:

搭建集群时生成的文件内容也很明显:用于记录其余各个节点的id和地址。但是这个里面有个包含的行,显然是记录该节点自己的信息的,但是自己的地址记录的是内网地址,这时导致我们项目从外网获得一个内网地址然后无法连接。
解决方法很显然,就是先停止所有节点,并依次打开每个节点生成的,找到那一行,将其内网地址改为该节点服务器的外网地址,保存,重新启动节点即可。由于这里已经生成了文件记录了节点信息,因此再次启动所有节点它们之间就可以再次构成集群,不需要再像第一次创建集群的时候使用命令了!
再次启动项目,就不会出错了!
2. 使用Docker或者内网情况下,外网无法访问集群
上述我们知道了Cluster集群在启动时,会在数据目录下生成一个记录集群信息,其中包含了每个节点的地址和端口,这也是为什么我们通常连接一个节点就可以操作整个集群,在默认情况下:
- 每次集群启动,每个节点会自动获取自己的内网地址并广播给其它节点,这样每个节点将各自节点地址记录在中,并且每次启动都会被刷新
- 通过客户端进行连接时,客户端会先通过连接的节点,获取整个集群每个节点的地址,再重新连接每个集群节点,而客户端获取的集群节点地址,就是对应节点中中的地址
可见这就会导致一个问题:当我们在Docker或者内网环境搭建了一个Cluster集群,客户端在连接时得到的每个节点地址是内网地址,这就导致客户端在外网无法成功连接集群。
事实上这个问题很好解决,我们让每个节点在广播自己地址端口给其它节点时,指定广播自己的外网地址和端口,而不是自动检测到的内网地址端口就可以了。
在每个Cluster的节点配置文件中,加入下列配置:
通过上述配置,我们可以指定每个节点启动时,广播给其它节点的自己的地址和端口信息,分别是:
- 配置该节点广播给其它节点的自己的地址,通常填写这个节点所在服务器外网地址即可
- 配置该节点广播给其它节点的自己的端口,通常就是的配置(或者Docker暴露的端口),需保证该端口防火墙已放行
- 配置该节点广播给其它节点的自己的集**互端口(用于集群节点间相互通信、连结的端口),通常是配置值加上,需保证该端口防火墙已放行
例如我的配置:
讯享网
这时重启整个集群,可见中地址就变成了我们配置的外网地址,而非节点自动检测的内网地址:

可见只要理解了Redis的三种集群模式的大致原理,搭建一个集群并非是一件难事。主要容易踩坑的地方也就是我们配置的节点地址相关的部分,需要保证每个节点都配置为外网地址和端口,并且保证所有节点之间两两是可以相互访问到的。
如果说你是使用Docker配置Redis集群,也是没问题的,不过配置集群地址时,也一定要注意配置地址为节点所在服务器的外网地址,以及配置节点端口为Docker容器映射到宿主机上的端口(对外暴露的那个端口)。
参考文档:
- Redis官方集群搭建文档:
- 主从复制模式:传送门
- 哨兵模式:传送门
- Cluster模式:传送门
- Spring Data Redis配置文档:
- 哨兵模式:传送门
- Cluster模式:传送门
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/151093.html