深入解析 Redis Cluster 架构与实现(一)

#作者:stackofumbrella

文章目录

  • Redis Cluster特点
  • Redis Cluster与其它集群模式的区别
    • 集群目标
    • 性能
    • hash tags
    • Mutli-key操作
    • Cluster Bus
    • 安全写入(write safety)
    • 集群节点的属性
    • 集群拓扑
    • 节点间handshake
    • 重定向与resharding
      • MOVED重定向
      • ASK重定向
      • 客户端首次链接以及重定向处理

Redis Cluster特点

多主多从,去中心化:从节点作为备用,复制主节点,不做读写操作,不提供服务
不支持处理多个key:因为数据分散在多个节点,在数据量大高并发的情况下会影响性能

支持动态扩容节点:这算是Redis Cluster最大的优点之一
节点之间相互通信,相互选举,不再依赖sentinel:准确来说是主节点之间相互监督,保证及时故障转移

Redis Cluster与其它集群模式的区别

相比较sentinel模式,多个master节点保证主要业务(比如master节点主要负责写)稳定性,不需要搭建多个sentinel实例监控一个master节点
,相比较一主多从的模式,具有自我故障检测,故障转移的特点
,相比较其他两个模式而言,对数据进行分片(sharding),不同节点存储的数据是不一样的。从某种程度上来说,Sentinel模式主要针对高可用(HA),而Cluster模式是不仅针对大数据量,高并发,同时也支持HA。
Redis Cluster的实现机制和原理

集群目标

1)高性能和线性扩展,最大可以支撑到1000个节点,Cluster架构中无Proxy层,Master与slave之间使用异步replication,且不存在操作的merge(即操作不能跨多个nodes,不存在merge层)。

2)一定程度上保证writes的安全性,需要客户端容忍一定程度的数据丢失。集群将会尽可能(best-effort)保存客户端write操作的数据,通常在failover期间,会有短暂时间内的数据丢失(因为异步replication引起),当客户端与少数节点处于网络分区时(network partition),丢失数据的可能性会更高,因节点有效性检测,failover需要更长的时间。

3)只要集群中大多数master可达、且失效的master至少有一个slave可达时,集群都可以继续提供服务。同时replicas migration可以将那些拥有多个slaves的master的某个slave,迁移到没有slave的master下,即将slaves的分布在整个集群相对平衡,尽力确保每个master都有一定数量的slave备份。Redis Cluster集群由多个shard组成,每个shard可以有一个master和多个slaves构成,数据根据hash slots配额分布在多个shard节点上,节点之间建立双向TCP链接用于有效性检测、Failover等,Client直接与shard节点进行通讯,集群暂不提供动态reblance策略。

性能

Redis Cluster并没有提供Proxy层,而是告知客户端将key的请求转发给合适的node。Client保存集群中nodes与keys的映射关系(slots),并保持此数据的更新,所以通常Client总能够将请求直接发送到正确的node上。因为采用异步replication,所以master不会等待slaves保存成功后才向客户端反馈结果,除非显式的指定了WAIT指令。multi-key指令仅限于单个节点内,除了resharding操作外,节点的数据不会在节点间迁移。每个操作只会在特定的一个节点上执行,所以集群的性能为master节点的线性扩展。同时Clients与每个node保持链接,所以请求的延迟等同于单个节点,即请求的延迟并不会因为Cluster的规模增大而受到影响。高性能和扩展性,同时保持合理的数据安全性,是Redis Cluster的设计目标。

hash tags

在计算hash slots时有一个意外的情况,用于支持“hash tags”,hash tags用于确保多个keys能够被分配在同一个hash slot中,每个key都可以包含一个自定义的“tags”,那么在存储时将根据tags计算此key应该分布在哪个node上(而不是使用key计算,但是存储层面仍然是key)。此特性可以强制某些keys被保存在同一个节点上,用于支持multi-key操作。hash tags的实现比较简单,key中“{}”之间的字符串就是当前key的hash tags,如果存在多个“{}”,首个符合规则的字符串作为hash tags,如果“{}”存在多级嵌套,那最内层首个完整的字符串作为hash tags,比如“{foo}.student”,那么“foo”是hash tags。如果key中存在合法的hash tags,那么在计算hash slots时,将使用hash tags,而不再使用原始的key,即“foo”与“{foo}.student”将得到相同的slot值,不过“{foo}.student”仍作为key来保存数据,即redis中数据的key仍为“{foo}.student”。

Mutli-key操作

Redis单实例支持的命令,Cluster也都支持,但是对于“multi-key”操作(即一次RPC调用需要进行多个key的操作)比如Set类型的交集、并集等,则要求这些key必须属于同一个node。Cluster不能进行跨Node操作,也没有node提供merge层代理。在人工对slots进行resharding期间,multi-key操作可能不可用。比如这些keys不存在于同一个slot(迁移会导致keys被分离)。比如Multikeys逻辑上属于同一个slot,但是因为resharding,它们可能暂时不处于同一个node,有些可能在迁移的目标节点上(比如Multikeys包含a、b、c三个keys,逻辑上它们都属于slot 8,但是其中c在迁移期间创建,它被存储在节点B上,a、b仍然在节点A),此时将会向客户端返回“-
TRYAGAIN”错误,那么客户端此后将需要重试一次,或者直接返回错误(如果迁移操作被中断),无论如何最终Multikeys的访问逻辑是一致的,slots的状态也是最终确定的。

Cluster Bus

集群中node负责存储数据,保持集群的状态,包括keys与node的对应关系(内部其实为slots与node对应关系)。node也能够自动发现其他的node,检测失效的节点,当某个master失效时还能将合适的slave提升为master。为了达成这些行为,集群中的每个节点都通过TCP与其他所有node建立连接,它们之间的通信协议和方式称为“Redis Cluster Bus”。 每个Node都有一个特定的TCP端口,用来接收其他nodes的链接,此端口号为面向Client的端口号+10000,比如客户端端口号为6379,那么node的Bus端口号为16379,客户端端口号可以在配置文件中声明。由此可见,node之间的交互通讯是通过Bus端口进行,使用gossip协议向其他node传播集群信息,以达到自动发现的特性,通过发送ping来确认其他node工作正常,也会在合适的时机发送集群信息。当然在Failover时(包括人为failover)也会使用Bus来传播消息。

gossip最终一致性,分布式服务数据同步算法,node首先需要知道(可以读取配置)集群中至少一个seed node,此node向seed发送ping请求,此时seed节点pong返回自己已知的所有node列表,然后node解析列表并与它们都建立tcp连接,同时也会向每个node发送ping,并从它们的pong结果中merge出全局node列表,并逐步与所有的node建立连接,数据传输的方式也是类似,网络拓扑结构为full mesh。

安全写入(write safety)

在Master-slaves之间使用异步replication机制,在failover之后,新的Master将会最终替代旧的master。在出现网络分区时(network partition),总会有个窗口期(node timeout)可能会导致数据丢失。不过,Client与多数派Master、少数派Master处于一个分区(网络分区,因为网络阻断问题,导致Clients与Nodes被隔离成两部分)时,这两种情况下影响并不相同。

1)write提交到master,master执行完毕后向Client反馈“OK”,不过此时可能数据还没有传播给slaves(异步replication),如果此时master不可达的时间超过阀值(node timeout),那么将触发slave被选举为新的Master(即Failover),这意味着那些没有replication到slaves的writes将永远丢失了。

2)还有一种情况导致数据丢失:

A)因为网络分区,此时master不可达,且Master与Client处于一个分区,且是少数派分区;

B)Failover机制,将其中一个slave提升为新Master;

C)此后网络分区消除,旧的Master再次可达,此时它将被切换成slave;

D)那么在网络分区期间,处于少数派分区的Client仍然将write提交到旧的Master,因为它们觉得Master仍然有效,当旧的Master再次加入集群,切换成slave之后,这些数据将永远丢失。

在第二种情况下,如果Master无法与其他大多数Masters通讯的时间超过阀值后,此Master也将不再接收Writes,自动切换为readonly状态。当网络分区消除后,仍然会有一小段时间,客户端的write请求被拒绝,因为此时旧的Master需要更新本地的集群状态、与其他节点建立连接、角色切换为slave等等,同时Client端的路由信息也需要更新。只有当此master与大多数其他master不可达的时间达到阀值时,才会触发Failover,这个时间称为NODE_TIMEOUT,可以通过配置设定。所以当网络分区在此时间内被消除的话,writes不会有任何丢失。反之,如果网络分区持续时间超过此值,处于“小分区”(minority)端的Master将会切换为readonly状态,拒绝客户端继续提交writes请求,那么“大分区”端将会进行failover,这意味着NODE_TIMEOUT期间发生在“小分区”端的writes操作将丢失。

集群节点的属性

集群中每个节点都有唯一的名字,称之为node ID,一个160位随机数字的16进制表示,在每个节点首次启动时创建。每个节点都将各自的ID保存在实例的配置文件中,此后将一直使用此ID,或者说只要配置文件不被删除,或者没有使用“CLUSTER RESET”指令重置集群,那么此ID将永不会修改。集群通过node ID来标识节点,而不是使用IP + port,因为node可以修改它的IP和port,如果ID不变,仍然认定它是集群中合法一员。集群可以在
cluster bus中通过gossip协议来探测IP、Port的变更,并重新配置。

node ID并不是与node相关的唯一信息,不过是唯一一个全局一致的。每个node还持有如下相关的信息,有些信息是关系集群配置的,其他的信息比如最后ping时间等。每个node也保存其他节点的IP、Port、flags(比如flags表示它是master还是slave)、最近ping的时间、最近pong接收时间、当前配置的epoch、链接的状态,最重要的是还包含此node上持有的hash slots。这些信息均可通过“CLUSTER NODES”指令开查看。

集群拓扑

Redis Cluster中每个node都与其他node的Bus端口建立TCP链接(full mesh,全网)。比如在有N个节点的集群中,每个node有N-1个向外发出的TCP链接,以及N-1个其他node发过来的TCP链接。这些TCP链接总是keepalive,不是按需创建的。如果ping发出之后,node在足够长的时间内仍然没有pong响应,那么此node将会被标记为“不可达”,那么与此node的链接将会被刷新或者重建。Nodes之间通过gossip协议和配置更新的机制,来避免每次都交互大量的消息,最终确保在nodes之间的信息传送量是可控的。

节点间handshake

Nodes通过Bus端口发送ping、pong,如果一个节点不属于集群,那么它的消息将会被其他node全部丢弃。一个节点被认为是集群成员的方式有2种:

1)如果此node在“Cluster meet”指令中引入,此命令的主要意义就是将指定node加入集群。那么对于当前节点,将认为指定的node为“可信任的”(此后将会通过gossip协议传播给其他node)。

2)当其他node通过gossip引入了新的node,这些node也是被认为是“可信任的”。

只要将一个节点加入集群,最终此节点将会与其他节点建立链接,即cluster可以通过信息交换来自动发现新的节点,链接拓扑仍然是full mesh。

重定向与resharding

MOVED重定向

因为redis并不提供Proxy机制,当Client将请求发给错误的node时(此node上不存在此key所属的slot),node将会反馈“MOVED”或“ASK”错误信息,以便Client重新定向到合适的node。理论上,Client可以将请求随意发给任何一个node,包括slaves,此node解析query,如果可以执行(比如语法正确,multiple keys都应该在一个node slots上),它会查看key应该属于哪个slot、以及此slot所在的node,如果当前node持有此slot,那么query直接执行即可,否则当前node将会向Client反馈“MOVED”错误。错误信息中包括此key对应的slot(3999),以及此slot所在node的ip和port,对于Client 而言,收到MOVED信息后,它需要将请求重新发给指定的node。不过,当node向Client返回MOVED之前,集群的配置也在变更(节点调整、resharding、failover等,可能会导致slot的位置发生变更),此时Client可能需要等待更长的时间,不过最终node会反馈MOVED信息,且信息中包含指定的新的node位置。虽然Cluster使用ID标识node,但是在MOVED信息中尽可能的暴露给客户端便于使用的ip + port。

当Client遇到“MOVED”错误时,将会使用“CLUSTER NODES”或“CLUSTER SLOTS”指令获取集群的最新信息,主要是nodes与slots的映射关系。因为遇到MOVED,一般也不会仅仅一个slot发生的变更,通常是一个或者多个节点的slots发生了变化,所以进行一次全局刷新是有必要的。Client将会把集群的这些信息缓存,以便提高query的性能。还有一个错误信息“ASK”,它与“MOVED”都属于重定向错误,客户端的处理机制基本相同,只是ASK不会触发Client刷新本地的集群信息。

ASK重定向

MOVED重定向与ASK非常相似。在resharding期间,为什么不能用MOVED?MOVED意思为hash slots已经永久被另一个node接管,接下来相应的查询应该与它交互,ASK的意思是当前query暂时与指定的node交互。在迁移期间,slot 8的keys有可能仍在A上,所以Client的请求仍然需要首先经由A,对于A上不存在的,才需要到B上进行尝试。迁移期间,Redis Cluster并没有粗暴的将slot 8的请求全部阻塞直到迁移结束,这种方式尽管不再需要ASK,但是会影响集群的可用性。

1)当Client接收到ASK重定向,它仅仅将当前query重定向到指定的node,此后的请求仍然交付给旧的节点。

2)客户端并不会更新本地的slots映射,仍然保持slot 8与A的映射,直到集群迁移完毕,且遇到MOVED重定向。一旦slot 8迁移完毕之后(集群的映射信息也已更新),如果Client再次在A上访问slot 8时,将会得到MOVED重定向信息,此后客户端也更新本地的集群映射信息。

客户端首次链接以及重定向处理

可能有些Cluster客户端的实现,不会在内存中保存slots映射关系(即node与slots的关系),每次请求都从声明的、已知的node中,随机访问一个node,并根据重定向(MOVED)信息来寻找合适的node,这种访问模式,通常是非常低效的。当然,Client应该尽可能的将slots配置信息缓存在本地,不过配置信息也不需要绝对的实时更新,因为在请求时偶尔出现“重定向”,Client也能兼容此次请求的正确转发,此时再更新slots配置,所以Client通常不需要间歇性的检测Cluster中配置信息是否已经更新,客户端通常是全量更新slots配置:

1)首次链接到集群的某个节点;

2)当遇到MOVED重定向消息时。

遇到MOVED时,客户端仅仅更新特定的slot是不够的,因为集群中的reshard通常会影响到多个slots。客户端通过向任意一个node发送“CLUSTER NODES”或“CLUSTER SLOTS”指令均可以获得当前集群最新的slots映射信息,“CLUSTER SLOTS”指令返回的信息更易于Client解析。如果集群处于broken状态,即某些slots尚未被任何nodes覆盖,指令返回的结果可能是不完整的。

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

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

相关文章

linux centos 服务器性能排查 vmstat、top等常用指令

背景:项目上经常出现系统运行缓慢,由于数据库服务器是linux服务器,记录下linux服务器性能排查常用指令 vmstat vmstat介绍 vmstat 命令报告关于内核线程、虚拟内存、磁盘、陷阱和 CPU 活动的统计信息。由 vmstat 命令生成的报告可以用于平衡系统负载活动。系统范围内的这…

在IIS上无法使用PUT等请求

错误来源: chat:1 Access to XMLHttpRequest at http://101.126.139.3:11000/api/receiver/message from origin http://101.126.139.3 has been blocked by CORS policy: No Access-Control-Allow-Origin header is present on the requested resource. 其实我的后…

Python训练第四十一天

DAY 41 简单CNN 知识回顾 数据增强卷积神经网络定义的写法batch归一化:调整一个批次的分布,常用与图像数据特征图:只有卷积操作输出的才叫特征图调度器:直接修改基础学习率 卷积操作常见流程如下: 1. 输入 → 卷积层 →…

Linux线程同步实战:多线程程序的同步与调度

个人主页:chian-ocean 文章专栏-Linux Linux线程同步实战:多线程程序的同步与调度 个人主页:chian-ocean文章专栏-Linux 前言:为什么要实现线程同步线程饥饿(Thread Starvation)示例:抢票问题 …

5.2 初识Spark Streaming

在本节实战中,我们初步探索了Spark Streaming,它是Spark的流式数据处理子框架,具备高吞吐量、可伸缩性和强容错能力。我们了解了Spark Streaming的基本概念和运行原理,并通过两个案例演示了如何利用Spark Streaming实现词频统计。…

Go 即时通讯系统:日志模块重构,并从main函数开始

重构logger 上次写的logger.go过于繁琐,有很多没用到的功能;重构后只提供了简洁的日志接口,支持日志轮转、多级别日志记录等功能,并采用单例模式确保全局只有一个日志实例 全局变量 var (once sync.Once // 用于实现…

「数据采集与网络爬虫(使用Python工具)」【数据分析全栈攻略:爬虫+处理+可视化+报告】

- 第 103 篇 - Date: 2025 - 06 - 01 Author: 郑龙浩/仟墨 文章目录 「据采集与网络爬虫」【使用工具:Python】一 数据采集1 数据采集综述(1)基本介绍(2)数据目标源(3)采集方式(4&am…

响应式系统与Spring Boot响应式应用开发

响应式系统概述 过去十年间,为应对移动和云计算的需求,软件行业通过改进开发流程来构建更稳定、健壮且灵活的软件系统。这种演进不仅服务于传统用户端(桌面/Web),还需支持多样化设备(手机、传感器等)。为应对这些挑战,多个组织共同制定了《响应式宣言》(2014年发布)…

POJO、DTO和VO:Java应用中的三种关键对象详解

在软件开发特别是Java开发中,常常会遇到POJO、DTO和VO这三类对象。它们在不同场景下扮演着重要角色,有助于优化代码结构、增强系统安全性和提升性能。本文将全面解析这三者的定义、区别及常见使用场景,帮助你更好地理解和应用。 1. POJO&…

leetcode付费题 353. 贪吃蛇游戏解题思路

贪吃蛇游戏试玩:https://patorjk.com/games/snake/ 问题描述 设计一个贪吃蛇游戏,要求实现以下功能: 初始化游戏:给定网格宽度、高度和食物位置序列移动操作:根据指令(上、下、左、右)移动蛇头规则: 蛇头碰到边界或自身身体时游戏结束(返回-1)吃到食物时蛇身长度增加…

NLP学习路线图(十三):正则表达式

在自然语言处理(NLP)的浩瀚宇宙中,原始文本数据如同未经雕琢的璞玉。而文本预处理,尤其是其中至关重要的正则表达式技术,正是将这块璞玉转化为精美玉器的核心工具集。本文将深入探讨正则表达式在NLP文本预处理中的原理…

计算机网络(4)——网络层

1.概述 1.1 网络层服务 (1) 网络层为不同主机(Host)之间提供了一种逻辑通信机制 (2)每个主机和路由器都运行网络层协议 发送方:将来自传输层的消息封装到数据报(datagram)中接收方:向传输层交付数据段(segment) 1.2 网络层核心功能 路由选择(routing…

EMO2:基于末端执行器引导的音频驱动虚拟形象视频生成

今天带来EMO2(全称End-Effector Guided Audio-Driven Avatar Video Generation)是阿里巴巴智能计算研究院研发的创新型音频驱动视频生成技术。该技术通过结合音频输入和静态人像照片,生成高度逼真且富有表现力的动态视频内容,值得…

[Redis] Redis:高性能内存数据库与分布式架构设计

标题:[Redis] 浅谈分布式系统 水墨不写bug 文章目录 一、什么是Redis?一、核心定位二、核心优势三、典型应用场景四、Redis vs 传统数据库 二、架构选择与设计1、单机架构(应用程序 数据库服务器)2、应用程序和数据库服务器分离3…

HTML5 视频播放器:从基础到进阶的实现指南

在现代Web开发中,视频播放功能是许多网站的重要组成部分。无论是在线教育平台、视频分享网站,还是企业官网,HTML5视频播放器都扮演着不可或缺的角色。本文将从基础到进阶,详细介绍如何实现一个功能完善的HTML5视频播放器&#xff…

牛客小白月赛117

前言:solveABCF相对简单,D题思路简单但是实现麻烦,F题郭老师神力b( ̄▽ ̄)。 A. 好字符串 题目大意:给定字符串s,里面的字母必须大小写同时出现。 【解题】:没什么好说的&#xff0…

特伦斯 S75 电钢琴:重构演奏美学的极致表达

在数字音乐时代,电钢琴正从功能性乐器升级为融合艺术、科技与生活的美学载体。特伦斯 S75 电钢琴以极简主义哲学重构产品设计,将专业级演奏体验与现代家居美学深度融合,为音乐爱好者打造跨越技术边界的沉浸式艺术空间。 一、极简主义的视觉叙…

GpuGeek 618大促引爆AI开发新体验

随着生成式AI技术迅猛发展,高效可靠的算力资源已成为企业和开发者突破创新瓶颈的战略支点。根据赛迪顾问最新发布的《2025中国AI Infra平台市场发展研究报告》显示,2025年中国生成式人工智能企业应用市场规模将达到629.0亿元,作为AI企业级应用…

第二十章 文本处理

第二十章 文本处理 所有类UNIX系统都严重依赖于文本文件来存储数据,所以存在大量文本操作工具也在情理之中。 相关命令: cat:拼接文件。sort:排序文本行。uniq:报告或忽略重复的行。cut:从每行中删除部分内容。past…

Reactor 和 Preactor

Reactor 和 Preactor 是两个在工业控制、生产调度和事件驱动系统中非常重要的设计模式或框架,不少人会用这两个名词来描述不同的编程思想或技术架构。 一、Reactor 模式(反应器模式) 1. 概述 Reactor 模式其实是一种I/O事件通知的设计思想…