Redis从入门到精通(十五)Redis分布式缓存(三)Redis分片集群的搭建和原理分析

news2025/1/14 4:13:11

文章目录

    • 前言
    • 5.4 分片集群
      • 5.4.1 搭建分片集群
      • 5.4.2 散列插槽
      • 5.4.3 集群伸缩
        • 5.4.3.1 需求分析
        • 5.4.3.2 创建新的Redis实例
        • 5.4.3.3 添加新节点到Redis集群
        • 5.4.3.4 转移插槽
      • 5.4.4 故障转移
        • 5.4.4.1 自动故障转移
        • 5.4.4.2 手动故障转移
      • 5.4.5 RedisTemplate
    • 5.5 小结

前言

Redis分布式缓存系列文章:

Redis从入门到精通(十三)Redis分布式缓存(一)RDB和AOF持久化、Redis主从集群的搭建与原理分析
Redis从入门到精通(十四)Redis分布式缓存(二)Redis哨兵集群的搭建和原理分析

5.4 分片集群

主从和哨兵可以解决高可用、高并发读的问题,但是依然有两个问题没有解决:海量数据存储问题、高并发写的问题。这两个问题可以通过分片集群来解决。

5.4.1 搭建分片集群

分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个master包含1个slave节点,实际上master节点及其slave节点的数量可以更多。其结构如下:

在同一台虚拟机开启6个Redis实例,模拟分片集群,其信息如下:

IP端口角色
192.168.146.1288001master
192.168.146.1288002master
192.168.146.1288003master
192.168.146.1289001slave
192.168.146.1289002slave
192.168.146.1289003slave

搭建步骤如下:

  • 1)在/usr/local/redis_sharding中创建6个目录,名字分别是8001、8002、8003、9001、9002、9003:

  • 2)在6个目录下分别创建配置文件redis.conf,其内容如下(以8001为例,其余端口应与所在目录一致):
# /usr/local/redis_sharding/8001/redis.conf

# 端口
port 8001
# 开启集群功能
cluster-enabled yes
# 集群的配置文件名称,不需要我们创建,由redis自己维护
cluster-config-file /usr/local/redis_sharding/8001/nodes.conf
# 节点心跳失败的超时时间
cluster-node-timeout 5000
# 持久化文件存放目录
dir /usr/local/redis_sharding/8001
# 绑定地址
bind 0.0.0.0
# 让redis后台运行
daemonize yes
# 注册的实例ip
replica-announce-ip 192.168.146.128
# 保护模式
protected-mode no
# 数据库数量
databases 1
# 日志
logfile /usr/local/redis_sharding/8001/run.log
  • 3)在6个目录下分别启动服务
/usr/local/bin/redis-server /usr/local/redis_sharding/8001/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/8002/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/8003/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/9001/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/9002/redis.conf
/usr/local/bin/redis-server /usr/local/redis_sharding/9003/redis.conf

6个实例启动后,其进程如下:

  • 4)创建集群

虽然服务启动了,但是目前每个服务之间都是独立的,没有任何关联,还需要执行命令来创建集群。

Redis5.0之前集群命令都是用redis安装包下的src/redis-trib.rb来实现的。案例使用的是Redis7.2.4版本,集群管理已经集成到了redis-cli中,格式如下:

redis-cli --cluster create --cluster-replicas 1 192.168.146.128:8001 192.168.146.128:8002 192.168.146.128:8003 192.168.146.128:9001 192.168.146.128:9002 192.168.146.128:
9003

命令说明:

  • redis-cli --cluster:集群操作命令

  • create:创建集群

  • --cluster-replicas 1:指定集群中每个master的slave节点个数为1,那么节点总数÷(replicas + 1)得到的就是master的数量。

    本例中即6÷(1 + 1)=3,因此上述命令列出的节点列表中的前3个就是master节点(8001、8002、8003),其他节点都是slave节点,随机分配到不同的master。

命令执行后:

可见,9002分配给了8001,9003分配给了8002,9001分配给了8003。输入yes继续执行:

集群创建完成。通过以下命令查看集群状态:

redis-cli -p 8001 cluster nodes

  • 5)测试

尝试连接8001节点,并存储一个数据:

redis-cli -p 8001

127.0.0.1:8001> set age 21
OK
127.0.0.1:8001> get age
"21"
127.0.0.1:8001> set name aaa
(error) MOVED 5798 192.168.146.128:8002

可以发现,测试过程中出现了错误,提示我们要去8002节点操作。

实际上在进行集群操作时,需要给redis-cli命令加上-c参数:

127.0.0.1:8001> set name aaaaaa
-> Redirected to slot [5798] located at 192.168.146.128:8002
OK
192.168.146.128:8002> get name
"aaaaaa"

5.4.2 散列插槽

Redis会把每一个master节点映射到0~16383共16384个插槽上,在创建集群时就可以看到具体的分配情况:

Redis会根据Key值的有效部分计算插槽值(利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是插槽值),然后将数据存到插槽值对应的master节点上。 Key值的有效部分分两种情况:

  • Key中包含"{}",且“{}”中至少包含1个字符,则“{}”中的部分是有效部分;
  • key中不包含“{}”,整个key都是有效部分。

例如:

127.0.0.1:8001> set test aaa
-> Redirected to slot [6918] located at 192.168.146.128:8002
OK

在8001节点上执行set test aaa时,对test进行插槽值计算得到的结果是6918,因此要存储到8002节点上。

127.0.0.1:8003> get test
-> Redirected to slot [6918] located at 192.168.146.128:8002
"aaa"

在8003节点上执行get test时,也要根据插槽值去8002节点上查找。

5.4.3 集群伸缩

Redis提供了很多操作集群的命令,可以通过redis-cli --cluster help命令查看具体有哪些。

5.4.3.1 需求分析

现在有一个需求:向集群中添加一个新的master节点,并向其中存储test=bbb。

换句话说,就是添加一个新的master节点到集群中,并将部分插槽分配到给新的master节点。

5.4.3.2 创建新的Redis实例

/usr/local/redis_sharding目录下创建文件夹8004,并拷贝配置文件redis.conf,将其中的端口、目录等配置修改为8004:

启动8004节点:

/usr/local/bin/redis-server /usr/local/redis_sharding/8004/redis.conf

5.4.3.3 添加新节点到Redis集群

执行以下命令:

redis-cli --cluster add-node 192.168.146.128:8004 192.168.146.128:8001

查看集群状态:

redis-cli -p 8001 cluster nodes

如图,8004节点加入了集群,并且是一个master节点,但是其插槽数量为0,因此没有任何数据可以保存到8004节点上。

5.4.3.4 转移插槽

由前面的测试可知,Key值为"test"时其插槽值为6918,我们可以将5461~7461共2000个插槽由8002转移到8004,其命令格式为:

具体的操作步骤如下:

执行以下命令:

redis-cli --cluster reshard 192.168.146.128:8001

得到如下反馈:

询问要移动多少个插槽,我们计划是2000个:

询问要使用哪个节点来接收这些插槽,我们计划是8004节点,因此这里输入8004节点的ID:

询问要从哪个节点移动这些插槽,我们计划是8002节点,因此这里输入8002节点的ID:

如果这里没有输入8002节点的ID,而是输入all,则代表从全部master节点中各移动一部分。

然后再输入done,完成插槽移动的准备工作:

询问是否确认转移,输入yes,开始执行插槽的移动。移动完成后,再次查看集群的状态:

可见,插槽5461~7460以从8002节点移动到了8004节点。

下面进行测试:

127.0.0.1:8001> set test bbb
-> Redirected to slot [6918] located at 192.168.146.128:8004
OK

可见,数据已成功保存到8004节点,需求成功实现。

5.4.4 故障转移

目前,8001、8002、8003、8004都是master节点,如果其中一个实例宕机,会发生什么呢?

5.4.4.1 自动故障转移

执行以下命令,停止8002实例:

redis-cli -p 8002 shutdown

再查询集群状态,集群已识别到8002宕机,并把9001实例提升为master:

当8002再次启动时,自动成为slave节点:

5.4.4.2 手动故障转移

在某个slave节点上执行cluster failover命令,可以手动让集群中的某个master节点宕机,然后自己提升为master节点,实现无感知的数据迁移。

例如,在进行自动故障转移时,8002节点成为了slave节点。我们可以在8002节点上执行cluster failover命令,就可以重新夺回master的地位。

127.0.0.1:8002> cluster failover
OK

查看集群状态:

可见,8002节点重新夺回master地位,9001节点降为slave节点。

5.4.5 RedisTemplate

RedisTemplate底层同样基于lettuce实现了对Redis分片集群的支持,使用步骤与主从集群基本一致,只是在配置文件application.yml中略有差异:

# src/main/resources/application.yml

spring:
  redis:
    cluster:
      nodes:
        - 192.168.146.128:8001
        - 192.168.146.128:8002
        - 192.168.146.128:8003
        - 192.168.146.128:8004
        - 192.168.146.128:9001
        - 192.168.146.128:9002
        - 192.168.146.128:9003

下面做个简单的测试:调用/redis/set/test/ccc接口,由日志可知写操作由master节点8004实例完成,这个之前的测试结果是一致的:

5.5 小结

第5章到此就学习完毕了,本章的主题是:Redis分布式缓存。回顾一下本章的学习的内容:

(十三)RDB、AOF持久化的原理;Redis主从复制集群的搭建和原理分析。
(十四)Redis哨兵集群的搭建和原理分析。
(十五)Redis分片集群的搭建和原理分析。

更多内容请查阅分类专栏:Redis从入门到精通

感兴趣的读者还可以查阅我的另外几个专栏:

  • SpringBoot源码解读与原理分析(已完结)
  • MyBatis3源码深度解析(已完结)
  • 再探Java为面试赋能(持续更新中…)

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

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

相关文章

【单片机毕业设计8-基于stm32c8t6的RFID校园门禁系统】

【单片机毕业设计8-基于stm32c8t6的RFID校园门禁系统】 前言一、功能介绍二、硬件部分三、软件部分总结 前言 🔥这里是小殷学长,单片机毕业设计篇8基于stm32的RFID校园门禁系统 🧿创作不易,拒绝白嫖可私 一、功能介绍 -----------…

[Python图像识别] 五十二.水书图像识别 (2)基于机器学习的濒危水书古文字识别研究

该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。目前我进入第二阶段Python图像识别,该部分主要以目标检测、图像…

亚远景科技-ASPICE 4.0-HWE硬件过程的范围 The Technical Scope of HW process

ASPICE 4.0中的HWE process是电气和电子硬件的技术范畴,涵盖了硬件工程中的需求分析、设计和验证活动,但不包括以下活动: 1. 系统级工程过程。既不包括机电一体MECHATRONIC,也不包括ECU特定电子控制单元的开发。 2. 硬件采购过程…

Redis 与 MySQL 数据一致性问题

1. 什么是数据库与缓存一致性 数据一致性指的是: 缓存中存有数据,缓存的数据值 数据库中的值;缓存中没有该数据,数据库中的值 最新值。 反推缓存与数据库不一致: 缓存的数据值 ≠ 数据库中的值;缓存或…

什么是One-Class SVM

1. 简介 单类支持向量机,简称One-Class SVM(One-Class Support Vector Machine),是一种用于异常检测的监督学习算法。其主要目标是找出数据集中的异常或罕见样本,而不需要大量的正常样本用于训练。这使其在处理高维数据和非常稀疏的异常检测问…

AutoCAD之DWF三维信息提取---linux编译篇

1. 权限 1.1 给文件添加执行权限 chmod x autogen.sh1.2.给当前文件下的所有文件改变为读写执行权限 chmod 777 * -R 2.环境安装 2.1安装automake 1.4.1 安装链接 安装中遇到的问题及解决 2.2安装autoconf 2.3 安装libtool 2.4 安装Cmake(CMake包含) cmake安装在cent…

GMSSL-通信

死磕GMSSL通信-C/C++系列(一) 最近再做国密通信的项目开发,以为国密也就简单的集成一个库就可以完事了,没想到能有这么多坑。遂写下文章,避免重复踩坑。以下国密通信的坑有以下场景 1、使用GMSSL guanzhi/GmSSL进行通信 2、使用加密套件SM2-WITH-SMS4-SM3 使用心得 ​…

影响小程序SSL证书收费标准的因素有哪些?

在当今互联网时代,移动应用发展日新月异,小程序逐渐成为广大企业和个人开发者的心仪之选。然而,伴随小程序的广泛应用,安全问题和用户信任显得尤为关键。为了确保小程序的信息传输安全,SSL证书成为了一项基础配置。那么…

【C++题解】1028 - 输入一个三位数,把个位和百位对调后输出

问题:1028 - 输入一个三位数,把个位和百位对调后输出 类型:基础问题 题目描述: 输入一个三位自然数,然后把这个数的百位数与个位数对调,输出对调后的数。 输入: 输入一行,只有一…

独一无二:探索单例模式在现代编程中的奥秘与实践

设计模式在软件开发中扮演着至关重要的角色,它们是解决特定问题的经典方法。在众多设计模式中,单例模式因其独特的应用场景和简洁的实现而广受欢迎。本文将从多个角度详细介绍单例模式,帮助你理解它的定义、实现、应用以及潜在的限制。 1. 什…

C++格式化输出开源库fmt入手教程

fmt项目快速上手指南 1. cmake环境配置 include(FetchContent) FetchContent_Declare(fmtGIT_REPOSITORY https://github.com/fmtlib/fmtGIT_TAG 10.0.0GIT_SHALLOW TRUE) # 1. 下载fmt库 FetchContent_MakeAvailable(fmt)add_executable(fmt_guide main.cpp) # 2. 链接fmt库…

Java 自定義 List<T> 分頁工具

Java 自定義 List 分頁工具 PS: T可修改为对应的实体 rt com.google.common.collect.Lists;import java.util.Arrays; import java.util.Collections; import java.util.List;/*** ClassName: MyPageHelper* Descripution: List<T>分頁工具**/ public class MyPageHelp…

自动化测试(selenium篇)

这次我们来介绍selenium 我们主要来讲解这几个要点 1.什么是自动化测试 2.什么是selenium 3.为什么来讲selenium 4.selenium的环境搭建 5.selenium的 API 1.什么是自动化测试 自动化测试指软件测试的自动化&#xff0c;在预设状态下运行应用程序或者系统&#xff0c;预设条…

Android Studio 使用Flutter开发第一个Web页面(进行中)

附上Flutter官方文档 1、新建Flutter项目&#xff08;需要勾选web选项&#xff09; 新建项目构成为&#xff1a; 2、配置 Flutter 使用 path 策略 官方文档 在main.dart中&#xff0c;需要导入flutter_web_plugins/url_strategy.dart包&#xff0c;并在main(){}函数中usePath…

水经微图IOS版5.2.0发布

随时随地&#xff0c;微图一下&#xff01; 水经微图&#xff08;简称“微图”&#xff09;IOS新版已上线。 在该版本中主要新增图层树节点排序功能、常规&#xff08;矩形、圆、椭圆、扇形&#xff09;绘制功能、地形夸张等主要功能。 当前版本 当前版本号为&#xff1a;5…

html-蜘蛛

<!doctype html> <html> <head> <meta charset"utf-8"> <title>彩虹蜘蛛-jq22.com</title> <script src"http://www.jq22.com/jquery/jquery-1.10.2.js"></script> <style> </style> </he…

Day:007(2) | Python爬虫:高效数据抓取的编程技术(scrapy框架使用)

Scrapy 数据的提取 Scrapy有自己的数据提取机制。它们被称为选择器。我们可以通过使用的选择器re、xpath、css提取数据 提示 不用再安装与引入Xpath,BS4 获得选择器 Response对象获取 正常使用 response.selector.xpath(//span/text()).get() response.selector.css(span::…

flask毕业设计选题管理系统python+django_96r19

本系统选择编程语言。Pymysql是封装了MySQL驱动的Python驱动一个能使Python连接到MySQL的库。Python语言官方规范访问数据库的统一接口规范(Python DB-API)&#xff0c;防止在使用不同数据库时&#xff0c;由于底层数据库技术不同造成接口程序紊乱的问题。通过本次系统设计可以…

处理json文件,并将数据汇总至Excel表格

从scores.jason文件中读取学生信息,输出学生的学号&#xff0c;姓名&#xff0c;各科成绩&#xff0c;平均分, 各科标准差 效果&#xff1a; # # 从scores.jason文件中读取学生信息,输出学生的学号&#xff0c;姓名&#xff0c;各科成绩&#xff0c;平均分, 各科标准差 impor…

K8S哲学 - 常见的资源类型

资源类型 namespace kubectl apply 和 kubectl create kubectl apply是声明式的 和 kubectl create是命令式的对吗 deployment 和 job的区别 k8s 的 lable 的意义