[微服务]redis主从集群搭建与优化

打印 上一主题 下一主题

主题 1025|帖子 1025|积分 3075

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
搭建主从集群

单节点Redis的并发本领是有上限的,要进一步进步Redis的并发本领,就必要搭建主从集群,实现读写分离。
1. 主从集群结构

下图就是一个简朴的Redis主从集群结构:


如图所示,集群中有一个master节点、两个slave节点(现在叫replica)。当我们通过Redis的Java客户端访问主从集群时,应该做好路由:


  • 如果是写操作,应该访问master节点,master会主动将数据同步给两个slave节点
  • 如果是读操作,建议访问各个slave节点,从而分担并发压力

2. 搭建主从集群

我们会在同一个虚拟机中使用3个Docker容器来搭建主从集群,容器信息如下:



2.1. 启动多个Redis实例

使用资料提供的docker-compose设置文件来构建主从集群:


a. 文件内容阐明:
  1. version: "3.2"
  2. services:
  3.   r1:
  4.     image: redis
  5.     container_name: r1
  6.     network_mode: "host"
  7.     entrypoint: ["redis-server", "--port", "7001"]
  8.   r2:
  9.     image: redis
  10.     container_name: r2
  11.     network_mode: "host"
  12.     entrypoint: ["redis-server", "--port", "7002"]
  13.   r3:
  14.     image: redis
  15.     container_name: r3
  16.     network_mode: "host"
  17.     entrypoint: ["redis-server", "--port", "7003"]
复制代码


  • redis官网建议在搭建集群时, 使用host网络模式, 让每个容器直接使用宿主机的网络
  • 此网络模式下, 容器会袒露在宿主机, 相称于成为宿主机的一个进程, 所以部署时也不必要端口映射
  • 直接使用宿主机的端口就可以了
  • entrypoint 入口设置, 用于修改容器的启动命令
  • "--port" 参数用于设置容器的默认端口

b. 把镜像文件上传至root目录下, 然后加载镜像文件





c. 在虚拟机的root目录下新建redis目录, 上传设置文件包


d. 执行命令,运行集群
  1. docker compose up -d
复制代码
执行结果:


查看docker容器,发现都正常启动了:


由于接纳的是host模式,我们看不到端口映射。不外能直接在宿主机通过ps命令查看到Redis进程:



2.2. 建立集群

固然我们启动了3个Redis实例,但是它们并没有形成主从关系。我们必要通过命令来设置主从关系:
  1. # 参数说明
  2. # masterip 主节点IP
  3. # masterport 主节点端口
  4. # 两个命令都能用
  5. # Redis5.0以前
  6. slaveof <masterip> <masterport>
  7. # Redis5.0以后
  8. replicaof <masterip> <masterport>
复制代码
有暂时和永久两种模式:


  • 永久见效:在redis.conf文件中使用slaveof命令指定master节点
  • 暂时见效:直接使用redis-cli控制台输入slaveof命令,指定master节点

我们测试暂时模式,起首毗连r2,让其以r1为master
  1. # 连接r2
  2. docker exec -it r2 redis-cli -p 7002
  3. # 认r1主,也就是7001
  4. slaveof 192.168.150.101 7001
  5. # 退出连接
  6. exit
复制代码
然后毗连r3,让其以r1为master
  1. # 连接r3
  2. docker exec -it r3 redis-cli -p 7003
  3. # 认r1主,也就是7001
  4. slaveof 192.168.150.101 7001
复制代码
然后毗连r1,查看集群状态:
  1. # 连接r1
  2. docker exec -it r1 redis-cli -p 7001
  3. # 查看集群状态
  4. info replication
复制代码


可以看到,当前节点r1:7001的脚色是master,有两个slave与其毗连:


  • slave0:port是7002,也就是r2节点
  • slave1:port是7003,也就是r3节点
此中重要的信息有:


  • master_replid: 主节点的唯一id
  • offset=672: 偏移量

2.3. 测试

依次在r1、r2、r3节点上执行下面命令:
  1. set num 123
  2. get num
复制代码


  • 只有在r1这个节点上可以执行set命令(写操作), 别的两个节点只能执行get命令(读操作)。
  • 也就是说读写操作已经分离了。
主从同步原理

主从同步原理时序图



  • 当主从第一次同步毗连或断开重连时,从节点都会发送psync请求,实验数据同步
  • 主节点判断从节点是否第一次毗连


  • 每个节点默认都是主节点, 每个主节点都有唯一id属性replicationID, 简称replid
  • 第一次paync, 从节点携带本身的replid
  • 所以, 主节点只必要判断, 从节点的replid是否与本身同等就可以了

  • 如果是第一次毗连, 主节点把本身全部数据全部发送给子节点


  • replid不同等, 属于第一次同步, 进行全量同步
  • 主节点将完整内存数据天生RDB,发送到从节点
  • 从节点清空本地数据, 加载RDBD到内存
  • 从节点把本身的replid 改成 主节点的replid

  • 如果是重新毗连, 主节点把子节点缺少的数据发给子节点


  • 全量同步必要先做RDB,然后将RDB文件通过网络传输个slave,成本太高了
  • 大多数时候从节点与主节点都是做增量同步
  • 增量同步就是只更新主从节点存在差异的数据。
  • 主节点会维护repl backlog文件, 此中会记录Redis处理过的命令及offset,包括主节点当前的offset,和子节点已经拷贝到的offset
  • 只要主从的offset同等, 代表数据同等, 如果offset存在差异, 那差异的部门,就是子节点必要增量拷贝的数据
  • repl_baklog巨细有上限,写满后会覆盖最早的数据。如果slave断开时间过久,导致尚未备份的数据被覆盖,则无法基于repl_baklog做增量同步,只能再次全量同步。

  • 每次主节点写数据时, 都把命令传播给子节点, 保持数据及时同步

主从集群优化
可以从以下几个方面来优化Redis主从集群:

  • 在master中设置repl-diskless-syncyes启用无磁盘复制,避免全量同步时的磁盘IO。
  • Redis单节点上的内存占用不要太大,减少RDB导致的过多磁盘IO, 一般建议不超过8G
  • 适当进步repl_baklog的巨细,发现slave宕机时尽快实现故障恢复,尽可能避免全量同步
  • 限制master上的slave节点数量,如果实在是太多slave,则可以接纳主-从-从链式结构,减少master压力


哨兵原理

Redis提供了哨兵(Sentinel)机制来实现主从集群的主动故障恢复。哨兵的具体作用如下:



  • 监控: Sentinel会不断检查您的master和slave是否按预期工作
  • 主动故障切换: 如果master故障,Sentinel会将-个slave提升为master。当故障实例恢复后也以新的master为主
  • 通知: 当集群发生故障转移时,Sentinel会将最新节点脚色信息推送给Redis的客户端

服务状态监控
Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:



  • 主观下线: 如果某sentinel节点发现某实例未在规定时间相应,则认为该实例主观下线。
  • 客观下线: 若超过指定命量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。
  • quorum值最好超过Sentinel实例数量的一半

推选新的master
一旦发现master故障,sentinel必要在salve中选择一个作为新的master,选择依据是这样的:

  • 起首会判断slave节点与master节点断开时间是非, 如果超过指定值 (down-after-milliseconds*10) 则会排除该slave节点
  • 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与推选, 默认都是1
  • 如果slave-prority一样,则判断slave节点的offset值, 越大阐明数据越新,优先级越高
  • 最后是判断slave节点的运行id巨细,越小优先级越高

怎样实现故障转移
当选中了此中一个slave为新的master后(比方slave1),故障的转移的步调如下:



  • sentinel给备选的slave1节点发送 slaveof no one 命令,让该节点成为master
  • sentinel给全部别的slave发送 slaveof 192.168.150.101 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
  • 最后,sentinel将故障节点标志为slave,当故障节点恢复后会主动成为新的master的slave节点
搭建哨兵集群

起首, 停掉之前的redis集群:
  1. # 老版本DockerCompose
  2. docker-compose down
  3. # 新版本Docker
  4. docker compose down
复制代码
然后,我们找到课前资料提供的sentinel.conf文件:


其内容如下:
  1. sentinel announce-ip "192.168.150.101"
  2. sentinel monitor hmaster 192.168.150.101 7001 2
  3. sentinel down-after-milliseconds hmaster 5000
  4. sentinel failover-timeout hmaster 60000
复制代码
阐明:


  • sentinel announce-ip "192.168.150.101":声明当前sentinel的ip
  • sentinel monitor hmaster 192.168.150.101 7001 2:指定集群的主节点信息




    • hmaster:主节点名称,自定义,任意写
    • 192.168.150.101 7001:主节点的ip和端口
    • 2:认定master下线时的quorum值



  • sentinel down-after-milliseconds hmaster 5000:声明master节点超时多久后被标志下线
  • sentinel failover-timeout hmaster 60000:在第一次故障转移失败后多久再次重试
  • 把设置文件中的信息修改为本身虚拟机的地点

我们在虚拟机的/root/redis目录下新建3个文件夹:s1、s2、s3:



  • 将课前资料提供的sentinel.conf文件上传到s1文件夹中, 再拷贝到其他文件夹中。



  • 接着修改docker-compose.yaml文件, 注意ip地点,内容如下:
  1. version: "3.2"
  2. services:
  3.   r1:
  4.     image: redis
  5.     container_name: r1
  6.     network_mode: "host"
  7.     entrypoint: ["redis-server", "--port", "7001"]
  8.   r2:
  9.     image: redis
  10.     container_name: r2
  11.     network_mode: "host"
  12.     entrypoint: ["redis-server", "--port", "7002", "--slaveof", "192.168.150.101", "7001"]
  13.   r3:
  14.     image: redis
  15.     container_name: r3
  16.     network_mode: "host"
  17.     entrypoint: ["redis-server", "--port", "7003", "--slaveof", "192.168.150.101", "7001"]
  18.   s1:
  19.     image: redis
  20.     container_name: s1
  21.     volumes:
  22.       - /root/redis/s1:/etc/redis
  23.     network_mode: "host"
  24.     entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27001"]
  25.   s2:
  26.     image: redis
  27.     container_name: s2
  28.     volumes:
  29.       - /root/redis/s2:/etc/redis
  30.     network_mode: "host"
  31.     entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27002"]
  32.   s3:
  33.     image: redis
  34.     container_name: s3
  35.     volumes:
  36.       - /root/redis/s3:/etc/redis
  37.     network_mode: "host"
  38.     entrypoint: ["redis-sentinel", "/etc/redis/sentinel.conf", "--port", "27003"]
复制代码

  • 直接运行命令,启动集群:
  1. docker-compose up -d
复制代码

  • 运行结果:



我们以s1节点为例,查看其运行日记:




可以看到sentinel已经联系到了7001这个节点,并且与别的几个哨兵也建立了链接。哨兵信息如下:


  • 27001:Sentinel ID是8e91bd24ea8e5eb2aee38f1cf796dcb26bb88acf
  • 27002:Sentinel ID是5bafeb97fc16a82b431c339f67b015a51dad5e4f
  • 27003:Sentinel ID是56546568a2f7977da36abd3d2d7324c6c3f06b8d
演示failover

接下来,我们演示一下当主节点故障时,哨兵是怎样完成集群故障恢复(failover)的。
我们毗连7001这个master节点,然后通过命令让其休眠60秒,模仿宕机:
  1. # 连接7001这个master节点,通过sleep模拟服务宕机,60秒后自动恢复
  2. docker exec -it r1 redis-cli -p 7001 DEBUG sleep 60
复制代码
轻微等待一段时间后,会发现sentinel节点触发了failover:



RedisTemplate毗连哨兵集群

分为三步:


  • 1)引入依靠
  • 2)设置哨兵地点
  • 3)设置读写分离
1.引入依靠

就是SpringDataRedis的依靠:
  1. <dependency>
  2.     <groupId>org.springframework.boot</groupId>
  3.     <artifactId>spring-boot-starter-data-redis</artifactId>
  4. </dependency>
复制代码
2.设置哨兵地点

毗连哨兵集群与传统单点模式不同,不再必要设置每一个redis的地点,而是直接指定哨兵地点:
  1. spring:
  2.   redis:
  3.     sentinel:
  4.       master: hmaster # 集群名
  5.       nodes: # 哨兵地址列表
  6.         - 192.168.150.101:27001
  7.         - 192.168.150.101:27002
  8.         - 192.168.150.101:27003
复制代码
3.设置读写分离

最后,还要设置读写分离,让java客户端将写请求发送到master节点,读请求发送到slave节点。定义一个bean即可:
  1. @Bean
  2. public LettuceClientConfigurationBuilderCustomizer clientConfigurationBuilderCustomizer(){
  3.     return clientConfigurationBuilder -> clientConfigurationBuilder.readFrom(ReadFrom.REPLICA_PREFERRED);
  4. }
复制代码
这个bean中设置的就是读写计谋,包括四种:


  • MASTER:从主节点读取
  • MASTER_PREFERRED:优先从master节点读取,master不可用才读取slave
  • REPLICA:从slave节点读取
  • REPLICA_PREFERRED:优先从slave节点读取,全部的slave都不可用才读取master

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

滴水恩情

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表