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

文章目录

    • 前言
    • 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为面试赋能(持续更新中…)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

webpack-loader的使用

引入css后执行打包命令 "build": "npx webpack --config wk.config.js"发现报错: webpack默认只能处理js其他的像css,图片都需要借助loader来处理 css-loader loader可以用于对模块的源代码进行转换,可以把css看成一个模块&…

项目管理工具——使用甘特图制定项目计划的详细步骤

甘特图是一种直观的项目管理工具,它有助于我们清晰地展示任务安排、时间管理和项目的进度。以下是使用甘特图制定项目计划的详细步骤: 1、创建项目:首先,在进度猫中创建新的项目,并设置项目的时间、工作日等参数。根据…

Day37|贪心算法part06:738.单调递增的数字、968. 监控二叉树、贪心总结

738. 单调递增的数字 总体思想就是从后往前遍历,比较第i位和第i1位的大小,不符合顺序char[i]减1,i1位填9,找到需要填9的最先位置,然后填9。 class Solution {public int monotoneIncreasingDigits(int n) {String s …

请求分发场景下的鉴权问题

说明:记录一次对请求分发,无法登录系统的问题。 场景 如下,在此结构下,如何判断该用户是已登录的用户; 常规操作,用户登录后给用户发Token,同时将发放的Token存入到Redis中。要求用户后续请求…

halcon domain和region总结

1.domain是什么 在halcon中,ROI(Region Of Interest)被称为图像的域(domain)(参考《solution_guide_i.pdf》)。这个术语来自数学中的定义域,而图像就是函数,本函数负责将坐标映射到像素值,即f(x) gray这样…

计算机网络——TCP和UDP协议

目录 前言 前篇 引言 TCP与UDP之间的区别 TCP 三次握手 为什么要三次握手而不是两次握手? 丢包问题与乱序问题的解决 四次挥手 为什么客户端需要等待超时时间? UDP协议 TCP和UDP的主要区别 前言 本博客是博主用于复习计算机网络的博客&…

性能测试-数据库优化二(SQL的优化、数据库拆表、分表分区,读写分离、redis)

数据库优化 explain select 重点: type类型,rows行数,extra SQL的优化 在写on语句时,将数据量小的表放左边,大表写右边where后面的条件尽可能用索引字段,复合索引时,最好按复合索引顺序写wh…

NGO-VMD+皮尔逊系数+小波阈值降噪+重构

NGO-VMD皮尔逊系数小波阈值降噪重构 NGO-VMD皮尔逊系数小波阈值降噪重构代码获取戳此处代码获取戳此处 以西储大学轴承数据为例,进行VMD,且采用NGO进行K a参数寻优 并对分解分量计算皮尔逊相关系数筛选含噪声分量,对其进行小波软硬阈值降噪&a…

网络协议——OSPF(开放式最短路径优先)详解

1.什么是OSPF 开放式最短路径优先OSPF 是一种动态的高度可靠和高度可扩展的路由协议,用于构建大型网络中的动态路由系统 2. OSPF的协议号为:89 3. OSPF的特点: OSPF是链路状态协议使用了区域概念:减少路由选择协议对路由器CPU,…

电磁兼容导论翻译疑问

在读电磁兼容导论P71页时,发现在“注意“这句话翻译的和原文有疑问:我的理解是单边幅度谱是双边幅度谱的两倍。请大家帮忙看看应如何翻译。 英文原版:Note that all positive frequency components except the dc component in the two-side…

【计算机毕业设计】基于微信小程序的开发项目150套(附源码+演示视频+LW)

大家好!我是程序猿老A,感谢您阅读本文,欢迎一键三连哦。 🧡今天给大家分享200的微信小程序毕业设计,后台用Java开发,这些项目都经过精心挑选,涵盖了不同的实战主题和用例,可做毕业设…

解决mac本git安装后找不到命令的问题

不熟悉mac配置,折腾了半天,记录一下。 1.问题描述2.解决方法 1.问题描述 从https://sourceforge.net/projects/git-osx-installer/files/下载的git安装包: 安装时提示: 这里的解决办法是按住control键再打开文件安装。 安装完…

Linux内核之互斥锁mutex_init和自旋锁spin_lock区别及用法实例(四十六)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 优质专栏:多媒…

股权融资成本GLS模型计算

一、模型公式 式中: r 为股权融资成本 P为股价 B为每股净资产 FROE为预测每股净资产收益率 目标:求解股权融资成本r 二、模型口径参考来源 PS:实际以代码为准 ①FROE(预测每股净资产收益率): 资本市场开放与…

物联网实战--驱动篇之(五)TEA和AES加密算法

目录 一、前言 二、TEA算法 三、AES算法 四、加解密测试 五、安全性保障 一、前言 物联网的安全性是经常被提及的一个点,如果你的设备之间通讯没有加密的话,那么攻击者很容易就能获取并解析出报文的协议,从而根据攻击者的需要进行设备操…

c# refc# substring c# 反射c# split c# websocket c# datatable使用

在C#编程中,ref关键字、Substring方法、反射(Reflection)、Split方法、WebSocket通信以及DataTable的使用都是常见的技术和方法。下面我将逐一为您详解这些内容。 1. C# ref关键字 ref关键字在C#中用于按引用传递参数。这意味着当您将变量作…

当你的项目体积比较大?你如何做性能优化

在前端开发中,项目体积优化是一个重要的环节,它直接影响到网页的加载速度和用户体验。随着前端项目越来越复杂,引入的依赖也越来越多,如何有效地减少最终打包文件的大小,成为了前端工程师需要面对的挑战。以下是一些常…

vim卡死了,没有反应怎么办?

解决办法: 很有可能是你有个在window下的好习惯,没事儿就ctrl s保存文件。但是在vim里,ctrl s默认是发送一种流控制信号,通常用于停止终端的输出,所以你的屏幕就卡死了。 解决办法也很简单,按下ctrl q即…

机器学习前导——PyCharm PyTorch Python3 机器学习

机器学习前导——PyCharm & pytorch & Python3 & 机器学习 文章目录 前言PyCharmPyTorchPython3机器学习联系 前言 这学期选了《机器学习》,第一次接触,对一些专有名词很陌生。 PyCharm PyCharm是一款由JetBrains开发的软件&#xff0c…

python--递归算法篇

1、给定一个包含n1个整数的数组nums,其数字在1到n之间(包含1和n), 可知至少存在一个重复的整数,假设只有一个重复的整数,请找出这个重复的数 def repeat(ls:list) -> list:#把个数超过1的数&#xff0c…