分布式缓存原理----Hash环/一致性Hash原理/Hash槽

2023-11-12

Memcached:为分布式客户端做分发,hash环

TWY Redis:为分布式客户端做分发 ,hash环

Redis Cluster:点对点                      ,2Khash槽

当前,Memcached、Redis这类分布式kv缓存已经非常普遍。从本篇开始,本系列将分析分布式缓存相关的原理、使用策略和最佳实践。

我们知道Memcached的分布式其实是一种“伪分布式”,也就是它的服务器结点之间其实是相互无关联的,之间没有网络拓扑关系,由客户端来决定一个key是存放到哪台机器。

具体来讲,假设我有多台memcached服务器,编号分别为m0,m1,m2,…。对于一个key,由客户端来决定存放到哪台机器,那最简单的hash公式就是 key % N,其中N是机器的总数。

但这有个问题,一旦机器数变少,或者增加机器,N发生变化,那之前存放的数据就全部无效了。因为你按照新的N值取模计算出的机器编号,和当时按旧的N值取模算出的机器编号肯定是不等的,也就意味着绝大部分缓存会失效。

这个问题的解决办法就是用1种特别的Hash函数,尽可能使得,增加机器/减少机器时,缓存失效的数目降到最低,这就是Hash环,或者叫一致性Hash。

Hash环
上面说的Hash函数,只经过了1次hash,即把key hash到对应的机器编号。 
而Hash环有2次Hash: 
(1)把所有机器编号hash到这个环上 
(2)把key也hash到这个环上。然后在这个环上进行匹配,看这个key和哪台机器匹配。

具体来讲,如下:

假定有这样一个Hash函数,其值空间为(0到2的32次方-1) ,也就是说,其hash值是个32位无整型数字 ,这些数字组成一个环。

然后,先对机器进行hash(比如根据机器的ip),算出每台机器在这个环上的位置; 再对key进行hash,算出该key在环上的位置,然后从这个位置往前走,遇到的第一台机器就是该key对应的机器,就把该(key, value) 存储到该机器上。

数据不均匀问题
当你机器不多的时候,很可能出现几台机器在环上面贴的很近,不是在环上均匀分布。这将会导致大部分数据,都会集中在某1台机器上。

为了解决这个问题,可以引入“虚拟机器”的概念,也就是说:1台机器,我在环上面计算出多个位置。怎么弄呢? 假设用机器的ip来hash,我可以在ip后面加上几个编号, ip_1, ip_2, ip_3, .. 把1台物理机器生个多个虚拟机器的编号。

数据首先映射到“虚拟机器上”,再从“虚拟机器”映射到物理机器上。因为虚拟机器可以很多,在环上面均匀分布,从而保证数据均匀分布到物理机器上面。

上面我们提到了服务器的机器增加、减少,问题是客户端怎么知道呢?

一种笨办法就是手动的,当服务器机器增加、减少时候,重新配置客户端,重启客户端。

另外一种,就是引入ZK,服务器的节点列表注册到ZK上面,客户端监听ZK。发现结点数发生变化,自动更新自己的配置。

当然,不用ZK,用一个其他的中心结点,只要能实现这种更改的通知,也是可以的。

但从Redis 3.0开始,引入了Redis Cluster,从此Redis进入了真正的“分布式集群“时代。而在“集群角度“,可以说Redis已经和Memcached有了很多重大的区别。

面这个表,从“集群角度“比较了2者的重大区别:
 

 

 

P2P架构
P2P模式,无中央结点,结点之间通过一个称之为Gossip的协议进行通信。

16384个hash槽
不同于Memcached的一致性Hash,Redis准备了16384个hash槽,类似于Memcached Hash环上的一个个位置。 
这16384个hash槽被分配给不同节点,存放数据时,根据数据的key计算出所在的槽,再根据槽找到对应的机器。hash函数为:CRC16(key) % 16384。

为什么是16384?
很显然,我们需要维护节点和槽之间的映射关系,每个节点需要知道自己有哪些槽,并且需要在结点之间传递这个消息。

为了节省存储空间,每个节点用一个Bitmap来存放其对应的槽: 
2k = 2*1024*8 = 16384,也就是说,每个结点用2k的内存空间,总共16384个比特位,就可以存储该结点对应了哪些槽。然后这2k的信息,通过Gossip协议,在结点之间传递。

客户端存储路由信息
对于客户端来说,维护了一个路由表:每个槽在哪台机器上。这样存储(key, value)时,根据key计算出槽,再根据槽找到机器。

无损扩容
虽然Hash环可以减少扩容时失效的key的数量,但毕竟有丢失。而在redis-cluster中,当新增机器之后,槽会在机器之间重新分配,同时被影响的数据会自动迁移,从而做到无损扩容。

主从复制
redis-cluster也引入了master-slave机制,从而提供了fail-over机制,这很大程度上解决了“缓存雪崩“的问题。关于这个,后面有机会再详细阐述。


 

 

 

 

 

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

分布式缓存原理----Hash环/一致性Hash原理/Hash槽 的相关文章

  • 自学Python能学会吗?

    这是一个非常好的问题 作为一名IT从业者 同时也是一名教育工作者 我来回答一下 首先 随着当前Python语言的应用越来越普遍 很多职场人和大学生都希望能够通过掌握Python语言来提升职场价值和岗位竞争力 由于Python语言本身比较简单
  • FreeRTOS-信号量详解

    作者简介 嵌入式入坑者 与大家一起加油 希望文章能够帮助各位 个人主页 rivencode的个人主页 系列专栏 玩转FreeRTOS 保持学习 保持热爱 认真分享 一起进步 目录 前言 一 信号量的简介 二 FreeRTOS信号量 1 二值
  • 牛客题:Java静态块、构造块执行顺序

    public class Test public static Test t1 new Test 静态变量 构造块 System out println AAA 静态块 static System out println BBB publi
  • 【C++】模拟实现二叉搜索树(附源码、测试用例)

    二叉搜索树 一 前言 二 模拟实现 1 构建树的单个节点 2 二叉搜索树的概念 3 构造函数与析构函数 4 赋值与拷贝构造 5 实现插入 6 实现删除 7 实现查找 8 实现遍历 三 源码及部分测试用例 一 前言 二叉搜索树 和普通的二叉树
  • 立创梁山派学习笔记——GPIO输入检测

    按键检测 前言 按键的硬件电路 BOOT选择 复位按键 唤醒按键 GPIO输入框图 软件配置 寄存器简介 1 端口控制寄存器 GPIOx CTL x A I 2 端口上拉 下拉寄存器 GPIOx PUD x A I 3 端口输入状态寄存器

随机推荐

  • 上传代码到gitee:常用命令详解

    目录 一 创建仓库 二 首次上传 三 添加代码后在上传 四 创建分支 创建dev分支 五 合并分支 六 删除分支 看个人需求 一 创建仓库 下面是创建好的仓库 无任何代码上传的状态 二 首次上传 第一步 git config global
  • 2022-3-26 Leetcode 09.字符串轮转

    class Solution public bool isFlipedString string s1 string s2 if s1 size s2 size return false string s s2 s2 return s fi
  • Bridging ConvNeXt and U-Net for medical image segmentation

    最近在收集论文时发现一篇比较有趣的论文 当提到ConvNeXt时 大家应该都知道 比较这个网络跟Transformer 一较高低的网络 在前段时间transformer 很多的时候 涌现了许多将transformer和U Net 相结合的网
  • 轻量应用服务器性能如何?CPU带宽流量系统盘测评

    轻量应用服务器性能如何 腾讯云轻量应用服务器是一种轻量级搭建小型网站和应用的服务器 相对于其他更高性能配置的服务器CVM 性价比更高 虽然其性能不如高性能云服务器CVM 但对于小型网站和应用来说 能够提供基本的计算和存储资源 可以满足基础的
  • STM32之模拟IIC总线通信(C++)

    目录 前言 主要内容 头文件 辅助函数 相关信号函数 起始信号 停止信号 接收应答信号 发送应答信号 发送非应答信号 发送一个字节数据 接收一个字节数据 应用 前言 上一篇也讲解了STM32的模拟IIC总线通信 其所使用的语言为C语言 但也
  • 人脸论文集选

    人脸论文集选 一 Face Detection 级联网络用于人脸检测 A Convolutional Neural Network Cascade for Face Detection CVPR2015 code https github
  • org.hibernate.id.IdentifierGenerationException

    问题 org hibernate id IdentifierGenerationException ids for this class must be manually assigned before calling save 原因 在添
  • Linux 上安装 Go 环境

    如果你向自己下载并编译 Go 的源代码的话 你可以根据这个页面找到安装指南和下载地址 Download the Go distribution 接下来也会带你一步步地完成安装过程 设置 Go 环境变量 我们在 Linux 系统下一般通过文件
  • 来点动力吧,存够300W退休

    这样写也可以 11年后退休 加油吧
  • pytorch学习总结(一)(SGD随机梯度下降、学习率调整策略、train模式)

    看了几个月的理论 总算是开始实践了 学习了几个月 这门学问中数学的应用还挺有意思的 比现在的工作有意思多了 1 torch optim SGD trainer torch optim SGD net parameters lr lr mom
  • linux怎么用代码做扣扣,如何在Linux上安装程序员喜爱的文本编辑器NotepadQQ

    原标题 如何在Linux上安装程序员喜爱的文本编辑器NotepadQQ 来自 Linux迷 链接 https www linuxmi com pop os 20 04 ubuntu html NotepadQQ是一个令人兴奋的应用程序 它试
  • 王垠的40行代码,究竟diao在哪里

    王垠是谁 不用我说了吧 别傻谈 亮码瞧 A simple CPS transformer which does proper tail call and does not duplicate contexts for if expressi
  • element-ui el-table 如何实现合并单元格

    el table的组件的可以合并单元格 先定义参数span method 方法objectSpanMethod 在方法内控制当前单元格渲染成几个单元格或者删除掉当前单元格 比如 代码中定义 span method objectSpanMet
  • Frameset布局

    原文地址 http captaincook iteye com blog 365634
  • angularjs 1.6.x 教程学习心得

    依赖注入 依赖注入是angularJs的核心 应用启动时 angular会创建一个injector 它会寻找并注入所有应用需要的服务 必须先被正确的定义 延迟实例化 lazily instantiate providers Provider
  • vsftpd主动模式和被动模式

    vsftpd主动模式和被动模式 主动模式 PORT 所谓主动模式 指的是FTP服务器主动去连接客户端的数据端口来传输数据 其过程具体来说就是 客户端从一个任意的非特权端口N N gt 1024 连接到FTP服务器的命令端口 即tcp 21端
  • 看看UE4源码: Pawn中默认InputComponent是控制器还是Pawn的

    Pawn中的InputComponent是谁的 结论 默认情况下 如果Pawn首次被PlayerController控制 则会在Pawn中创建一个InputComponent 写在Pawn中SetupPlayerInputComponent
  • 数据结构编程视频

    来源 我是码农 转载请保留出处和链接 本文链接 http www 54manong com cate 3 数据结构与算法是计算机专业一门相当重要的专业必修课 同时数据结构与算法也是电气电子类等一些需要涉及到编程的专业学生一门很重要的基础课程
  • WVP+ZLMediaKit+MediaServerUI实现摄像头GB28181推流播放录制

    本文主要介绍使用 WVP ZLMediaKit MediaServerUI 实现通过 GB28181 进行海康 大华 宇视等品牌的 IPC NVR DVR 接入 完成摄像头监控播放 控制 录制 准备工作 服务运行环境 Linux OS X
  • 分布式缓存原理----Hash环/一致性Hash原理/Hash槽

    Memcached 为分布式客户端做分发 hash环 TWY Redis 为分布式客户端做分发 hash环 Redis Cluster 点对点 2Khash槽 当前 Memcached Redis这类分布式kv缓存已经非常普遍 从本篇开始