为什么Redis集群有16384个槽?(redis集群多少个槽)
mhr18 2024-11-01 12:18 27 浏览 0 评论
Redis集群通过引入16384个槽(slots)的概念来实现数据的分布式存储。
这个是结论,
在讨论具体的原因前,必须要清楚redis的集群的概念。
什么是Redis集群?
Redis集群是一种服务器Sharding(分片)技术,3.0版本开始正式提供。
Redis的哨兵模式基本已经可以实现高可用,读写分离 ,
但是在这种模式下每台Redis服务器都存储相同的数据,
很浪费内存,所以在redis3.0上加入了Cluster集群模式,
实现了Redis的分布式存储,
也就是说每台 Redis 节点上存储不同的内容。
如上图所示,Redis集群可以看成多个主从架构组合起来的,每一个主从架构可以看成一个节点(其中,只有master节点具有处理请求的能力,slave节点主要是用于节点的高可用)
集群的数据分片??????
前面讲到,
Redis集群通过分布式存储的方式解决了单节点的海量数据存储的问题,
对于分布式存储,
需要考虑的重点就是如何将数据进行拆分到不同的Redis服务器上。
常见的分区算法有hash算法、一致性hash算法,
关于这些算法这里就不多介绍。
如果要实现 Redis 数据的分片,我们有三种方案。
1>普通hash算法
- (客户端负载)第一种是在客户端实现相关的逻辑,例如用取模或者一致性哈希对key进行分片,查询和修改都先判断key的路由。
Jedis客户端提供了Redis Sharding的方案,并且支持连接池。
Sharded 分片的原理?怎么连接到某一个Redis服务:提供了一致性hash和md5散列两种hash算法,默认使用一致性hash算法。
并且为了使得请求能均匀的落在不同的节点上,Sharded Jedis会使用节点的名称(如果节点没有名称使用默认名称)虚拟化出160个虚拟节点。也可以根据不同节点的weight,虚拟化出160,weight个节点。
当客户端访问redis时,首先根据key计算出其落在哪个节点上,然后找到节点的ip和端口进行连接访问。
- (中间代理负载)第二种是把做分片处理的逻辑抽取出来,运行一个独立的代理服务,客户端连接到这个代理服务,代理服务做请求的转发。
- (服务端负载) 第三种就是基于服务端实现分为:普通hash算法,一致性hash算法,哈希槽Slot算法
如果是希望数据分布相对均匀的话,可以考虑哈希后取模。
将key使用hash算法计算之后:hash(key)%N,根据余数,决定映射到那一个节点。
优点就是比较简单,属于静态的分片规则。但是一旦节点数量变化,新增或者减少,由于取模的 N 发生变化, 数据需要重新分布和迁移。
2>一致性hash算法
- 把所有的哈希值空间组织成一个虚拟的圆环(哈希环),整个空间按顺时针方向组织。因为是环形空间,0 和 2^32-1 是重叠的(总共2^32个)。
1.先根据机器的名称或者 IP计算哈希值。
2.然后分布到哈希环中。查找时先根据key计算哈希值,得到哈希环中的位置。
3.最后顺时针找到第一个大于等于该哈希值的第一个Node,就是数据存储的节点。
- 优点是在加入和删除节点时只影响相邻的两个节点。
- 缺点是加减节点会造成部分数据无法命中
- 此外,针对于hash节点分散不均匀或者倾倒状态,采用一个节点分为多个虚拟节点做优化
- 所以一般用于缓存,而且用于节点量大的情况下,扩容一般增加一倍节点保障数据负载均衡。
3>哈希槽Slot算法
Redis 集群既没有用哈希取模,也没有用一致性哈希,而是用Hash槽来实现的。
Redis集群创建了 16384 个槽(slot),每个节点负责一定区间的slot。
Redis集群的哈希槽的分区
- Redis集群中有16384(2^14)个哈希槽(槽的范围是 0 -16383,哈希槽),将不同的哈希槽分布在不同的Redis节点上面进行管理,也就是说每个Redis节点只负责一部分区间的哈希槽。
对数据进行操作的时候:
- 集群会对使用CRC16算法对key进行计算并对16384取模 (slot = CRC16(key)%16384)
得到的结果就是Key-Value所放入的槽,通过这个槽值,去找对应的槽所对应的Redis节点。
然后直接到这个对应的节点上进行存取操作。
- 好处:(自动更新hash槽的映射数据关系)使用哈希槽的好处就在于可以方便的添加或者移除节点,并且无论是添加删除或者修改某一个节点,都不会造成集群不可用的状态。
- 当需要增加节点时,只需要把其他节点的某些哈希槽挪到新节点就可以了;
- 当需要移除节点时,只需要把移除节点上的哈希槽挪到其他节点就行了;
哈希槽分区的分析
集群的每个节点负责一部分hash槽,举个例子,比如当前集群有3个节点,那么:
节点 A 包含 0 到 5460 号哈希槽
节点 B 包含 5461 到 10922 号哈希槽
节点 C 包含 10923 到 16383 号哈希槽
这种结构很容易添加或者删除节点。
- (1)如果我想新添加个节点 D , 我需要从节点 A, B, C 中得部分槽到 D 上。
- (2)如果我想移除节点 A ,需要将 A 中的槽移到 B 和 C 节点上,然后将没有任何槽的 A 节点从集群中移除即可。
由于从一个节点将哈希槽移动到另一个节点并不会停止服务,所以无论添加删除或者改变某个节点的哈希槽的数量都不会造成集群不可用的状态。
注意:key 与 slot 的关系是永远不会变的,会变的只有 slot 和 Redis 节点的关系
怎么让相关的数据落到同一个节点上????????
在key里面加入{hash tag}即可。
Redis在计算槽编号的时候只会获取{}之间的字符串进行槽编号计算,
这样由于上面两个不同的键,{}里面的字符串是相同的,
因此他们可以被计算出相同的槽
客户端重定向
客户端连接到哪一台服务器?访问的数据不在当前节点上,怎么办?
比如在 7291 端口的 Redis 的 redis-cli 客户端操作:???????
127.0.0.1:7291> set qs 1
(error) MOVED 13724 127.0.0.1:7293
服务端返回 MOVED,也就是根据 key 计算出来的 slot 不归 7191 端口管理,而是 归 7293 端口管理,服务端返回 MOVED 告诉客户端去 7293 端口操作。
这个时候更换端口,用 redis-cli –p 7293 操作,才会返回 OK。这样客户端需要连接两次。或者用./redis-cli -c -p port 的命令(c 代表 cluster)自动重定向。
新增或下线了 Master 节点,数据怎么迁移(重新分配)?
因为 key 和 slot 的关系是永远不会变的,当新增了节点的时候,需要把原有的 slot 分配给新的节点负责,并且把相关的数据迁移过来。
新增的节点没有哈希槽,不能分布数据,在原来的任意一个节点上执行。
redis-cli --cluster reshard 127.0.0.1:7291
槽的迁移与指派命令:
CLUSTER ADDSLOTS 0 1 2 3 4 ... 5000
输入需要分配的哈希槽的数量(比如 500),和哈希槽的来源节点(可以输入 all 或 者 id)
以上内容基本就是集群的全部内容,那么我们继续聊下redis集群为什么有16384个槽?
平衡性能和灵活性:选择 16384 个槽是为了在管理上的便利性、数据分布的均匀性以及集群重新分片的灵活性之间寻找平衡。较小的槽数量会减少重分布灵活性,较大的槽数量则会增加管理的复杂度和数据移动的成本。
避免大规模数据迁移:通过较小的槽数量,当需要扩展或收缩集群时,可以减少因为节点变动导致的大规模数据迁移,使得集群能够更快地达到平衡状态。
提高故障转移速度:在发生节点故障时,较少的槽数量意味着较少的数据迁移,从而可以更快完成故障转移和恢复,保证集群的高可用性。
如何突破限制?
尽管 Redis 集群设计的 16384 个槽为集群的扩展和管理提供了便利,但在某些大规模应用场景下,可能需要进一步提高集群的管理效率或突破这个槽数量的限制。下面是几种可能的方法:
使用代理:通过引入代理层,如 Twemproxy 或 Redis Cluster Proxy,可以在客户端 Redis 集群之间提供一个抽象层从而在客户端看来像是在与一个单一的大容量 Redis 实例交互。这种方法可以在一定程度上隐藏槽数量的限制。
多集群部署在极端的大规模场景下,可以部署多个 Redis 集群,并在应用逻辑中分配不同的数据集到不同的集群。这种方式虽然增加了应用层的复杂性,但可以有效地扩展 Redis 的存储和处理能力。
自定义数据分片策略:在应用层实现自定义的数据分片逻辑,根据业务需求将数据分布到不同的 Redis 集群或节点上。这种方法需要开发者在应用层做更多的管理和维护工作,但提供了更大的灵活性。
总结
Redis 集群通过 16384 个槽的设计,在数据分布的均匀性、集群扩展的灵活性和管理的简便性之间找到了一种平衡。虽然这个设计对大多数应用来说已经足够,但在一些特殊场景下,通过使用代理、多集群部署或自定义数据分片策略等方法,可以在不改变 Redis 内部机制的情况下,进一步提高系统的规模和性能。
以上为全部内容。
相关推荐
- Java培训机构,你选对了吗?(java培训机构官网)
-
如今IT行业发展迅速,不仅是大学生,甚至有些在职的员工都想学习java开发,需求量的扩大,薪资必定增长,这也是更多人选择java开发的主要原因。不过对于没有基础的学员来说,java技术不是一两天就能...
- 产品经理MacBook软件清单-20个实用软件
-
三年前开始使用MacBookPro,从此再也不想用Windows电脑了,作为生产工具,MacBook可以说是非常胜任。作为产品经理,值得拥有一台MacBook。MacBook是工作平台,要发挥更大作...
- RAD Studio(Delphi) 本月隆重推出新的版本12.3
-
#在头条记录我的2025#自2024年9月,推出Delphi12.2版本后,本月隆重推出新的版本12.3,RADStudio12.3,包含了Delphi12.3和C++builder12.3最...
- 图解Java垃圾回收机制,写得非常好
-
什么是自动垃圾回收?自动垃圾回收是一种在堆内存中找出哪些对象在被使用,还有哪些对象没被使用,并且将后者删掉的机制。所谓使用中的对象(已引用对象),指的是程序中有指针指向的对象;而未使用中的对象(未引用...
- Centos7 初始化硬盘分区、挂载(针对2T以上)添加磁盘到卷
-
1、通过命令fdisk-l查看硬盘信息:#fdisk-l,发现硬盘为/dev/sdb大小4T。2、如果此硬盘以前有过分区,则先对磁盘格式化。命令:mkfs.文件系统格式-f/dev/sdb...
- 半虚拟化如何提高服务器性能(虚拟化 半虚拟化)
-
半虚拟化是一种重新编译客户机操作系统(OS)将其安装在虚拟机(VM)上的一种虚拟化类型,并在主机操作系统(OS)运行的管理程序上运行。与传统的完全虚拟化相比,半虚拟化可以减少开销,并提高系统性能。虚...
- HashMap底层实现原理以及线程安全实现
-
HashMap底层实现原理数据结构:HashMap的底层实现原理主要依赖于数组+链表+红黑树的结构。1、数组:HashMap最底层是一个数组,称为table,它存放着键值对。2、链...
- long和double类型操作的非原子性探究
-
前言“深入java虚拟机”中提到,int等不大于32位的基本类型的操作都是原子操作,但是某些jvm对long和double类型的操作并不是原子操作,这样就会造成错误数据的出现。其实这里的某些jvm是指...
- 数据库DELETE 语句,还保存原有的磁盘空间
-
MySQL和Oracle的DELETE语句与数据存储MySQL的DELETE操作当你在MySQL中执行DELETE语句时:逻辑删除:数据从表中标记为删除,不再可见于查询结果物理...
- 线程池—ThreadPoolExecutor详解(线程池实战)
-
一、ThreadPoolExecutor简介在juc-executors框架概述的章节中,我们已经简要介绍过ThreadPoolExecutor了,通过Executors工厂,用户可以创建自己需要的执...
- navicat如何使用orcale(详细步骤)
-
前言:看过我昨天文章的同鞋都知道最近接手另一个国企项目,数据库用的是orcale。实话实说,也有快三年没用过orcale数据库了。这期间问题不断,因为orcale日渐消沉,网上资料也是真真假假,难辨虚...
- 你的程序是不是慢吞吞?GraalVM来帮你飞起来性能提升秘籍大公开
-
各位IT圈内外的朋友们,大家好!我是你们的老朋友,头条上的IT技术博主。不知道你们有没有这样的经历:打开一个软件,半天没反应;点开一个网站,图片刷不出来;或者玩个游戏,卡顿得想砸电脑?是不是特别上火?...
- 大数据正当时,理解这几个术语很重要
-
目前,大数据的流行程度远超于我们的想象,无论是在云计算、物联网还是在人工智能领域都离不开大数据的支撑。那么大数据领域里有哪些基本概念或技术术语呢?今天我们就来聊聊那些避不开的大数据技术术语,梳理并...
- 秒懂列式数据库和行式数据库(列式数据库的特点)
-
行式数据库(Row-Based)数据按行存储,常见的行式数据库有Mysql,DB2,Oracle,Sql-server等;列数据库(Column-Based)数据存储方式按列存储,常见的列数据库有Hb...
- AMD发布ROCm 6.4更新:带来了多项底层改进,但仍不支持RDNA 4
-
AMD宣布,对ROCm软件栈进行了更新,推出了新的迭代版本ROCm6.4。这一新版本里,AMD带来了多项底层改进,包括更新改进了ROCm的用户空间库和AMDKFD内核驱动程序之间的兼容性,使其更容易...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- oracle位图索引 (74)
- oracle批量插入数据 (65)
- oracle事务隔离级别 (59)
- oracle 空为0 (51)
- oracle主从同步 (56)
- oracle 乐观锁 (53)
- redis 命令 (78)
- php redis (88)
- redis 存储 (66)
- redis 锁 (69)
- 启动 redis (66)
- redis 时间 (56)
- redis 删除 (67)
- redis内存 (57)
- redis并发 (52)
- redis 主从 (69)
- redis 订阅 (51)
- redis 登录 (54)
- redis 面试 (58)
- 阿里 redis (59)
- redis 搭建 (53)
- redis的缓存 (55)
- lua redis (58)
- redis 连接池 (61)
- redis 限流 (51)