一.前言

我在《那些年用过的Redis集群架构(含面试解析)》一文里提到过,现在redis集群架构,redis cluster用的会比较多。

如下图所示

对于客户端请求的key,根据公式HASH_SLOT=CRC16(key) mod 16384,计算出映射到哪个分片上,然后Redis会去相应的节点进行操作!

那大家思考过,为什么有16384个槽么?

ps:CRC16算法产生的hash值有16bit,该算法可以产生2^16-=65536个值。换句话说,值是分布在0~65535之间。那作者在做mod运算的时候,为什么不mod65536,而选择mod16384?

其实我当初第一次思考这个问题的时候,我心里是这么想的,作者应该是觉得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个槽的更多相关文章

  1. 【原创】为什么Redis集群有16384个槽

    引言 我在<那些年用过的Redis集群架构(含面试解析)>一文里提到过,现在redis集群架构,redis cluster用的会比较多. 如下图所示 对于客户端请求的key,根据公式HAS ...

  2. 面试官:Redis集群有哪些方式,Leader选举又是什么原理呢?

    哈喽!大家好,我是小奇,一位不靠谱的程序员 小奇打算以轻松幽默的对话方式来分享一些技术,如果你觉得通过小奇的文章学到了东西,那就给小奇一个赞吧 文章持续更新 一.前言 作为一名Java程序员,Redi ...

  3. Redis总结(八)如何搭建高可用的Redis集群

    以前总结Redis 的一些基本的安装和使用,大家可以这这里查看Redis 系列文章:https://www.cnblogs.com/zhangweizhong/category/771056.html ...

  4. Redis 集群_主从复制_哨兵模型

    1 redis集群简介 1.1 集群的概念 所谓的集群,就是通过添加服务器的数量,提供相同的服务,从而让服务器达到一个稳定.高效的状态. 1.1.1 使用redis集群的必要性 问题:我们已经部署好了 ...

  5. Redis集群节点扩容及其 Redis 哈希槽

    Redis 集群中内置了 16384 个哈希槽,当需要在 Redis 集群中放置一个 key-value 时,redis 先对 key 使用 crc16 算法算出一个结果,然后把结果对 16384 求 ...

  6. Redis集群搭建方案(Linux)

    Redis简介 redis是一个key-value存储系统.和Memcached类似,它支持存储的value类型相对更多,包括string(字符串). list(链表).set(集合)和zset(有序 ...

  7. redis集群配置与管理

    Redis在3.0版本以后开始支持集群,经过中间几个版本的不断更新优化,最新的版本集群功能已经非常完善.本文简单介绍一下Redis集群搭建的过程和配置方法,redis版本是5.0.4,操作系统是中标麒 ...

  8. redis单点、redis主从、redis哨兵sentinel,redis集群cluster配置搭建与使用

    目录 redis单点.redis主从.redis哨兵 sentinel,redis集群cluster配置搭建与使用 1 .redis 安装及配置 1.1 redis 单点 1.1.2 在命令窗口操作r ...

  9. Linux 下redis 集群搭建练习

    Redis集群 学习参考:https://blog.csdn.net/jeffleo/article/details/54848428https://my.oschina.net/iyinghui/b ...

随机推荐

  1. Python 爬取 拉钩

    ... from urllib import request from urllib import parse from urllib.error import URLError import jso ...

  2. [luogu7736]路径交点

    对于两条路径,注意到每一个交点都会改变两者的上下关系,因此两条路径交点的奇偶性,仅取决于两者的起点和终点是否改变了上下关系(改变即为奇数) 类似地,对于整个路径方案,令$p_{i}$为以第一层的$i$ ...

  3. [luogu4607]反回文串

    参考ARC064F 令$h(n)=\begin{cases}n(n为奇数)\\\frac{n}{2}(n为偶数)\end{cases}$,$f(n)$定义与ARC064F相同,答案即$\sum_{d| ...

  4. [atARC109F]1D Kingdom Builder

    考虑最终有石子的位置的状态,判断一种状态是否可行 反过来,依次删除石子,删除条件是:当删除的石子是该段最后一个(即其两边都没有石子了),要求除其以外,每个连续段旁边的两个点都与其颜色不同 构造一种删除 ...

  5. mysql变成类型字段varchar值更新变长或变短底层文件存储原理

    为了搞清楚MySQL对于可变长度字段值修改时,如何高效操作数据文件的机制.之前一直模糊不清,网上也搜不到现成的答案.经过多方资料搜集整理.写出此文供大家一起参阅.由于涉及众多非常底层的知识,我假设读者 ...

  6. PL\SQL和PL/SQL Developer 12安装与配置

    安装: (1)在已有安装包的情况下,直接将安装包解压到文件夹下,注意不要解压缩到c:\programs Files(x86)的文件夹下,不能解压缩到有中文文件夹命名的文件夹下面 (2)没有安装包的情况 ...

  7. 【Redis】过期键删除策略和内存淘汰策略

    Redis 过期键策略和内存淘汰策略 目录 Redis 过期键策略和内存淘汰策略 设置Redis键过期时间 Redis过期时间的判定 过期键删除策略 定时删除 惰性删除 定期删除 Redis过期删除策 ...

  8. [源码解析] PyTorch分布式优化器(2)----数据并行优化器

    [源码解析] PyTorch分布式优化器(2)----数据并行优化器 目录 [源码解析] PyTorch分布式优化器(2)----数据并行优化器 0x00 摘要 0x01 前文回顾 0x02 DP 之 ...

  9. Java 性能优化的 50 个细节

    在JAVA程序中,性能问题的大部分原因并不在于JAVA语言,而是程序本身.养成良好的编码习惯非常重要,能够显著地提升程序性能. #尽量在合适的场合使用单例 使用单例可以减轻加载的负担,缩短加载的时间, ...

  10. 集合类——集合输出、栈和队列及Collections集合

    1.集合输出 在之前我们利用了toString()及get()方法对集合进行了输出,其实那都不是集合的标准输出,集合输出有四种方式:Iterator.ListIterator.Enumeration. ...