【原创】为什么Redis集群有16384个槽
引言
我在《那些年用过的Redis集群架构(含面试解析)》一文里提到过,现在redis集群架构,redis cluster用的会比较多。
如下图所示
对于客户端请求的key,根据公式HASH_SLOT=CRC16(key) mod 16384
,计算出映射到哪个分片上,然后Redis会去相应的节点进行操作!
那大家思考过,为什么有16384个槽么?
ps
:CRC16
算法产生的hash值有16bit,该算法可以产生2^16-=65536个值。换句话说,值是分布在0~65535之间。那作者在做mod
运算的时候,为什么不mod
65536,而选择mod
16384?
其实我当初第一次思考这个问题的时候,我心里是这么想的,作者应该是觉得16384就够了,然后我就开始查这方面资料。
很幸运的是,这个问题,作者是给出了回答的!
地址如下:
https://github.com/antirez/redis/issues/2576
作者原版回答如下:
The reason is:
- Normal heartbeat packets carry the full configuration of a node, that can be replaced in an idempotent way with the old in order to update an old config. This means they contain the slots configuration for a node, in raw form, that uses 2k of space with16k slots, but would use a prohibitive 8k of space using 65k slots.
- At the same time it is unlikely that Redis Cluster would scale to more than 1000 mater nodes because of other design tradeoffs.
So 16k was in the right range to ensure enough slots per master with a max of 1000 maters, but a small enough number to propagate the slot configuration as a raw bitmap easily. Note that in small clusters the bitmap would be hard to compress because when N is small the bitmap would have slots/N bits set that is a large percentage of bits set.
因此,能看懂上面那段话的读者。这篇文章不用看了,因为作者讲的很清楚了。本文只是对上面那段话做一些解释而已。
正文
基础
我们回忆一下Redis Cluster
的工作原理!
这里要先将节点握手讲清楚。我们让两个redis节点之间进行通信的时候,需要在客户端执行下面一个命令
127.0.0.1:7000>cluster meet 127.0.0.1:7001
如下图所示
意思很简单,让7000节点和7001节点知道彼此存在!
在握手成功后,连个节点之间会定期发送ping/pong消息,交换数据信息,如下图所示。
在这里,我们需要关注三个重点。
- (1)交换什么数据信息
- (2)数据信息究竟多大
- (3)定期的频率什么样
到底在交换什么数据信息?
交换的数据信息,由消息体和消息头组成。
消息体无外乎是一些节点标识啊,IP啊,端口号啊,发送时间啊。这与本文关系不是太大,我不细说。
我们来看消息头,结构如下
注意看红框的内容,type表示消息类型。
另外,消息头里面有个myslots的char数组,长度为16383/8,这其实是一个bitmap,每一个位代表一个槽,如果该位为1,表示这个槽是属于这个节点的。
到底数据信息究竟多大?
在消息头中,最占空间的是 myslots[CLUSTER_SLOTS/8]
。这块的大小是:
16384÷8÷1024=2kb
那在消息体中,会携带一定数量的其他节点信息用于交换。
那这个其他节点的信息,到底是几个节点的信息呢?
约为集群总节点数量的1/10,至少携带3个节点的信息。
这里的重点是:节点数量越多,消息体内容越大。
消息体大小是10个节点的状态信息约1kb。
那定期的频率是什么样的?
redis集群内节点,每秒都在发ping消息。规律如下
- (1)每秒会随机选取5个节点,找出最久没有通信的节点发送ping消息
- (2)每100毫秒(1秒10次)都会扫描本地节点列表,如果发现节点最近一次接受pong消息的时间大于cluster-node-timeout/2 则立刻发送ping消息
因此,每秒单节点发出ping消息数量为
数量=1+10*num(node.pong_received>cluster_node_timeout/2)
那大致带宽损耗如下所示,图片来自《Redis运维与实现》
讲完基础知识以后,我们可以来看作者的回答了。
回答
(1)如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。
如上所述,在消息头中,最占空间的是 myslots[CLUSTER_SLOTS/8]
。
当槽位为65536时,这块的大小是:
65536÷8÷1024=8kb
因为每秒钟,redis节点需要发送一定数量的ping消息作为心跳包,如果槽位为65536,这个ping消息的消息头太大了,浪费带宽。
(2)redis的集群主节点数量基本不可能超过1000个。
如上所述,集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者,不建议redis cluster节点数量超过1000个。
那么,对于节点数在1000以内的redis cluster集群,16384个槽位够用了。没有必要拓展到65536个。
(3)槽位越小,节点少的情况下,压缩比高
Redis主节点的配置信息中,它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中,会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。
如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。
ps
:文件压缩率指的是,文件压缩前后的大小比。
综上所述,作者决定取16384个槽,不多不少,刚刚好!
总结
希望大家有所收获!
【原创】为什么Redis集群有16384个槽的更多相关文章
- 为什么Redis集群有16384个槽
一.前言 我在<那些年用过的Redis集群架构(含面试解析)>一文里提到过,现在redis集群架构,redis cluster用的会比较多. 如下图所示 对于客户端请求的key,根据公式H ...
- 面试官:Redis集群有哪些方式,Leader选举又是什么原理呢?
哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 作为一名Java程序员,Redi ...
- Redis总结(八)如何搭建高可用的Redis集群
以前总结Redis 的一些基本的安装和使用,大家可以这这里查看Redis 系列文章:https://www.cnblogs.com/zhangweizhong/category/771056.html ...
- Redis 集群_主从复制_哨兵模型
1 redis集群简介 1.1 集群的概念 所谓的集群,就是通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定.高效的状态. 1.1.1 使用redis集群的必要性 问题:我们已经部署好了 ...
- Redis集群节点扩容及其 Redis 哈希槽
Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求 ...
- Redis集群搭建方案(Linux)
Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串). list(链表).set(集合)和zset(有序 ...
- redis集群配置与管理
Redis在3.0版本以后开始支持集群,经过中间几个版本的不断更新优化,最新的版本集群功能已经非常完善.本文简单介绍一下Redis集群搭建的过程和配置方法,redis版本是5.0.4,操作系统是中标麒 ...
- redis单点、redis主从、redis哨兵sentinel,redis集群cluster配置搭建与使用
目录 redis单点.redis主从.redis哨兵 sentinel,redis集群cluster配置搭建与使用 1 .redis 安装及配置 1.1 redis 单点 1.1.2 在命令窗口操作r ...
- Linux 下redis 集群搭建练习
Redis集群 学习参考:https://blog.csdn.net/jeffleo/article/details/54848428https://my.oschina.net/iyinghui/b ...
随机推荐
- ping(网络诊断工具)
ping(网络诊断工具) Ping是Windows下的一个命令,在Unix和Linux下也有这个命令.ping也属于一个通信协议,是TCP/IP协议的一部分.利用"ping"命令可 ...
- java练习---9
//程序员:罗元昊 2017.10.22 package cn.lyh; import com.rupeng.game.GameCore; public class L implements Runn ...
- <<Modern CMake>> 翻译 2.2 CMake 编程
<<Modern CMake>> 翻译 2.2 CMake 编程 流程控制 CMake有一个 if 语句, 经年累月之后,现在它已经相当复杂. 您可以在 if 语句中使用全大写 ...
- Apache ActiveMQ 实践 <二>
一.订阅/发布模式 1.生产者 /** * 消息生产者 * */public class JMSProducer { private static final String USERNAME=Acti ...
- 完美解决windows10磁盘占用100%并出现卡顿、假死无反应
完美解决windows10磁盘占用100%并出现卡顿.假死无反应 想必大家也跟我一样,自从用win10系统以后经常会出现这种情况:磁盘突然占用100%然后开始出现假死现象,电脑卡住,点击任何软件没反应 ...
- 一道看似简单的go程序的深入分析
先上代码: func main() { var a [10]int for i := 0; i < 10; i++ { go func(i int) { for { a[i]++ } }(i) ...
- spring boot 学习笔记(二)之打包
一.叙述 spring boot 在 pom 中可以配置成 packaging 为 jar ,这样打包出来的就是一个 jar 包,可以通过 Java 命令直接运行, Java 命令为: java - ...
- JS 中获得根目录
/*** * 获得根目录 * @returns */ function getRootPath() { var strFullPath = window.document.location.href; ...
- 异步编程CompletableFuture实现高并发系统优化之请求合并
先说场景: 根据Redis官网介绍,单机版Redis的读写性能是12万/秒,批量处理可以达到70万/秒.不管是缓存或者是数据库,都有批量处理的功能.当我们的系统达到瓶颈的时候,我们考虑充分的压榨缓存和 ...
- S2:.net
1.net框架结构 主要包含公共语言运行时(CLR)和框架类库(.NET Framework 类库 ,FCL) 2.CLR 1.对于一个将要面向.NET平台进行开发的人来说,了解一下.NET平台的整 ...