Redis集群搭建准备,了解一致性哈希算法和哈希槽

一致性哈希是在哈希取余算法基础之上优化的,分布式缓存数据变动和映射问题,某个机器宕机了,分母数量改变了,自然取余数不对了。用于解决分布式缓存系统中的数据选择节点存储问题和数据选择节点读取问题以及在增删节点后减少数据缓存的消失范畴,防止雪崩的发生。

哈希槽是在redis cluster集群方案中采用的,redis cluster集群没有采用一致性哈希方案,而是采用数据分片中的哈希槽来进行数据存储与读取的。

一致性哈希
一致性hash是指将 “存储节点” 和 “数据” 都映射到一个首尾相连的hash环上。如果增删节点,仅影响该节点在hash环上顺时针相邻的后继节点,其他数据不会受到影响。

三步:

1:算法构建一致性哈希环。

对存储节点进行哈希计算,也就是对存储节点做哈希映射,比如根据节点的 IP 地址进行哈希(用ip地址对环上的节点个数进行hash,比如ip地址为1.2.3.4,节点个数N,那么可映射到第1234%N的位置上)

2:服务器IP节点映射。

当对数据进行存储或访问时,对数据进行哈希映射; 将存储的key进行hash(key),然后将其值要分布在这个闭合圆上。

一致性Hash算法使用 “取模法”,且是对 2^32 次方取模,其可表示的范围为:0 ~ 2^32-1。

3:key落到服务器的落键规则。

将数据key使用Hash函数计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针”行走”,第一台遇到的服务器就是其应该定位到的服务器!
比如:a、b、c三个key,经过哈希计算后,在环空间上的位置如下:key-a存储在node1,key-b存储在node2,key-c存储在node3。

与普通的hash算法有何不同?
普通的hash算法是对节点数进行hash,而一致性hash是对固定值2^32进行取模。

优点:

将数据key使用Hash函数计算出哈希值,并确定此数据在环上的位置,从此位置沿环顺时针”行走”,第一台遇到的服务器就是其应该定位到的服务器!
比如:a、b、c三个key,经过哈希计算后,在环空间上的位置如下:key-a存储在node1,key-b存储在node2,key-c存储在node3。一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。
新增服务器节点/删除服务器节点:
在hash环中新增服务器,也是通过hash算法确认分布,只需要移动一小部分数据即可;移除也是同理(比如下图中想删除4节点,只需把原本1~4节点之间的数据移动到2节点上即可)。

Redis集群搭建准备,了解一致性哈希算法和哈希槽

缺点:(数据倾斜)

但是一致性哈希算法不能够均匀的分布节点,会出现大量请求都集中在一个节点的情况,在这种情况下进行容灾与扩容时,容易出现雪崩的连锁反应。
当在服务器节点数量太少的时候,容易出现分布不均而导致数据倾斜。
例如:系统中只有两台服务器,此时必然造成大量数据集中到Node 2上,而只有极少量会定位到Node 1上。所以用一致性哈希算法时,节点太少容易出现数据倾斜,就达不到了分布式效果。其环分布如下

Redis集群搭建准备,了解一致性哈希算法和哈希槽

总结:一致性Hash算法,主要是考虑到分布式系统每个节点都有可能失效,并且新的节点很可能动态的增加进来的情况。如何保证当系统的节点数目发生变化的时候(新增/删减),我们的系统仍然能够对外提供良好的服务(不用停掉所有redis服务),这是值得考虑的!

哈希槽

哈希槽解决了数据均匀分布的问题,在数据和节点之间又加入了一层,把这层称之为哈希槽,用于管理数据和节点之间的关系,现在就相当于节点上放的是槽,槽里放数据。

Redis集群搭建准备,了解一致性哈希算法和哈希槽

槽解决的是粒度问题,相当于把粒度变大了,这样便于数据移动。

原理

  • 只是进行不重复的基数统计,不是集合也不保存数据,只记录数量而不是具体内容。
  • 有误差,非精准统计,牺牲准确率来换取空间,误差仅仅只是0.81%左右。误差来自Redis之父回答。

redis cluster采用数据分片的哈希槽来进行数据存储和数据的读取。redis cluster一共有2^14(16384)个槽,所有的master节点都会有一个槽区比如0~1000,槽数是可以迁移的。master节点的slave节点不分配槽,只拥有读权限。但是注意在代码中redis cluster执行读写操作的都是master节点,并不是读是从节点,写是主节点。

为什么是16384个槽?

hash方式:
一个redis集群包含 16384 个哈希槽,编号0-16383(0-2*14-1)。这些槽会分配给集群中的所有主节点,分配策略没有要求,可以指定哪些编号的槽分配给哪个主节点。集群会记录节点槽的对应关系,解决了节点和槽的关系后,接下来就需要对key求哈希值,然后对16384取余,余数是及,那么Key就落入对应的槽里。集群使用公式 CRC16(key) % 16384 来计算键 key 属于哪个槽。
一个redis节点包含N个槽,数据通过hash算法哈希到固定的槽里,所以槽只是决定了数据的存放位置,当多个数据hash出来的结果相同时,他们就被分配到相同的槽里,即也会映射到相同的服务节点上。

在握手成功后,两个节点之间会定期发送ping/pong消息,交换数据信息,在redis节点发送心跳包时需要把所有的槽信息放到这个心跳包里,以便让节点知道当前集群信息,在发送心跳包时使用char进行bitmap压缩后是2k(16384÷8÷1024=2kb),也就是说使用2k的空间创建了16k的槽数。
虽然使用CRC16算法最多可以分配65535(2^16-1)个槽位,65535=65k,压缩后就是8k(8 * 8 (8 bit) * 1024(1k) = 8K),也就是说需要需要8k的心跳包,作者认为这样做不太值得;并且一般情况下一个redis集群不会有超过1000个master节点,所以16k的槽位是个比较合适的选择。

Redis集群搭建准备,了解一致性哈希算法和哈希槽

再来一个图

Redis集群搭建准备,了解一致性哈希算法和哈希槽

①如果槽位为65536,发送心跳信息的消息头达8k,发送的心跳包过于庞大。
②redis的集群主节点数量基本不可能超过1000个。集群节点越多,心跳包的消息体内携带的数据越多。如果节点过1000个,也会导致网络拥堵。因此redis作者,不建议redis cluster节点数量超过1000个。
③槽位越小,节点少的情况下,压缩率高
Redis主节点的配置信息中,它所负责的哈希槽是通过一张bitmap的形式来保存的,在传输过程中,会对bitmap进行压缩,但是如果bitmap的填充率slots / N很高的话(N表示节点数),bitmap的压缩率就很低。
如果节点数很少,而哈希槽数量很多的话,bitmap的压缩率就很低。

哈希槽和一致性哈希相比
并不是闭合的,key的定位规则是根据CRC-16(key)%16384的值来判断属于哪个槽区,从而判断该key属于哪个节点,而一致性哈希是根据hash(key)的值来顺时针找第一个hash(ip)的节点,从而确定key存储在哪个节点。
一致性哈希是创建虚拟节点来实现节点宕机后的数据转移并保证数据的安全性和集群的可用性的。redis cluster是采用master节点有多个slave节点机制来保证数据的完整性的,master节点写入数据,slave节点同步数据。当master节点挂机后,slave节点会通过选举机制选举出一个节点变成master节点,实现高可用。但是这里有一点需要考虑,如果master节点存在热点缓存,某一个时刻某个key的访问急剧增高,这时该mater节点可能操劳过度而死,随后从节点选举为主节点后,同样宕机,进入fail状态。
扩容和缩容
一致性哈希算法在新增和删除节点后,数据会按照顺时针来重新分布节点。而redis cluster的新增和删除节点都需要手动来分配槽区。

为什么redis集群不采用一致性哈希算法?
一致性哈希的节点分布基于圆环,无法很好的手动控制数据分布,比如有些节点的硬件差,希望少存一点数据,这种很难操作(还得通过虚拟节点映射,总之较繁琐)。
而redis集群的槽位空间是可以用户手动自定义分配的,类似于 windows 盘分区的概念,可以手动控制大小。
其实,无论是一致性哈希还是哈希槽的方式,在增减节点的时候,都会对一部分数据产生影响,都需要我们迁移数据,当然,redis集群也提供了相关手动迁移槽数据的命令。

Original: https://www.cnblogs.com/wt645631686/p/16398332.html
Author: 温柔的风
Title: Redis集群搭建准备,了解一致性哈希算法和哈希槽

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/528952/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Linux的OpenLava配置

    OpenLava OpenLava是基于LSF早期的开源版本发展而来,其 免费、 开源、 兼容IBM LSF的工作负载调度器。当你需要执行某项业务时候(比如跑渲染之类的),当有服务…

    Linux 2023年6月6日
    095
  • 【XML】学习笔记第三章-namesapce

    命名空间概述 标记中出现了同名不同义的情况,极其容易造成含义混乱。命名空间就是由W3C制定的用于解决这类问题的。 【命名空间的作用】出现标记同名不同义情况时,避免含义混乱 XML技…

    Linux 2023年6月14日
    074
  • 阿里云Redis开发规范

    (1)【建议】: 可读性和可管理性 以业务名(或数据库名)为前缀(防止key冲突),用冒号分隔,比如业务名:表名:id <span class="hljs-sele…

    Linux 2023年5月28日
    0110
  • MySQL之多表查询、Navicat及pymysql

    一、多表查询 1.1 数据准备 — 建表 create table dep( id int primary key auto_increment, name varchar(20…

    Linux 2023年6月14日
    096
  • Redis 生产架构选型对比,一文整治选择困难症

    前言 在写开源项目的时候,想到了要支持多种redis部署方式,于是对于这块的生产环境的架构选型展开调研。 一、引擎版本 推荐使用更新的引擎版本以支持更多的特性, Redis 6.0…

    Linux 2023年6月8日
    080
  • HTS备份脚本

    #!/bin/bash #program:用于升级前后备份;看时间戳 #author:sundz #version:v1 20220610 创建脚本 备份mysql以及aboss程…

    Linux 2023年6月7日
    064
  • bochs(2.6.11)配置安装

    下载:https://bochs.sourceforge.io/ 建议下载2.6.11,下文一开始安装的2.7,但运行时有无法解决的错误。但是大致安装过程一致。 linux 提前安…

    Linux 2023年5月27日
    0121
  • 【Example】C++ 接口概念讲解及例子演示

    C++ 和 Java 不同的是,C++ 没有 interface 关键字。对于很多新手来说,C++ 当中接口的概念不容易像 Java 当中那样被理解。 然而接口是面向对象编程当中的…

    Linux 2023年6月13日
    085
  • 【异常】Jenkins构建任务控制台乱码,但是直接执行shell脚本却没有问题

    1 问题现象 构建各种问号 2 检查各种配置 查看Jenkins的文件编码为 ANSI_X3.4-1968 然后直接执行mvn -v命令显示的也不是UTF-8 3 解决方案,直接在…

    Linux 2023年5月28日
    0101
  • [ Python ] 音视频剪辑

    https://www.cnblogs.com/yeungchie/ 视频 提取视频 from moviepy.editor import * 从 MP4 文件提取 video =…

    Linux 2023年6月7日
    085
  • python 练习题:请利用循环依次对list中的每个名字打印出Hello, xxx!

    方法一: python;gutter:true; -<em>- coding: utf-8 -</em>- 请利用循环依次对list中的每个名字打印出Hel…

    Linux 2023年6月8日
    087
  • wait() 进程控制函数实现伪代码

    wait()的实现 父进程调用 wait() wait() { 进入系统调用 sys_wait() sys_wait () { for { x = true for (循环所有就绪…

    Linux 2023年6月7日
    0104
  • 开放平台架构指南

    1.前言 2010年前,大型社交网站如腾讯QQ、新浪微博都搭建了开放平台。中小型互联网公司接入开放平台,能够获取社交平台的海量用户,有效的降低获客成本,获得社交平台的其他能力。对于…

    Linux 2023年6月6日
    064
  • 查询windows日志

    系统日志可以用来查看系统的一些信息,比如警告、错误、验证、开关机等。 打开系统日志 按下快捷键 win+R,输入 eventvwr.exe,并点击确定 查询开关机记录 点击左侧 W…

    Linux 2023年6月8日
    0100
  • 【证券从业】金融基础知识-第五章 债券01

    注1:后续学习并整理到第八章,全书完结后再合并成一个笔记进行源文件分享 注2:本章内容巨多,大约分为两篇文章记录消化 posted @2022-06-08 01:30 陈景中 阅读…

    Linux 2023年6月13日
    064
  • Unicode、UTF-8、UTF-16 终于懂了

    计算机起源于美国,上个世纪,他们对英语字符与二进制位之间的关系做了统一规定,并制定了一套字符编码规则,这套编码规则被称为ASCII编码 ASCII 编码一共定义了128个字符的编码…

    Linux 2023年6月13日
    094
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球