[Redis][集群][下]详细讲解

server/2024/10/9 3:28:47/

目录

  • 1.集群搭建(基于 Docker)
  • 2.主节点宕机
    • 1.宕机后会发生什么?
    • 2.处理流程
      • 1.故障判定
      • 2.故障迁移
  • 3.集群扩容
    • 0.前言
    • 1.把新的主节点加入到集群
    • 2.重新分配slots
    • 3.给新的主节点添加从节点


1.集群搭建(基于 Docker)

  • 拓扑结构如下
    请添加图片描述

  • 创建目录和配置:创建redis-cluster⽬录,内部创建两个⽂件

    redis-cluster/
    ├── docker-compose.yml 
    └── generate.sh
    
  • generate.sh

    for port in $(seq 1 9); \
    do \mkdir -p redis${port}/touch redis${port}/redis.confcat << EOF > redis${port}/redis.confport 6379bind 0.0.0.0protected-mode noappendonly yescluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000cluster-announce-ip 172.30.0.10${port}cluster-announce-port 6379cluster-announce-bus-port 16379EOF
    done# 注意cluster-announce-ip的值有变化
    for port in $(seq 10 11); \
    do \mkdir -p redis${port}/touch redis${port}/redis.confcat << EOF > redis${port}/redis.confport 6379bind 0.0.0.0protected-mode noappendonly yescluster-enabled yescluster-config-file nodes.confcluster-node-timeout 5000cluster-announce-ip 172.30.0.1${port}cluster-announce-port 6379cluster-announce-bus-port 16379EOF
    done
    
    • 配置说明
      • cluster-enabled yes:开启集群
      • cluster-config-file nodes.conf集群节点⽣成的配置
      • cluster-node-timeout 5000:节点失联的超时时间
      • cluster-announce-ip 172.30.0.101:节点⾃⾝ip
      • cluster-announce-port 6379:节点⾃⾝的业务端⼝
      • cluster-announce-bus-port 16379节点⾃⾝的总线端⼝(管理端口)集群管理的信息交互是通过这个端⼝进⾏的
  • docker-compose.yml

    • 先创建networks,并分配网段172.30.0.0/24
    • 配置每个节点,注意配置⽂件映射,端⼝映射,以及容器的ip地址,设定成固定ip⽅便后续的观察和操作
      version: '3.7'
      networks:mynet:ipam:config:- subnet: 172.30.0.0/24services:redis1:image: 'redis:5.0.9'container_name: redis1restart: alwaysvolumes:- ./redis1/:/etc/redis/ports:- 6371:6379- 16371:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.101redis2:image: 'redis:5.0.9'container_name: redis2restart: alwaysvolumes:- ./redis1/:/etc/redis/ports:- 6372:6379- 16372:16379command:redis-server /etc/redis/redis.confnetworks:mynet:ipv4_address: 172.30.0.102# redis3 ~ redis11
      
  • 启动容器docker-compose up -d

  • 构建集群:此处把前9个主机构成集群,3主6从,后两个主机暂时不用

    • --cluster create:表⽰建⽴集群.后⾯填写每个节点的ip和地址
    • --cluster-replicas 2:表⽰每个主节点需要两个从节点备份
      redis-cli --cluster create 172.30.0.101:6379 172.30.0.102:6379 172.30.0.103:6379 172.30.0.104:6379 172.30.0.105:6379 172.30.0.106:6379 172.30.0.107:6379 172.30.0.108:6379 172.30.0.109:6379 --cluster-replicas 2
      
    • 日志中会描述哪些是主节点,哪些从节点跟随哪个主节点
      >>> Performing hash slots allocation on 9 nodes...
      Master[0] -> Slots 0 - 5460
      Master[1] -> Slots 5461 - 10922
      Master[2] -> Slots 10923 - 16383
      Adding replica 172.30.0.105:6379 to 172.30.0.101:6379
      Adding replica 172.30.0.106:6379 to 172.30.0.101:6379
      Adding replica 172.30.0.107:6379 to 172.30.0.102:6379
      Adding replica 172.30.0.108:6379 to 172.30.0.102:6379
      Adding replica 172.30.0.109:6379 to 172.30.0.103:6379
      Adding replica 172.30.0.104:6379 to 172.30.0.103:6379
      M: e4f37f8f0ea0dafc584349999795716613910e51 172.30.0.101:6379slots:[0-5460] (5461 slots) master
      M: 5f71983ad52cc7077ce8874ae1c4f9c23d9f502c 172.30.0.102:6379slots:[5461-10922] (5462 slots) master
      M: b3c0a96f6a206088ecea639147b6fcf903afe872 172.30.0.103:6379slots:[10923-16383] (5461 slots) master
      S: 85025819223f12615046c54d89f510e9cd0444a1 172.30.0.104:6379replicates b3c0a96f6a206088ecea639147b6fcf903afe872
      S: 2e5dc211288784ba55d554a377b87bfe2b5398db 172.30.0.105:6379replicates e4f37f8f0ea0dafc584349999795716613910e51
      S: 29f05d98982bd3df05d0222091e4b8ef9569f424 172.30.0.106:6379replicates e4f37f8f0ea0dafc584349999795716613910e51
      S: 3584840ac704c3ee016f3bdcca3f7ebe6f6e8e80 172.30.0.107:6379replicates 5f71983ad52cc7077ce8874ae1c4f9c23d9f502c
      S: 0a889103b35db2a6e82e8c09904bbef310cff3b1 172.30.0.108:6379replicates 5f71983ad52cc7077ce8874ae1c4f9c23d9f502c
      S: 00ba82bed6abeb015116d51d1af7fcb1609d03ad 172.30.0.109:6379replicates b3c0a96f6a206088ecea639147b6fcf903afe872
      Can I set the above configuration? (type 'yes' to accept): yes
      
    • Redis在构建集群时,谁是主节点,谁是从节点,谁和谁是一个分片,都是不固定的
      • 理论上说,从集群角度看,提供的所有节点本就应该是等价的
  • 此时,使用客户端连上集群中的任何一个节点,都相当于连上了整个集群

    • 客⼾端后⾯要加上-c选项,否则如果key没有落到当前节点上,是不能操作的
      • -c会自动把请求重定向到对应节点
    • 使⽤cluster nodes可以查看到整个集群的情况
  • 使用集群之后,之前的那些Redis命令,基本都能使用,除了一些操作多个key,如mget
    ![[Pasted image 20240911210424.png]]


2.主节点宕机

1.宕机后会发生什么?

  • 此处集群做的工作,和之前哨兵做的类似,会主动从该主节点旗下从节点中挑一个出来,提拔为主节点
    • master提示fail后,原本的slave会变成新的master
    • 如果重新启动原master,该节点会作为slave存在
  • 可以使⽤cluster failover进⾏集群恢复,也就是把原master重新设定成·master
    • 需要登录到原master机器上执行

2.处理流程

1.故障判定

  • 集群中的所有节点,都会周期性的使⽤⼼跳包进⾏通信
    • 节点A给节点B发送ping包,B就会给A返回⼀个pong
      • pingpong除了message type属性之外,其他部分都是⼀样的
      • 这⾥包含了集群的配置信息(该节点的id,该节点从属于哪个分⽚,是主节点还是从节点,从属于谁,持有哪些slots的位图…)
    • 每个节点,每秒钟,都会给⼀些随机的节点发起ping,⽽不是全发⼀遍
      • 这样设定是为了避免在节点很多的时候,⼼跳包也⾮常多
      • ⽐如有9个节点,如果全发,就是 9 ∗ 8 9*8 98有72组⼼跳了,⽽且这是按照 N 2 N^2 N2这样的级别增⻓的
    • 当节点A给节点B发起ping包,B不能如期回应的时候,此时A就会尝试重置和B的TCP连接,看能否连接成功,如果仍然连接失败,A就会把B设为PFAIL状态(相当于主观下线).
    • A判定B为PFAIL之后,会通过Redis内置的Gossip协议,和其他节点进⾏沟通,向其他节点确认B的状态
      • 每个节点都会维护⼀个⾃⼰的"下线列表",由于视⻆不同,每个节点的下线列表也不⼀定相同
    • 此时A发现其他很多节点,也认为B为PFAIL,并且数⽬超过总集群个数的⼀半,那么A就会把B标记成FALL(相当于客观下线),并且把这个消息同步给其他节点(其他节点收到之后,也会把B标记成FAIL)
    • 至此,B是否下线,就已经明确了
  • 某个或者某些节点宕机,有的时候会引起整个集群都宕机,称为fail状态
    • 某个分⽚,所有的主节点和从节点都挂了
      • 此时,该分片就无法提供数据服务了,相当于数据缺失
    • 某个分⽚,主节点挂了,但是没有从节点
    • 超过半数的master节点都挂了
      • 如果突然一系列的master都挂了,说明集群遇到了非常严重的问题,此时就需要赶紧停下来,检查检查是不是有什么问题
    • 核心原则:保证每个slots都能正常工作(存取数据)

2.故障迁移

  • 上述例⼦中,B故障,并且A把BFAIL的消息告知集群中的其他节点
    • 如果B是从节点,那么不需要进行故障迁移
    • 如果B是主节点,那么就会由B的从节点(比如C和D)触发故障转移了
  • 所谓故障转移,就是指把从节点提拔成主节点,继续给整个Redis集群提供支持
  • 具体流程
    • 从节点判定⾃⼰是否具有参选资格,如果从节点和主节点已经太久没通信(此时认为从节点的数据和主节点差异太⼤了),时间超过阈值,就失去竞选资格
    • 具有资格的节点,⽐如C和D,就会先休眠⼀定时间休眠时间 = 500ms基础时间 + [0, 500ms]随机时间 + 排名 * 1000msoffset的值越⼤,则排名越靠前(越⼩)
      • 排名越靠前,休眠时间就越短,谁休眠时间短,大概率就是新的主节点了
    • 比如C的休眠时间到了,C就会给其他所有集群中的节点,进行拉票操作
      • 但是只有主节点才有投票资格
    • 主节点就会把⾃⼰的票投给C(每个主节点只有1票),当C收到的票数超过主节点数⽬的⼀半,C就会晋升成主节点
      • C⾃⼰负责执⾏slaveof no one,并且让D执⾏slaveof C
    • 同时,C还会把⾃⼰成为主节点的消息,同步给其他集群的节点,⼤家也都会更新⾃⼰保存的集群结构信息
  • 上述选举的过程,成为Raft算法,是一种在分布式系统中广泛使用的算法
    • 在随即休眠时间的加持下,基本上就是谁先醒,谁就能竞选成功
    • 更多的时候,是为了选一个节点出来,至于是谁,并不重要
  • 哨兵是先选出leaderleader负责找一个从节点升级成主节点这里是直接投票选出新的主节点

3.集群扩容

0.前言

  • 扩容是⼀个在开发中⽐较常遇到的场景
  • 随着业务的发展,现有集群很可能⽆法容纳⽇益增⻓的数据,此时给集群中加⼊更多新的机器。就可以使存储的空间更⼤了
  • 分布式的本质就是使⽤更多的机器,引⼊更多的硬件资源
  • 明确集群扩容操作,是一件风险较高,成本较大的操作,操作时,需要抱着一个敬畏的心!!!

1.把新的主节点加入到集群

  • 上⾯已经把redis1-redis9重新构成了集群,接下来把redis10和redis11也加⼊集群
    • 此处把redis10作为主机,redis11作为从机
      redis-cli --cluster add-node 172.30.0.110:6379 172.30.0.101:6379
      
  • 说明
    • add-node后的第⼀组地址是新节点的地址
    • 第⼆组地址是集群中的任意节点地址,表示要把新节点加到哪个集群
  • 执行结果
    >>> Adding node 172.30.0.110:6379 to cluster 172.30.0.101:6379
    >>> Performing Cluster Check (using node 172.30.0.101:6379)
    M: 00d319e23ef76a4d51e74600c42ee2a371ae81f6 172.30.0.101:6379slots:[0-5460] (5461 slots) master2 additional replica(s)
    S: e34911c57d7605903de84ec05b3deac611aaef7e 172.30.0.105:6379slots: (0 slots) slavereplicates 00d319e23ef76a4d51e74600c42ee2a371ae81f6
    S: 6cf48cc11d0171b6ab1b418808473167acd7986e 172.30.0.106:6379slots: (0 slots) slavereplicates 00d319e23ef76a4d51e74600c42ee2a371ae81f6
    S: fd18c7f164b09ec563f4573ec9d6466e6769221e 172.30.0.108:6379slots: (0 slots) slavereplicates b3f2ba758318f4bd54031c98c01d7a6155ff43d3
    M: 579282abe81b3f20ffd17d5a1956cdca3b0e71b0 172.30.0.103:6379slots:[10923-16383] (5461 slots) master2 additional replica(s)
    S: e9ea79b1326ea5a75a1701d5c12a0f6081c1d043 172.30.0.109:6379slots: (0 slots) slavereplicates 579282abe81b3f20ffd17d5a1956cdca3b0e71b0
    S: 628d1ec9ceef6760b9038c4fbc83ee92430062ac 172.30.0.107:6379slots: (0 slots) slavereplicates b3f2ba758318f4bd54031c98c01d7a6155ff43d3
    M: b3f2ba758318f4bd54031c98c01d7a6155ff43d3 172.30.0.102:6379slots:[5461-10922] (5462 slots) master2 additional replica(s)
    S: 2a248acb47f0036655397897f9800c70ea22514f 172.30.0.104:6379slots: (0 slots) slavereplicates 579282abe81b3f20ffd17d5a1956cdca3b0e71b0
    [OK] All nodes agree about slots configuration.
    >>> Check for open slots...
    >>> Check slots coverage...
    [OK] All 16384 slots covered.
    >>> Send CLUSTER MEET to node 172.30.0.110:6379 to make it join the cluster.
    [OK] New node added correctly.
    
  • 此时的集群状态172.30.0.110这个节点已经成为了集群中的主节点,但没有任何slots
    • 需要重新分配slots

2.重新分配slots

  • 示例命令
    redis-cli --cluster reshard 172.30.0.101:6379
    
  • 说明reshard后的地址是集群中的任意节点地址
  • 执行之后,会进入交互式操作,Redis会提示用户输入以下内容
    • 多少个slots要进⾏reshard?
    • 哪个节点来接收这些slots?
    • 这些slots从哪些节点搬运过来?
      • all:从其他每个持有slotsmaster都拿过来点
      • done:从某一个或某几个节点来移动slots,以done为结尾
    How many slots do you want to move (from 1 to 16384)? 4096
    What is the receiving node ID? 522a1bd88a1a9084e6919fa88f4bf1c3655ad837
    Please enter all the source node IDs.Type 'all' to use all the nodes as source nodes for the hash slots.Type 'done' once you entered all the source nodes IDs.
    Source node #1: all
    
  • 如果在搬运slots/key的过程中,此时客户端能否访问Redis集群
    • 对于那些不需要搬运的key,访问的时候是没有任何问题的
    • 但是对于需要搬运的key,进⾏访问可能会出现短暂的访问错误(key的位置出现了变化)
    • 随着搬运完成,这样的错误⾃然就恢复了

3.给新的主节点添加从节点

  • 光有主节点了,此时扩容的⽬标已经初步达成,但是为了保证集群可⽤性,还需要给这个新的主节点添加从节点,保证该主节点宕机之后,有从节点能够顶上
  • 示例命令
    redis-cli --cluster add-node 172.30.0.111:6379 172.30.0.101:6379 --cluster-slave --cluster-master-id [172.30.1.110 节点的 nodeId]
    

http://www.ppmy.cn/server/127768.html

相关文章

基于python+flask+mysql的音频信息隐藏系统

博主介绍&#xff1a; 大家好&#xff0c;本人精通Java、Python、C#、C、C编程语言&#xff0c;同时也熟练掌握微信小程序、Php和Android等技术&#xff0c;能够为大家提供全方位的技术支持和交流。 我有丰富的成品Java、Python、C#毕设项目经验&#xff0c;能够为学生提供各类…

前缀和(6)_和可被k整除的子数组_蓝桥杯

个人主页&#xff1a;C忠实粉丝 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 C忠实粉丝 原创 前缀和(6)_和可被k整除的子数组 收录于专栏【经典算法练习】 本专栏旨在分享学习算法的一点学习笔记&#xff0c;欢迎大家在评论区交流讨论&#x1f48c; 目录 …

WPF入门教学二十二 多线程与异步编程

在WPF&#xff08;Windows Presentation Foundation&#xff09;中&#xff0c;多线程和异步编程是非常重要的概念&#xff0c;因为它们可以帮助你创建响应性更好的应用程序。WPF的UI线程负责处理所有的用户界面操作&#xff0c;如果你的代码在UI线程上执行耗时操作&#xff0c…

使用Materialize制作unity的贴图,Materialize的简单教程,Materialize学习日志

Materialize 官网下载地址&#xff1a;http://boundingboxsoftware.com/materialize/ github源码地址&#xff1a;https://github.com/BoundingBoxSoftware/Materialize 下载地址&#xff1a;http://boundingboxsoftware.com/materialize/getkey.php 下载后解压运行exe即可 …

软件验证与确认实验一:静态分析

目录 1. 实验目的及要求.................................................................................................... 3 2. 实验软硬件环境.................................................................................................... 3 …

Python环境安装教程

文章目录 一、搭建Python环境1.官网下载Python2.安装Python3.检验是否安装成功 二、安装pip1.检验是否有pip2.pip升级3.模块安装4.检验模块是否安装成功5.番外&#xff1a;pip做了什么&#xff1f; 本教程是安装Windows环境下Python3.7.4 一、搭建Python环境 1.官网下载Python…

<Rust>iced库(0.13.1)学习之部件(二十九):button部件新增方法on_press_with,可传入闭包函数

前言 本专栏是学习Rust的GUI库iced的合集,将介绍iced涉及的各个小部件分别介绍,最后会汇总为一个总的程序。 iced是RustGUI中比较强大的一个,目前处于发展中(即版本可能会改变),本专栏基于版本0.12.1. 注:新版本已更新为0.13 概述 这是本专栏的第二十九篇,在新版本中…

【GeekBand】C++设计模式笔记5_Observer_观察者模式

1. “组件协作”模式 现代软件专业分工之后的第一个结果是“框架与应用程序的划分”&#xff0c;“组件协作”模式通过晚期绑定&#xff0c;来实现框架与应用程序之间的松耦合&#xff0c;是二者之间协作时常用的模式。典型模式 Template MethodStrategyObserver / Event 2.…