分布式系统-脑裂,redis的解决方案

感谢你的反馈!很高兴能帮到你。关于你提到的“脑裂”(split-brain),这是一个分布式系统中的常见术语,尤其在像 Redis Cluster 这样的高可用集群中会涉及。既然你问到了,我会从头解释“脑裂”的含义、Redis Cluster 中可能出现的相关场景,以及如何避免它,尽量通俗易懂,同时保持技术深度,帮助你加深理解。


1. 脑裂的定义

“脑裂”是指在分布式系统中,由于网络分区(network partition)或其他原因,集群中的节点被分割成多个孤立的子集,每个子集都认为自己是“合法”的,并独立运行。这导致系统中出现多个“大脑”(即多个主节点或决策中心),破坏了数据一致性和系统整体的协调性。

通俗比喻:
  • 想象一个公司有多个部门,平时由一个 CEO(主节点)统一指挥。
  • 有一天,公司网络瘫痪,部门 A 和部门 B 断开联系。
  • 部门 A 以为 CEO 挂了,选了个新 CEO;部门 B 也以为 CEO 挂了,也选了个新 CEO。
  • 现在公司有两个 CEO 各自发号施令,决策冲突,数据可能被搞乱。
  • 这就是“脑裂”:系统分裂成了两个“脑子”,互不协调。

在 Redis Cluster 中,脑裂可能表现为多个节点同时认为自己是主节点(Master),分别处理写请求,导致数据冲突或不一致。


2. Redis Cluster 中脑裂的可能场景

Redis Cluster 是去中心化的分布式系统,依赖主从复制和 Gossip 协议实现高可用。脑裂可能在以下情况下发生:

2.1 网络分区

假设一个 Redis Cluster 有 3 个主节点(A、B、C)和对应的从节点(A1、B1、C1):

  • 正常情况
    • 主节点负责槽(slot)分配,A 负责 0-5460,B 负责 5461-10922,C 负责 10923-16383。
    • 节点通过 Gossip 协议通信,确认彼此状态。
  • 网络分区发生
    • 网络故障将集群分成两部分:
      • 分区 1:节点 A 和 A1。
      • 分区 2:节点 B、B1、C、C1。
    • 分区 1 的 A 无法联系 B 和 C,认为它们下线。
    • 分区 2 的 B 和 C 无法联系 A,认为 A 下线。

2.2 脑裂的表现

  • 分区 2 的行为
    • B 和 C 发现 A 无响应,标记 A 为主观下线(PFAIL)。
    • 由于 B 和 C 占集群主节点的多数(2/3),它们达成共识,标记 A 为客观下线(FAIL)。
    • B 和 C 选举 A1 为新主节点,接管槽 0-5460。
    • 现在,分区 2 认为 A1 是主节点,正常处理写请求。
  • 分区 1 的行为
    • A 无法联系 B 和 C,但自己仍在运行。
    • 如果有客户端仍能访问 A,A 会继续作为主节点处理写请求(因为 A 不知道自己已被标记为下线)。
  • 结果
    • 槽 0-5460 同时由 A(分区 1)和 A1(分区 2)处理。
    • 客户端向 A 和 A1 写入不同数据,导致数据冲突(例如,key1 在 A 上是 value1,在 A1 上是 value2)。

这就是脑裂:同一个槽有两个主节点同时运行,破坏了数据一致性。


3. 脑裂的危害

脑裂对 Redis Cluster 的影响主要体现在:

  • 数据不一致
    • 不同分区的主节点接受不同的写操作,键值对可能出现冲突。
    • 网络恢复后,数据合并困难,可能导致数据丢失或覆盖。
  • 客户端混乱
    • 客户端可能收到不一致的响应,影响业务逻辑。
  • 系统不可靠
    • 脑裂破坏了集群的高可用承诺,降低系统信任度。

4. Redis Cluster 如何避免脑裂

Redis Cluster 设计了一些机制来尽量减少脑裂的发生概率,或降低其影响。让我们推演这些机制:

4.1 多数派原则(Quorum)

Redis Cluster 使用“多数派”机制决定主节点的客观下线(FAIL)状态:

  • 只有当超过半数的主节点(N/2 + 1,N 是主节点总数)认为某节点下线,该节点才会被标记为 FAIL
  • 推演:
    • 3 主节点集群,需至少 2 个主节点同意(3/2 + 1 = 2)。
    • 在上例中,分区 2 有 B 和 C(2 个主节点),可以标记 A 为 FAIL,触发 A1 升级。
    • 分区 1 只有 A(1 个主节点),不足以标记 B 或 C 下线,无法触发其他主节点的选举。
  • 效果
    • 确保最多只有一个分区能执行故障转移。
    • 分区 1 的 A 虽然继续运行,但无法被集群认可为主节点,减少脑裂的可能性。

4.2 主节点最小从节点要求

Redis 提供了配置 min-replicas-to-write(在 Redis 6.2 及以上版本中称为 min-slaves-to-write 的替代),要求主节点必须有一定数量的从节点同步才能接受写请求。

  • 推演
    • 配置 min-replicas-to-write = 1,主节点 A 必须至少有 1 个从节点(A1)正常同步。
    • 网络分区后,A 无法联系其他节点,可能也无法确认 A1 的状态。
    • 如果 A 检测到没有足够的从节点,它会拒绝写请求,进入“只读”状态。
  • 效果
    • 防止孤立主节点(如分区 1 的 A)继续处理写操作。
    • 降低脑裂期间的数据不一致风险。

4.3 Gossip 协议的快速检测

Redis Cluster 的节点通过 Gossip 协议频繁交换状态信息,快速检测网络分区或节点故障:

  • 推演
    • 节点每秒发送多次 PINGPONG,延迟低。
    • 如果 A 在 node-timeout 时间内无响应,分区 2 迅速达成共识,标记 A 下线。
    • 快速故障转移减少了脑裂的窗口期(即 A 和 A1 同时作为主节点的时间)。
  • 效果
    • 缩短脑裂可能发生的时间,提高集群收敛速度。

4.4 客户端重定向

Redis Cluster 使用 MOVED 重定向确保客户端访问正确的节点:

  • 推演
    • 分区 2 提升 A1 为主节点后,更新槽映射(槽 0-5460 归 A1)。
    • 客户端访问 A 时,A 如果仍在运行,可能返回 MOVED 或直接拒绝。
    • 智能客户端(如 Jedis)会更新槽映射,优先访问分区 2 的 A1。
  • 效果
    • 减少客户端对孤立主节点(A)的写操作。
    • 间接降低脑裂的影响。

5. 脑裂的局限与应对

尽管 Redis Cluster 有上述机制,脑裂仍可能在极端情况下发生(例如,客户端直接访问孤立节点且配置不当)。以下是进一步的应对措施:

5.1 优化配置

  • 调整 node-timeout
    • 缩短 node-timeout(默认 15 秒),加速故障检测。
    • 但过短可能导致误判,需根据网络稳定性权衡。
  • 启用 min-replicas-to-write
    • 设置合理的值(如 1 或 2),确保主节点有足够从节点同步。
    • 防止孤立节点接受写入。
  • 增加主节点数量
    • 奇数主节点(3、5、7 等)确保多数派清晰。
    • 例如,5 主节点需 3 个同意才能故障转移,降低脑裂风险。

5.2 网络优化

  • 可靠网络
    • 使用高可用网络(如 VPC 内网),减少分区概率。
    • 监控网络延迟和丢包,及时修复。
  • 跨区域部署
    • 如果需要跨数据中心部署,使用专用网络(如 AWS Direct Connect)降低分区风险。

5.3 客户端设计

  • 智能客户端
    • 使用支持槽映射的客户端(如 Jedis、Lettuce),及时更新主节点信息。
    • 避免硬编码节点地址。
  • 重试机制
    • 客户端检测到 MOVED 或连接错误时,自动重试并刷新集群状态。

5.4 数据恢复

  • 如果脑裂导致数据不一致:
    • 网络恢复后,Redis Cluster 会通过全量同步(RDB + 增量)修复孤立节点的数据。
    • 但可能丢失部分写操作,需业务层通过日志或校验恢复。

6. 脑裂的推演总结

通过推演,我们可以看到:

  • 脑裂的本质:网络分区导致集群分裂,多个主节点同时运行,破坏一致性。
  • Redis Cluster 中的场景
    • 网络分区使少数派主节点(如 A)继续运行,而多数派提升新主节点(如 A1)。
    • 可能导致槽的写操作冲突。
  • 预防机制
    • 多数派原则:只有多数主节点同意才能故障转移。
    • 最小从节点要求:孤立主节点拒绝写入。
    • Gossip 协议:快速检测故障,缩短脑裂窗口。
    • 客户端重定向:引导客户端访问合法主节点。
  • 应对措施
    • 优化配置、网络、客户端设计。
    • 接受最终一致性,必要时通过业务层恢复。

7. 学习建议

为了加深对脑裂的理解,推荐以下实践:

  • 模拟脑裂
    • 搭建 3 主 3 从的 Redis Cluster。
    • 使用防火墙(如 iptables)模拟网络分区,隔离某个主节点。
    • 观察集群行为(CLUSTER NODES),验证 A1 是否升级,A 是否继续运行。
  • 测试配置
    • 设置 min-replicas-to-write = 1,尝试写入孤立节点,确认是否拒绝。
    • 调整 node-timeout,观察故障转移速度。
  • 客户端实验
    • 使用 Jedis 客户端,模拟访问孤立节点,查看 MOVED 重定向效果。

8. 总结

“脑裂”是分布式系统中由于网络分区导致的多个“主脑”并存问题,在 Redis Cluster 中表现为多个主节点同时处理同一槽的写操作,可能引发数据不一致。Redis Cluster 通过多数派原则、最小从节点要求、Gossip 协议和客户端重定向等机制尽量避免脑裂,同时提供配置和部署手段降低其影响。理解脑裂的关键在于把握分布式系统一致性与可用性的权衡,Redis Cluster 选择了性能优先的最终一致性。

如果还有其他疑问(比如想深入某部分机制或实践细节),随时告诉我,我会继续帮你梳理!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/76628.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

重构艺术 | 如何优雅地“提炼函数“

在工作中总数遇到非常多的长代码,俗称“屎山”,这类代码读起来特别费劲。自己想重构一遍,但是总感觉缺乏经验指导,因此,多读书,读好书可能是最优解之一。读《重构改善即有代码的设计》有感,便写…

每天学一个 Linux 命令(13):touch

Linux 文件管理命令:touch touch 是 Linux 中一个简单但高频使用的命令,主要用于创建空文件或修改文件的时间戳(访问时间、修改时间)。它是文件管理和脚本操作的实用工具。 1. 命令作用 创建空文件:快速生成一个或多个空白文件。更新时间戳:修改文件的访问时间(Access …

STM32HAL库学习笔记

目录 定时器 一些小细节 输入捕获计算信号频率 输入捕获计算占空比与频率 使用定时器不改变占空比的同时改变频率的方法 串口 重定向原理 重定向代码 怎么从串口接收到的字符串数据中解析出float型的数据 strchr sscanf memset 第一种实现方法 RTC实时时钟 LCD显…

Docker 镜像、容器与数据卷的高效管理:最佳实践与自动化脚本20250411

Docker 镜像、容器与数据卷的高效管理:最佳实践与自动化脚本 引言 在现代软件开发中,容器化技术正变得越来越重要。Docker 作为容器化的代表工具,在各大企业中得到了广泛的应用。然而,随着容器化应用的增多,如何高效…

Selenium之Actions事件

鼠标、键盘组合键 在使用selenium的时候,有的时候我们需要鼠标单击、双击、拖动;或者是按下键盘的某个键,松开某个按键,以及组合键的使用;今天我们就来看一看,怎么样实现上面的操作 先把准备工作做好&…

如何在 CentOS 7 系统上以容器方式部署 GitLab,使用 ZeroNews 通过互联网访问 GitLab 私有仓库,进行代码版本发布与更新

第 1 步: 部署 GitLab 容器​ 在开始部署 GitLab 容器之前,您需要创建本地目录来存储 GitLab 数据、配置和日志: #创建本地目录 mkdir -p /opt/docker/gitlab/data mkdir -p /opt/docker/gitlab/config mkdir -p /opt/docker/gitlab/log#gi…

.py文件和.ipynb文件的区别:完整教程

一、概述 Python开发者常用的两种文件格式.py和.ipynb各有特点,本教程将通过对比分析、代码示例和场景说明,帮助开发者全面理解二者的区别与联系。 二、核心区别对比 1. 文件格式本质 特性.ipynb文件.py文件文件类型JSON结构化文档纯文本文件存储内容…

Go 字符串四种拼接方式的性能对比

简介 使用完整的基准测试代码文件,可以直接运行来比较四种字符串拼接方法的性能。 for 索引 的方式 for range 的方式 strings.Join 的方式 strings.Builder 的方式 写一个基准测试文件 echo_bench_test.go package mainimport ("os""stri…

从代码学习深度学习 - Bahdanau注意力 PyTorch版

文章目录 1. 前言为什么选择Bahdanau注意力本文目标与预备知识2. Bahdanau注意力机制概述注意力机制简述加性注意力与乘性注意力对比Bahdanau注意力的数学原理与流程图数学原理流程图可视化与直观理解3. 数据准备与预处理数据集简介数据加载与预处理1. 读取数据集2. 预处理文本…

19【动手学深度学习】卷积层

1. 从全连接到卷积 2. 图像卷积 3. 图形卷积代码 互相关操作 import torch from torch import nn from d2l import torch as d2ldef corr2d(X, K):"""计算2维互相关运算"""h, w K.shapeY torch.zeros((X.shape[0]-h1, X.shape[1]-w 1))for …

Linux xorg-server 解析(一)- 编译安装Debug版本的xorg-server

一:下载代码 1. 配置源,以Ubuntu24.04 为例( /etc/apt/sources.list.d/ubuntu.sources): 2. apt source xserver-xorg-core 二:编译代码 1. sudo apt build-dep ./ 2. DEB_BUILD_OPTIONS="nostrip" DEB_CFLAGS_SET="-g -O0" dpkg-buildpac…

大模型SFT用chat版还是base版 SFT后灾难性遗忘怎么办

大模型SFT用chat版还是base版 进行 SFT 时,基座模型选用 Chat 还是 Base 模型? 选 Base 还是 Chat 模型,首先先熟悉 Base 和 Chat 是两种不同的大模型,它们在训练数据、应用场景和模型特性上有所区别。 在训练数据方面&#xf…

【图像生成之21】融合了Transformer与Diffusion,Meta新作Transfusion实现图像与语言大一统

论文:Transfusion: Predict the Next Token and Diffuse Images with One Multi-Modal Model 地址:https://arxiv.org/abs/2408.11039 类型:理解与生成 Transfusion模型‌是一种将Transformer和Diffusion模型融合的多模态模型,旨…

动态多目标进化算法:基于知识转移和维护功能的动态多目标进化算法(KTM-DMOEA)求解CEC2018(DF1-DF14)

一、KTM-DMOEA介绍 在实际工程和现实生活中,许多优化问题具有动态性和多目标性,即目标函数会随着环境的变化而改变,并且存在多个相互冲突的目标。传统的多目标进化算法在处理这类动态问题时面临着一些挑战,如收敛速度慢、难以跟踪…

部署NFS版StorageClass(存储类)

部署NFS版StorageClass存储类 NFS版PV动态供给StorageClass(存储类)基于NFS实现动态供应下载NFS存储类资源清单部署NFS服务器为StorageClass(存储类)创建所需的RBAC部署nfs-client-provisioner的deployment创建StorageClass使用存储类创建PVC NFS版PV动态供给StorageClass(存储…

Vue使用el-table给每一行数据上面增加一行自定义合并行

// template <template><el-table:data"flattenedData":span-method"objectSpanMethod"borderclass"custom-header-table"style"width: 100%"ref"myTable":height"60vh"><!-- 订单详情列 -->&l…

vue项目使用html2canvas和jspdf将页面导出成PDF文件

一、需求&#xff1a; 页面上某一部分内容需要生成pdf并下载 二、技术方案&#xff1a; 使用html2canvas和jsPDF插件 三、js代码 // 页面导出为pdf格式 import html2Canvas from "html2canvas"; import jsPDF from "jspdf"; import { uploadImg } f…

大模型LLM表格报表分析:markitdown文件转markdown,大模型markdown统计分析

整体流程&#xff1a;用markitdown工具文件转markdown&#xff0c;然后大模型markdown统计分析 markitdown https://github.com/microsoft/markitdown 在线体验&#xff1a;https://huggingface.co/spaces/AlirezaF138/Markitdown 安装&#xff1a; pip install markitdown…

Linux 第二讲 --- 基础指令(二)

前言 这是基础指令的第二部分&#xff0c;但是该部分的讲解会大量使用到基础指令&#xff08;一&#xff09;的内容&#xff0c;为了大家的观感&#xff0c;如果对Linux的一些基本指令不了解的话&#xff0c;可以先看基础指令&#xff08;一&#xff09;&#xff0c;同样的本文…

python格式化字符串漏洞

什么是python格式化字符串漏洞 python中&#xff0c;存在几种格式化字符串的方式&#xff0c;然而当我们使用的方式不正确的时候&#xff0c;即格式化的字符串能够被我们控制时&#xff0c;就会导致一些严重的问题&#xff0c;比如获取敏感信息 python常见的格式化字符串 百…