0

0

面试问Redis集群,被虐的不行了......

咔咔

咔咔

发布时间:2020-08-28 17:23:42

|

1905人浏览过

|

来源于php中文网

原创

哨兵主要针对单节点故障无法自动恢复的解决方案,集群主要针对单节点容量、并发问题、线性可扩展性的解决方案。本文使用官方提供的redis cluster。文末有你们想要的设置ssh背景哦!

前言

咔咔整理了一个路线图,打造一份面试宝典,准备按照这样的路线图进行编写文章,后期发现没有补充到的知识点在进行添加。也期待各位伙伴一起来帮助补充一下。评论区见哦!

在这里插入图片描述
在这里插入图片描述

本文主要围绕如下几个方面介绍集群

  • 集群简介
  • 集群作用
  • 配置集群
  • 手动、自动故障转移
  • 故障转移原理

本文实现环境

  • centos 7.3
  • redis 4.0
  • redis工作目录  /usr/local/redis
  • 所有操作均在虚拟机模拟进行

一、集群简介

集群是为了解决主从复制中单机内存上限和并发问题,假如你现在的云服务内存为256GB,当达到这个内存时redis就没办法再提供服务,同时数据量能达到这个地步写数据量也会很大,容易造成缓冲区溢出,造成从节点无限的进行全量复制导致主从无法正常工作。

在这里插入图片描述
在这里插入图片描述

那么我们就需要把单机的主从改为多对多的方式并且所有的主节点都会连接在一起互相通信。这样的方式既可以分担单机内存,也可以分发请求,提高系统的可用性。

如图:当有大量请求写入时,不再会单一的向一个主节点发送指令,而会把指令进行分流到各个主节点,达到分担内存、避免大量请求的作用。

那么指令是如何进行分流存储的呢!我们就需要到集群存储结构中一探究竟。在这里插入图片描述

二、集群作用

  • 分散单机的存储能力,同时也可以很方便的实现扩展。
  • 分流单机的访问请求
  • 提高系统的可用性

如何理解提高系统的可用性这句话,我们看下图,当master1宕机后对系统的影响不会那么大,仍然可以提供正常的服务。

这个时候就会有人问了,当master1宕机后集群这个时候怎么工作呀!这个问题会在下文的故障转移来给你解答。并且在原理篇会对这个问题进行详解在这里插入图片描述

三、集群存储结构

1. 存储结构

单机的存储是当用户发起请求后直接把key存储到自己的内存即可。在这里插入图片描述集群的存储结构就没有那么简单了,首先当用户发起一个key指令后需要做的事情。

  • 通过CRC16(key)会计算出来一个值
  • 用这个值取模16384,会得到一个值,我们就先认为是28
  • 这个值28就是key保存的空间位置

那么现在问题来了,这个key到底应该存储在那个redis存储空间里边呢!在这里插入图片描述

其实redis在集群启动后就已经把存储空间划分了16384份,每台主机保存一部分。

这里需要注意的是我给每个redis存储空间里边的编号就相当于一个小的存储空间(专业术语“哈希槽”),你可以理解为一栋楼里边的编号,一栋楼就是redis的整个存储空间,每个房子的编号就相当于一个存储空间,这个存储空间会有一定的区域来保存对应的key,并非上图取模后的位置。

箭头指向的28是指的28会存储在这个区域里,这个房子有可能会存储29、30、31等。

在这里插入图片描述此时问题来了,如果新增、减少一台机器后怎么办呢!看图说话,能用图说明尽量不去用文字。

在新增一台机器后,会从其他三个存储空间中拿出一定的槽分配给新的机器。这里可以自己设置想给新的机器放多少个槽。

同样减少一台机器后会把去掉的槽在重新分配给其它现有的机器跟新增节点一样,可以指定节点接收槽。

所谓的增节点或去节点就是改变槽所存储的位置不同。在这里插入图片描述了解了集群的存储结构后,我们就需要在对另一个问题进行说明了,集群是如何设计内部通讯呢!来了一个值,获取一个key,去哪拿数据,跟着这个问题我们看下文。

2. 通讯设计

集群中的每个节点会在一定的时期给其它节点发送ping消息,其它节点返回pong作为响应。经过一段时间后所有节点都会知道集群全部节点的槽信息。

如下图有三个节点,那么就会把16384个哈希槽分成三份。

分别为0-5500、5501-11000、11001-16384

当用户发起了一个key的请求,集群是如何处理请求的呢!

下图的黑框代表这集群所有节点的槽信息,里边还有很多其它信息。在这里插入图片描述

如图所示,用户发起请求key,redis接收后计算key的槽位置,在根据槽位置找出对应的节点

如果访问的槽就在节点本身,那么就会直接返回key对应数据。

否则会回复moved重定向错误, 并且给客户端返回正确的节点。

然后重发key指令

在这里插入图片描述
在这里插入图片描述

四、配置集群

1. 修改配置文件

在这里插入图片描述只需要注意咔咔圈中的配置信息即可

  • cluster-enabled yes:开启集群模式
  • cluster-config-file nodes-6379.conf:集群配置文件
  • clustre-node-timeout 10000:节点超时时间,这里为了方便测试设置为10s
在这里插入图片描述
在这里插入图片描述

2. 构建6个节点的配置文件并全启动

咔咔给大家提供一个命令可以很方便的替换文件sed 's/6379/6380/g' 6379-redis.conf > 6380-redis.conf

按照这样的方式创建出来6个不同端口的配置文件

在这里插入图片描述随便打开一个配置文件查看,检测是否替换成功在这里插入图片描述为了查看日志信息方便,全部使用前台启动。并且查看服务是否都正常启动,执行命令ps -ef | grep redis

可以看到启动后多了个cluster标识,代表着都是集群的一个节点。在这里插入图片描述所有节点启动完成,集群启动的指令需要基于ruby(咔咔使用redis版本为4.0)。接下来一起安装

3. 安装ruby

执行命令wget https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.1.tar.gz

解压:tar -xvzf ruby-2.7.1.tar.gz 根据自己下载的版本来解压

安装:./configure | make | make install这三个指令一气呵成。

查看ruby和gem版本:ruby -v

在这里插入图片描述
在这里插入图片描述

4. 启动集群

集群的执行命令在/usr/local/redis/src/redis-trib.rb

注意如果需要直接使用redis-trib.rb命令,需要ln到bin目录下,否则就必须使用./redis-trib.rb的方式。

如果按照步骤走,这里会出现一个错误在这里插入图片描述执行gem install redis很不幸的是在这里也会出现错误。在这里插入图片描述随后需要安装yum install zlib-develyum install openssl-devel

安装完成后,在/ruby-2.7.1/ext/openssl/ruby-2.7.1/ext/zlib  分别执行ruby extconf.rb并且执行make | make install

然后在执行gem install redis就OK在这里插入图片描述这时在回头来执行./redis-trib.rb create --replicas 1 127.0.0.1:6379 127.0.0.1:6380 127.0.0.1:6381 127.0.0.1:6382 127.0.0.1:6383 127.0.0.1:6384在这里插入图片描述「信息解读」

创建集群,并且给6个节点分配哈希槽,后三个节点配置为前三个节点的从节点在这里插入图片描述显示每个节点的哈希槽信息和节点ID,最后一步需要输入yes在这里插入图片描述来到data目录下查看配置文件的变化。配置文件主要信息是每个主节点分的槽在这里插入图片描述在这里插入图片描述「查看主机点的运行日志」

这里给的主要信息cluster status changed:ok   集群状态正常在这里插入图片描述

5. 集群设置与获取数据

当直接设置数据会报错,并且把name这个key进行转化后的槽位置为5798   并且给出了ip地址和端口号。在这里插入图片描述需要使用命令redis-cli -c

在进行设置值的时候提示说重定向到5798的这个槽在这里插入图片描述接下来进行获取数据,会自动的切换节点。在这里插入图片描述

五、故障转移

1. 集群从节点下线

根据上文集群启动信息知道端口6383是6379的从节点。

接下来就是让6383下线查看6379的日志信息。

6379会报出连接6383丢失,并且给上标记fail,表示不可用。这个时候集群还是正常工作的。

「总结:从节点下线对集群没有影响」在这里插入图片描述当端口6383上线后,所有的节点会把fail的标记清除在这里插入图片描述

2. 集群主节点下线

手动下线主节点6379,查看从节点6383日志信息

此时的6383节点会持续连接6379共计10次。那为什么是10次呢! 是根据我们配置的参数cluster-node-timeout 10来决定的,这里给我们一个信息就是一秒连接一次

直到时间到期后,开始故障转移。

这时6383在故障转移选举中胜任,翻身奴隶把歌唱,成为了主节点。在这里插入图片描述此时在查看一下集群的节点信息,命令cluster nodes

会发现这里竟然存在四个主节点,但是其中一个主节点时下线状态在这里插入图片描述「6379原主节点上线」

6379上线后,同样所有的节点也会清除fail信息。

并且节点信息也会改变,此时的6379改变为6383的从节点。在这里插入图片描述

3. 新增主节点

在新增俩个端口6385和6386在这里插入图片描述执行新增命令./redis-trib.rb add-node 127.0.0.1:6385 127.0.0.1:6379,这里发送的就是meet消息

执行add-node命令,第一个参数为新节点的ip+端口   第二个参数为已存在集群中的节点。根据下图我们就可以看到新增的节点已经存在集群中了。

「注意:虽说6385已经成为集群中的节点了,但是跟其它节点有区别。它没有数据,也就是没有哈希槽」在这里插入图片描述接下来我们就需要把集群中的某些哈希槽分配到这个新节点上,分配结束后这个节点才会成为真正意义上的主节点

执行命令./redis-trib.rb reshard 127.0.0.1:6385

会提示转移多少个哈希槽并填写接收节点的id

最后一步询问是否从所有节点中转移:咔咔使用的是all

使用指令:cluster nodes查看,6385的这个节点就已经拥有三个范围的哈希槽了在这里插入图片描述

「主节点已经新增好了,接下来就需要给6385这个主节点配置一个从节点6386」

命令:./redis-trib.rb add-node --slave --master-id dcc0ec4d0c932ac5c35ae76af4f9c5d27a422d9f 127.0.0.1:6386 127.0.0.1:6385

master-id是6385的id,第一个参数为新节点的ip+端口    第二个为指定的主节点ip+端口在这里插入图片描述

4. 手动故障迁移

当想对集群中的主节点进行升级的话可以手动执行故障转移到从节点,避免集群可用性受影响。

在从节点执行命令:cluster failover

「执行过程」

查看节点信息就可以看到6386这个节点已经成为了主机点。

当给从节点发送cluster  failover 指令后,从节点会给主节点发送CLUSTERMSG_TYPE_MFSTART包。从节点请求主节点停止访问,从而对比两者的数据偏移量达到一致。

这时客户端不会连接我们淘汰的主节点,同时主节点向从节点发送复制偏移量,从节点得到复制偏移量后故障转移开始,接着通知主节点进行配置切换,当客户端在旧的master上解锁后重新连接到新的主节点上。在这里插入图片描述

六、故障转移原理篇

上文中我们测试了故障转移,主节点下线后从节点变为主节点,接下来剖析这个过程。

1. 故障发现到确认

集群中的每个节点会定期的给其它节点发送ping消息,接收方用pong作为回复。

如果在cluster-node-timeout的时间内ping消息一直失败,则会把接收方的节点标记为pfail状态也就是主观下线。

这个下线状态是不是很熟悉。没错,这个跟哨兵判断主节点是否异常有点相似。当一个哨兵发现主节点有问题时也会标记主节点客观下线(s_down)。  突然发现跑题了,尴尬.......

在这里插入图片描述在提一下哨兵,当一个哨兵认为主节点异常后标记主观下线,但是其它哨兵怎么能会同意,不能你说什么就是什么。都会去尝试连接异常的主节点,当半数以上的哨兵都认为主节点异常后会直接让其主节点客观下线。

同样集群也不会因为一个节点判断其状态为下线就行的,节点直接通过Gossip消息传播,集群中节点会不断收集故障节点的下线反馈并且存储到本地的故障节点下线报告中。当有半数以上的集群主节点都标记为主观下线后改变状态为客观下线。

最后向集群广播一条fail消息,通知所有节点将故障节点标记为客观下线。

例如:节点A发送ping到节点B通信异常后标记节点B为pfail,之后节点A会继续给节点C发送ping并且携带节点B的pfail信息然后节点C将节点B的故障保存到下线报告中。当下线报告数量大于有哈希槽主节点的一半数量以上后就会尝试客观下线。

2. 故障恢复(从节点从此翻身奴隶把歌唱)

当故障节点被定义为客观下线后,故障节点的所有从节点承担故障恢复的责任。

故障恢复是从节点通过定时任务发现自己的主机点客观下线后就会执行故障恢复流程。

「1. 资格检查」

所有的从节点都会进行检查与主节点最后的连接时间,断线时间大于cluster-node-time*cluster-slave-validity-factor时不具备故障转移的资格。

「2. 准备选举时间」

先说说为什么这里会有一个准备选举时间。

资格检查过后存在多个从节点,那么就需要使用不同的延迟选举时间来支持优先级。这里的优先级就是 以复制偏移量为基准,偏移量越大与故障主节点的延迟越小,那么就更有机会拥有替换主节点的机会。

主要的作用就是确保数据一致性最好的节点优先发起选举

「3.选举投票」

redis集群的投票机制没有采用从节点进行领导选举,这点切记不要跟哨兵搞混了。集群的投票机制都是持有槽的主机点进行投票的。

故障节点的从节点会广播一个FAILOVER_AUTH_REQUEST 数据包给所有的持有槽的主节点请求投票。

当主节点回复FAILOVER_AUTH_ACK投票后在NODE_TIMEOUT * 2的这段时间不能给其它的从节点投票

从节点获取到半数以上的投票后就会进行故障恢复阶段

「4. 故障转移」

选举成功的从节点取消复制变为主节点

删除故障节点的槽,并且将故障节点的槽委托到自己身上

向集群广播自己的pong消息,通知主机点的改变和接管了故障节点的槽信息。

你们想要的ssh的背景!!!

一篇利用俩个夜晚才弄完的redis哨兵文章,结果你们的关注点却不在文章本身,啊!小编心很痛

为了满足大家的要求,咔咔忍痛说一下如何设置亮瞎的背景。在这里插入图片描述咔咔使用的工具是xsheel在这里插入图片描述打开工具选择选项在这里插入图片描述接着到查看有个窗口透明就可以设置xsheel透明了。在这里插入图片描述对喽!你想的没错这就是桌面背景,是不是准备开始设置去了。那设置完了回来再把文章看完好吗?咔咔也需要各路大神给予技术点补充和辨错。

坚持学习、坚持写博、坚持分享是咔咔从业以来一直所秉持的信念。希望在偌大互联网中咔咔的文章能带给你一丝丝帮助。我们下期再见。

推荐:《redis教程

INFINITE ALBUM
INFINITE ALBUM

面向游戏玩家的生成式AI音乐

下载

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

23

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

68

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

162

2026.03.04

AI安装教程大全
AI安装教程大全

2026最全AI工具安装教程专题:包含各版本AI绘图、AI视频、智能办公软件的本地化部署手册。全篇零基础友好,附带最新模型下载地址、一键安装脚本及常见报错修复方案。每日更新,收藏这一篇就够了,让AI安装不再报错!

84

2026.03.04

Swift iOS架构设计与MVVM模式实战
Swift iOS架构设计与MVVM模式实战

本专题聚焦 Swift 在 iOS 应用架构设计中的实践,系统讲解 MVVM 模式的核心思想、数据绑定机制、模块拆分策略以及组件化开发方法。内容涵盖网络层封装、状态管理、依赖注入与性能优化技巧。通过完整项目案例,帮助开发者构建结构清晰、可维护性强的 iOS 应用架构体系。

113

2026.03.03

C++高性能网络编程与Reactor模型实践
C++高性能网络编程与Reactor模型实践

本专题围绕 C++ 在高性能网络服务开发中的应用展开,深入讲解 Socket 编程、多路复用机制、Reactor 模型设计原理以及线程池协作策略。内容涵盖 epoll 实现机制、内存管理优化、连接管理策略与高并发场景下的性能调优方法。通过构建高并发网络服务器实战案例,帮助开发者掌握 C++ 在底层系统与网络通信领域的核心技术。

29

2026.03.03

Golang 测试体系与代码质量保障:工程级可靠性建设
Golang 测试体系与代码质量保障:工程级可靠性建设

Go语言测试体系与代码质量保障聚焦于构建工程级可靠性系统。本专题深入解析Go的测试工具链(如go test)、单元测试、集成测试及端到端测试实践,结合代码覆盖率分析、静态代码扫描(如go vet)和动态分析工具,建立全链路质量监控机制。通过自动化测试框架、持续集成(CI)流水线配置及代码审查规范,实现测试用例管理、缺陷追踪与质量门禁控制,确保代码健壮性与可维护性,为高可靠性工程系统提供质量保障。

79

2026.02.28

Golang 工程化架构设计:可维护与可演进系统构建
Golang 工程化架构设计:可维护与可演进系统构建

Go语言工程化架构设计专注于构建高可维护性、可演进的企业级系统。本专题深入探讨Go项目的目录结构设计、模块划分、依赖管理等核心架构原则,涵盖微服务架构、领域驱动设计(DDD)在Go中的实践应用。通过实战案例解析接口抽象、错误处理、配置管理、日志监控等关键工程化技术,帮助开发者掌握构建稳定、可扩展Go应用的最佳实践方法。

62

2026.02.28

Golang 性能分析与运行时机制:构建高性能程序
Golang 性能分析与运行时机制:构建高性能程序

Go语言以其高效的并发模型和优异的性能表现广泛应用于高并发、高性能场景。其运行时机制包括 Goroutine 调度、内存管理、垃圾回收等方面,深入理解这些机制有助于编写更高效稳定的程序。本专题将系统讲解 Golang 的性能分析工具使用、常见性能瓶颈定位及优化策略,并结合实际案例剖析 Go 程序的运行时行为,帮助开发者掌握构建高性能应用的关键技能。

51

2026.02.28

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
进程与SOCKET
进程与SOCKET

共6课时 | 0.4万人学习

Redis+MySQL数据库面试教程
Redis+MySQL数据库面试教程

共72课时 | 7.1万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号