2.2.1.2 一致性哈希分区(Consistent hashing)
原理
- 环形 hash 空间
按常用 hash 算法,将对应的 key hash到一个具有 2^32
个桶的空间,即(0 ~ 2^32
- 1)的数字空间中。
将这些数字头尾相连,想象成一个闭合环形:
-
把数据通过一定的 hash 算法映射到环上
-
将机器通过一定的 hash 算法映射到环上
-
节点按顺时针转动,遇到的第一个机器,就把数据放在该机器
-
把对象映射到hash空间
把cache映射到hash空间
基本思想就是将对象和cache都映射到同一个hash数值空间中, 并且使用相同的hash算法
hash(cache A) = key A;
hash(cache C) = key C;
在移除 or 添加一个 cache 时,能够尽可能小的改变已存在的 key 映射关系
Consistent hashing 一致性算法
移除 Cache
- 删除CacheB后,橙色区为被影响范围
添加Cache
- 理想的分布式
现实却很拥挤-即倾斜性:
Hash倾斜性
为解决该问题,引入虚拟节点
- 虚拟节点
命中率计算公式:服务器台数n,新增服务器数m
(1 - n/(n + m) ) * 100%
- 一致性哈希-扩容
客户端分片:哈希+顺时针(优化取余)
节点伸缩:只影响邻近节点,但还是有数据迁移
翻倍伸缩:保证最小迁移数据和负载均衡
2.2.1.3 虚拟槽哈希分区(Redis Cluster采用)
- 虚拟槽分配
- 预设虚拟槽
每个槽映射一个数据子集, 一般比节点数大
- 良好的哈希函数
例如CRC16
- 服务端管理节点、槽、数据
特点
-
数据分散度高
-
键值分布业务无关
-
无法顺序访问
-
支持批量操作
产品
-
一致性哈希Memcache
-
Redis Cluster
-
…
哈希分片的一种高端形式称为一致性哈希(consistent hashing),被一些 Redis 客户端和代理实现。
========================================================================
客户端直接选择正确节点来写入和读取指定键,许多 Redis 客户端实现了客户端分片。
在客户端配置多个缓存的节点,通过缓存写入和读取算法策略来实现分布式,从而提高缓存可用性。
写入数据时,需要把被写入缓存的数据分散到多个节点中,即进行数据分片;
- 读数据时,可利用多组的缓存来做容错,提升缓存系统可用性。这里可用主从、多副本两种策略,专为解决不同问题而提。
在应用代码和缓存节点之间增加代理层。客户端所有的写入和读取的请求都通过代理层,而代理层中会内置高可用策略,帮助提升缓存系统的高可用。
客户端发送请求到一个可以理解 Redis 协议的代理上,而非直接发到Redis 实例。
代理会根据配置好的分片模式,来保证转发我们的请求到正确的 Redis 实例,并返回响应给客户端。
Redis 和 Memcached 的代理 Twemproxy 都实现了代理协助的分片。
可发送你的查询到一个随机实例,该实例会保证转发你的查询到正确节点。
Redis 集群在客户端的帮助下,实现了查询路由的一种混合形式,请求不是直接从 Redis 实例转发到另一个,而是客户端收到重定向到正确的节点。
Redis 2.4版本后提出的Redis Sentinel方案。
======================================================================
Redis 的一些特性与分片在一起时玩的不是很好:
-
涉及多个键的操作通常不支持。例如,无法直接对映射在两个不同 Redis 实例上的键执行交集
-
涉及多个键的事务不能使用
-
分片的粒度是键,所以不能使用一个很大的键来分片数据集,例如一个很大的sorted set
-
当使用了分片,数据处理变得更复杂。例如,你需要处理多个 RDB/AOF 文件,备份数据时需要聚合多个实例和主机的持久化文件
-
添加和删除容量也很复杂。例如,Redis 集群具有运行时动态添加和删除节点的能力来支持透明地再均衡数据,但是其他方式,像客户端分片和代理都不支持这个特性。但有一种称为预分片(Presharding)的技术在这一点上能帮上忙。
==========================================================================
尽管无论是将 Redis 作为数据存储还是缓存,Redis 分片概念上都是一样的。
-
但作为数据存储时有个重要局限:当 Redis 作为数据存储时,一个给定的键总是映射到相同 Redis 实例。
-
当 Redis 作为缓存时,如果一个节点不可用而使用另一个节点,这并不是啥大问题,按照我们的愿望来改变键和实例的映射来改进系统的可用性(即系统响应我们查询的能力)。
一致性哈希实现常常能够在指定键的首选节点不可用时切换到其它节点。类似的,如果你添加一个新节点,部分数据就会开始被存储到这个新节点上。
主要概念:
-
如果 Redis 用作缓存,使用一致性哈希来实现伸缩扩展很容易
-
如果 Redis 用作存储,使用固定的键到节点的映射,所以节点的数量必须固定不能改变。否则,当增删节点时,就需要一个支持再平衡节点间键的系统,当前只有 Redis 集群可以做到这点。
====================================================================
分片存在一个问题,除非我们使用 Redis 作为缓存,否则增加和删除节点都是件麻烦事,而使用固定的键和实例映射要简单得多。
然而,数据存储的需求可能一直在变化。今天可接受 10 个 Redis 节点,但明天可能就需 50 个节点。
因为 Redis 只有相当少的内存占用且轻量级(一个空闲的实例只使用 1MB 内存),一个简单的解决办法是一开始就开启很多实例。即使你一开始只有一台服务器,也可以在第一天就决定生活在分布式世界,使用分片来运行多个 Redis 实例在一台服务器上。
你一开始就可以选择很多数量的实例。例如,32 或者 64 个实例能满足大多数用户,并且为未来的增长提供足够的空间。
这样,当数据存储增长,需要更多 Redis 服务器,你要做的就是简单地将实例从一台服务器移动到另外一台。当你新添加了第一台服务器,你就需要把一半的 Redis 实例从第一台服务器搬到第二台,以此类推。
使用 Redis 复制,就可以在很小或者根本不需要停机的时间内完成移动数据:
-
在新服务器上启动一个空实例
-
移动数据,配置新实例为源实例的从服务
小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数初中级Java工程师,想要提升技能,往往是自己摸索成长,但自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年最新Java开发全套学习资料》送给大家,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
由于文件比较大,这里只是将部分目录截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频
如果你觉得这些内容对你有帮助,可以添加下面V无偿领取!(备注Java)
总结
谈到面试,其实说白了就是刷题刷题刷题,天天作死的刷。。。。。
为了准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的
并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)
66个Java面试知识点
架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)
算法刷题(PDF)
准备这个“金三银四”的春招,狂刷一个月的题,狂补超多的漏洞知识,像这次美团面试问的算法、数据库、Redis、设计模式等这些题目都是我刷到过的
并且我也将自己刷的题全部整理成了PDF或者Word文档(含详细答案解析)
[外链图片转存中…(img-71hraHF2-1710412389744)]
66个Java面试知识点
架构专题(MySQL,Java,Redis,线程,并发,设计模式,Nginx,Linux,框架,微服务等)+大厂面试题详解(百度,阿里,腾讯,华为,迅雷,网易,中兴,北京中软等)
[外链图片转存中…(img-k1AZJakL-1710412389744)]
算法刷题(PDF)
[外链图片转存中…(img-LHLpxs08-1710412389744)]