Redis之哈希分片原理一致性哈希算法与crc16算法
集群分片模式
如果Redis只用复制功能做主从,那么当数据量巨大的情况下,单机情况下可能已经承受不下一份数据,更不用说是主从都要各自保存一份完整的数据。在这种情况下,数据分片是一个非常好的解决办法。
Redis的Cluster正是用于解决该问题。它主要提供两个功能:
- 自动对数据分片,落到各个节点上
- 即使集群部分节点失效或者连接不上,依然可以继续处理命令
对于第二点,它的功能有点类似于Sentienl的故障转移(可以了解下之前Sentinel的文章),在这里不细说。下面详细了解下Redis的槽位分片原理,在此之前,先了解下分布式简单哈希算法和一致性哈希算法,以帮助理解槽位的作用。
简单哈希算法
假设有三台机,数据落在哪台机的算法为
c = Hash(key) % 3
例如key A的哈希值为4,4%3=1,则落在第二台机。Key ABC哈希值为11,11%3=2,则落在第三台机上。
利用这样的算法,假设现在数据量太大了,需要增加一台机器。A原本落在第二台上,现在根据算法4%4=0,落到了第一台机器上了,但是第一台机器上根本没有A的值。这样的算法会导致增加机器或减少机器的时候,引起大量的缓存穿透,造成雪崩。
一致性哈希算法
在1997年,麻省理工学院的Karger等人提出了一致性哈希算法,为的就是解决分布式缓存的问题。
在一致性哈希算法中,整个哈希空间是一个虚拟圆环
假设有四个节点Node A、B、C、D,经过ip地址的哈希计算,它们的位置如下
有4个存储对象Object A、B、C、D,经过对Key的哈希计算后,它们的位置如下
对于各个Object,它所真正的存储位置是按顺时针找到的第一个存储节点。例如Object A顺时针找到的第一个节点是Node A,所以Node A负责存储Object A,Object B存储在Node B。
一致性哈希算法大概如此,那么它的容错性和扩展性如何呢?
假设Node C节点挂掉了,Object C的存储丢失,那么它顺时针找到的最新节点是Node D。也就是说Node C挂掉了,受影响仅仅包括Node B到Node C区间的数据,并且这些数据会转移到Node D进行存储。
同理,假设现在数据量大了,需要增加一台节点Node X。Node X的位置在Node B到Node C直接,那么受到影响的仅仅是Node B到Node X间的数据,它们要重新落到Node X上。
所以一致性哈希算法对于容错性和扩展性有非常好的支持。但一致性哈希算法也有一个严重的问题,就是数据倾斜。
如果在分片的集群中,节点太少,并且分布不均,一致性哈希算法就会出现部分节点数据太多,部分节点数据太少。也就是说无法控制节点存储数据的分配。如下图,大部分数据都在A上了,B的数据比较少。
哈希槽
Redis集群(Cluster)并没有选用上面一致性哈希,而是采用了哈希槽(SLOT)的这种概念。主要的原因就是上面所说的,一致性哈希算法对于数据分布、节点位置的控制并不是很友好。
首先哈希槽其实是两个概念,第一个是哈希算法。Redis Cluster的hash算法不是简单的hash(),而是crc16算法,一种校验算法。
另外一个就是槽位的概念,空间分配的规则。其实哈希槽的本质和一致性哈希算法非常相似,不同点就是对于哈希空间的定义。一致性哈希的空间是一个圆环,节点分布是基于圆环的,无法很好的控制数据分布。而Redis Cluster的槽位空间是自定义分配的,类似于Windows盘分区的概念。这种分区是可以自定义大小,自定义位置的。
Redis Cluster包含了16384个哈希槽,每个Key通过计算后都会落在具体一个槽位上,而这个槽位是属于哪个存储节点的,则由用户自己定义分配。例如机器硬盘小的,可以分配少一点槽位,硬盘大的可以分配多一点。如果节点硬盘都差不多则可以平均分配。所以哈希槽这种概念很好地解决了一致性哈希的弊端。
另外在容错性和扩展性上,表象与一致性哈希一样,都是对受影响的数据进行转移。而哈希槽本质上是对槽位的转移,把故障节点负责的槽位转移到其他正常的节点上。扩展节点也是一样,把其他节点上的槽位转移到新的节点上。
但一定要注意的是,对于槽位的转移和分派,Redis集群是不会自动进行的,而是需要人工配置的。所以Redis集群的高可用是依赖于节点的主从复制与主从间的自动故障转移。
集群搭建
下面以最简单的例子,抛开高可用主从复制级转移的内容,来重点介绍下Redis集群是如何搭建,槽位是如何分配的,以加深对Redis集群原理及概念的理解。
redis.conf配置
先找到redis.conf,启用cluster功能。
cluster-enabled yes默认是关闭的,要启用cluster,让redis成为集群的一部分,需要手动打开才行。
然后配置cluster的配置文件
每一个cluster节点都有一个cluster的配置文件,这个文件主要用于记录节点信息,用程序自动生成和管理,不需要人工干预。唯一要注意的是,如果在同一台机器上运行多个节点,需要修改这个配置为不同的名字。
本次为了方便搭建,所有Redis实例都在同一台机器上,所以修改不同的cluster config名字后,复制三份redis.conf配置,以用于启动三个集群实例(cluster至少要三个主节点才能进行)。
集群关联
> redis-server /usr/local/etc/redis/redis-6379.conf --port 6379 &
> redis-server /usr/local/etc/redis/redis-6380.conf --port 6380 &
> redis-server /usr/local/etc/redis/redis-6381.conf --port 6381 &
&符号的作用是让命令在后台执行,但程序执行的log依然会打印在console中。也可以通过配置redis.conf中deamonize yes,让Redis在后台运行。
连上6379的Redis实例,然后通过cluster nodes查看集群范围。
连上其他实例也是一样,目前6379、6380、6381在各自的集群中,且集群只有它们自己一个。
在6379上,通过cluster meet命令,与6380、6381建立链接。
127.0.0.1:6379> cluster meet 127.0.0.1 6380
127.0.0.1:6379> cluster meet 127.0.0.1 6381

可以看到集群中已经包含了6379、6380、6381三个节点了。登录其他节点查看也是一样的结果。即使6380与6381之间没有直接手动关联,但在集群中,节点一旦发现有未关联的节点,会自动与之握手关联。
槽位分配
通过cluster info命令查看集群的状态
state的状态是fail的,还没启用。看下官方的说明
只有state为ok,节点才能接受请求。如果只要有一个槽位(slot)没有分配,那么这个状态就是fail。而一共需要分配16384槽位才能让集群正常工作。
接下来给6379分配05000的槽位,给6380分配500110000的槽位,给6381分配10001~16383的槽位。
> redis-cli -c -p 6379 cluster addslots {0..5000}
> redis-cli -c -p 6380 cluster addslots {5001..10000}
> redis-cli -c -p 6381 cluster addslots {10001..16383}
再看看cluster info
state已经为ok,16384个槽位都已经分配好了。现在集群已经可以正常工作了。
效果测试
随便登上一个实例,记得加上参数-c,启用集群模式的客户端,否则无法正常运行。
redis-cli -c -p 6380
尝试下set、get操作
可以看到,Redis集群会计算key落在哪个卡槽,然后会把命令转发到负责该卡槽的节点上执行。
利用cluster keyslot命令计算出key是在哪个槽位上,从而得出会跳转到哪个节点上执行。
Redis之哈希分片原理一致性哈希算法与crc16算法的更多相关文章
- 进阶的Redis之哈希分片原理与集群实战
前面介绍了<进阶的Redis之数据持久化RDB与AOF>和<进阶的Redis之Sentinel原理及实战>,这次来了解下Redis的集群功能,以及其中哈希分片原理. 集群分片模 ...
- Memcached 笔记与总结(5)Memcached 的普通哈希分布和一致性哈希分布
普通 Hash 分布算法的 PHP 实现 首先假设有 2 台服务器:127.0.0.1:11211 和 192.168.186.129:11211 当存储的 key 经过对 2 (2 台服务器)取模运 ...
- Redis Cluster 的数据分片机制
上一篇<分布式数据缓存中的一致性哈希算法> 文章中讲述了一致性哈希算法的基本原理和实现,今天就以 Redis Cluster 为例,详细讲解一下分布式数据缓存中的数据分片,上线下线时数据迁 ...
- 用于KV集群的一致性哈希Consistent Hashing机制
KV集群的请求分发 假定N为后台服务节点数,当前台携带关键字key发起请求时,我们通常将key进行hash后采用模运算 hash(key)%N 来将请求分发到不同的节点上, 后台节点的增删会引起几乎所 ...
- redis集群与分片(1)-redis服务器集群、客户端分片
下面是来自知乎大神的一段说明,个人觉得非常清晰,就收藏了. 为什么集群? 通常,为了提高网站响应速度,总是把热点数据保存在内存中而不是直接从后端数据库中读取.Redis是一个很好的Cache工具.大型 ...
- 一致性哈希(consistent hashing)算法
文章同步发表在博主的网站朗度云,传输门:http://www.wolfbe.com/detail/201608/341.html 1.背景 我们都知道memcached服务器是不提供分布 ...
- Memcached 笔记与总结(8)Memcached 的普通哈希分布算法和一致性哈希分布算法命中率对比
准备工作: ① 配置文件 config.php ② 封装 Memcached 类 hash.class.php,包含普通哈希算法(取模)和一致性哈希算法 ③ 初始化 Memcached 节点信息 in ...
- redis集群之分片集群的原理和常用代理环境部署
上篇文章刚刚介绍完redis的主从复制集群,但主从复制集群主要是为了解决redis集群的单点故障问题,通过整合哨兵能实现集群的高可用:但是却无法解决数据容量以及单节点的压力问题,所以本文继续介绍red ...
- 一致性哈希算法原理及Java实现
一致性哈希算法在1997年由麻省理工学院提出的一种分布式哈希(DHT)实现算法,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似.一致性哈希修正了CARP使用的简 单 ...
- 深入一致性哈希(Consistent Hashing)算法原理,并附100行代码实现
转自:https://my.oschina.net/yaohonv/blog/1610096 本文为实现分布式任务调度系统中用到的一些关键技术点分享——Consistent Hashing算法原理和J ...
随机推荐
- CreateProcess函数源码分析
CreateProcess函数源码分析 源码版本:Windows 2003 源码 源码阅读工具:Source Insight 函数功能分析 函数原型 BOOL CreateProcessA( ...
- 事务提交之后再执行某些操作 → 引发对 TransactionSynchronizationManager 的探究
开心一刻 昨晚,小妹跟我妈聊天 小妹:妈,跟你商量个事,我想换车,资助我点呀 妈:哎呀,你那分扣的攒一堆都够考清华的,还换车资助点,有车开就不错了 小妹:你要是这么逼我,别说哪天我去学人家傍大款啊 妈 ...
- Docker从认识到实践再到底层原理(二-2)|Namespace+cgroups
前言 那么这里博主先安利一些干货满满的专栏了! 首先是博主的高质量博客的汇总,这个专栏里面的博客,都是博主最最用心写的一部分,干货满满,希望对大家有帮助. 高质量博客汇总 然后就是博主最近最花时间的一 ...
- C++小项目|2022期末大作业
前言 那么这里博主先安利一下一些干货满满的专栏啦! 手撕数据结构https://blog.csdn.net/yu_cblog/category_11490888.html?spm=1001.2014. ...
- mysql 索引优化 explain,复合索引,联合索引,优化 user_base 和 log_login 实战
本节是关于MySQL的复合索引相关的知识,两个或更多个列上的索引被称作复合索引,本文主要介绍了mysql 联合索引生效的条件及失效的条件 对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可 ...
- 《ASP.NET Core 与 RESTful API 开发实战》-- (第9章)-- 读书笔记(上)
第 9 章 测试和文档 9.1 测试 测试是软件生命周期中的一个非常重要的阶段,对于保证软件的可靠性具有极其重要的意义 常见的测试方法有很多,根据不同的维度,可以把测试方法分为不同的类别 从观察结构的 ...
- ABC 314
F 每次相当于创建一个包含 \(p_i,q_i\) 各自所在集合的点的大点 \(u\),然后 \(u\) 向 \(p_i,q_i\) 各自所在集合连边,边权就是胜率. 连完之后求每个点到根结点(\(\ ...
- 顺着这份Java面试地图,国内一二线互联网公司随便进...
原创:陶朱公Boy(微信公众号ID:taozhugongboy),欢迎分享,转载请保留出处. 前言 临近春节,这几天手头没什么事情,花了点时间,将自己近两年收集的面试真题,进行了一番深度归纳总结,整理 ...
- C# 二十年语法变迁之 C# 8参考
C# 二十年语法变迁之 C# 8参考 自从 C# 于 2000 年推出以来,该语言的规模已经大大增加,我不确定任何人是否有可能在任何时候都对每一种语言特性都有深入的了解.因此,我想写一系列快速参考文章 ...
- 在linux 平台上源码编译安装MySQL 8.0
从根源上掌握MySQL安装,以此类推,在linux 平台上通过源码安装其他c/c++软件都是大同小异. 1. 安装方式 linux 的安装包分为RPM 包.二进制包和源码包. 不同的安装方式各有优 ...