普通hash

定义

Hash函数:一般翻译做散列、杂凑,或音译为哈希,是把任意长度的输入(又叫做预映射pre-image)通过散列算法变换成固定长度的输出,该输出就是散列值。
碰撞(冲突):如果两个关键字通过hash函数得到的值是一样的,就是碰撞或冲突。
Hash表(散列表):根据散列函数和冲突处理将一组关键字分配在连续的地址空间内,并以散列值记录在表中的存储位置,这种表成为散列表。

常用算法

直接寻址法:即取关键字或关键字的线性函数为散列地址:H(key)=key或H(key)=a*key+b;
数字分析法:即分析一组数据后采用的方法:如人的出生年月为92-09-03则前三位重复的几率比较大,容易产生碰撞,所以应该采用后三位作为hash值好点
平方取中法:取关键字平方的后几位。
折叠法:把关键字分割成位数相同的几部分,最后一部分可以位数不同,然后取这几部分的叠加值
随机数法:以关键值作为生成随机数的种子生成散列地址,通常适用于关键字长度不同的场合。
除留余数法:取关键字被某个不大于散列表长度m的数p除后所得的余数为散列地址:H(key)=key%p(p<=m);不仅可以对关键字直接取模,也可在折叠、平方取中等运算之后取模。对p的选择很重要,一般取素数或m,若p选的不好,容易产生碰撞。

什么是一致性Hash算法

1. 为什么要使用Hash算法
举个例子,我们在使用Redis的时候,为了保证Redis的高可用,提高Redis的读写性能,最简单的方式我们会做主从复制,,或者搭建Redis集群,进行数据的读写分离,当数据量很大的时候(标准可能不一样,要看Redis服务器容量)我们同样可以对Redis进行类似数据库的操作,就是分库分表。如图所示

假若采用随机分配的方式,那么我们保存到一条数据都有可能存储在任何一组Redis中,如果我们需要查询某一条数据,由于我们不清楚数据保存在哪一个redis服务器中,因此需要遍历了所有的Redis服务器,这显然不是我们想要的结果。
如果我们使用Hash的方式,每一张图片在进行分库的时候都可以定位到特定的服务器,示意图如下:

上图中,假设我们查找的是”a.png”,由于有4台服务器(排除从库),因此公式为hash(a.png) % 4 = 2 ,可知定位到了第2号服务器,这样的话就不会遍历所有的服务器,大大提升了性能!

2. 使用Hash带来的问题
上述的方式虽然提升了性能,我们不再需要对整个Redis服务器进行遍历!但是,使用上述Hash算法进行缓存时,会出现一些缺陷,主要体现在服务器数量变动的时候,所有缓存的位置都要发生改变!

试想一下,如果4台缓存服务器已经不能满足我们的缓存需求,那么我们应该怎么做呢?很简单,多增加几台缓存服务器不就行了!假设:我们增加了一台缓存服务器,那么缓存服务器的数量就由4台变成了5台。那么原本hash(a.png) % 4 = 2 的公式就变成了hash(a.png) % 5 = ? , 可想而知这个结果肯定不是2的,这种情况带来的结果就是当服务器数量变动时,所有缓存的位置都要发生改变!换句话说,当服务器数量发生改变时,所有缓存在一定时间内是失效的,当应用无法从缓存中获取数据时,则会向后端数据库请求数据!

同样的,假设4台缓存中突然有一台缓存服务器出现了故障,无法进行缓存,那么我们则需要将故障机器移除,但是如果移除了一台缓存服务器,那么缓存服务器数量从4台变为3台,也是会出现上述的问题!

所以,我们应该想办法不让这种情况发生,但是由于上述Hash算法本身的缘故,使用取模法进行缓存时,这种情况是无法避免的,为了解决这些问题,Hash一致性算法(一致性Hash算法)诞生了!

3. 一致性hash算法原理
一致性Hash算法也是使用取模的方法,只是,刚才描述的取模法是对服务器的数量进行取模,而一致性Hash算法是对2^32取模,一致性Hash算法将整个哈希值空间组织成一个虚拟的圆环,将各个服务器使用Hash进行一个哈希,具体可以选择服务器的IP或主机名作为关键字进行哈希,这样每台机器就能确定其在哈希环上的位置,这里假设将上文中四台服务器使用IP地址哈希后在环空间的位置如下:

每次根据要缓存的key计算得到hash值,在hash环上顺时针查找距离最近的缓存服务器节点,

根据一致性Hash算法,数据A会被定为到Node A上,B被定为到Node B上,C被定为到Node C上,D被定为到Node D上。

一致性Hash算法的容错性和可扩展性
现假设Node C不幸宕机,可以看到此时对象A、B、D不会受到影响,只有C对象被重定位到Node D。一般的,在一致性Hash算法中,如果一台服务器不可用,则受影响的数据仅仅是此服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它不会受到影响,如下所示:

下面考虑另外一种情况,如果在系统中增加一台服务器Node X,如下图所示:


此时对象Object A、B、D不受影响,只有对象C需要重定位到新的Node X !一般的,在一致性Hash算法中,如果增加一台服务器,则受影响的数据仅仅是新服务器到其环空间中前一台服务器(即沿着逆时针方向行走遇到的第一台服务器)之间数据,其它数据也不会受到影响。

综上所述,一致性Hash算法对于节点的增减都只需重定位环空间中的一小部分数据,具有较好的容错性和可扩展性。

4. Hash环的数据倾斜问题
一致性Hash算法在服务节点太少时,容易因为节点分部不均匀而造成数据倾斜(被缓存的对象大部分集中缓存在某一台服务器上)问题,例如系统中只有两台服务器,其环分布如下:

此时必然造成大量数据集中到Node A上,而只有极少量会定位到Node B上。为了解决这种数据倾斜问题,一致性Hash算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个计算结果位置都放置一个此服务节点,称为虚拟节点。具体做法可以在服务器IP或主机名的后面增加编号来实现。
例如上面的情况,可以为每台服务器计算三个虚拟节点,于是可以分别计算 “Node A#1”、“Node A#2”、“Node A#3”、“Node B#1”、“Node B#2”、“Node B#3”的哈希值,于是形成六个虚拟节点:

同时数据定位算法不变,只是多了一步虚拟节点到实际节点的映射,例如定位到“Node A#1”、“Node A#2”、“Node A#3”三个虚拟节点的数据均定位到Node A上。这样就解决了服务节点少时数据倾斜的问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,因此即使很少的服务节点也能做到相对均匀的数据分布。

总结

在分布式系统中一致性hash起着不可忽略的地位,无论是分布式缓存,还是分布式Rpc框架的负载均衡策略都有所使用。分布式系统每个节点都有可能失效,并且新的节点很可能动态的增加进来的情况,如何保证当系统的节点数目发生变化的时候,我们的系统仍然能够对外提供良好的服务,这是值得考虑的!

一致性哈希算法能尽可能减少了服务器数量变化所导致的缓存迁移。

consistent(一致性) hash算法能够在一定程度上改善缓存的雪崩问题,它能够在移除/添加一台缓 存服务器时,尽可能小的改变已存在的key映射关系,避免大量key的重新映射。

先构造一个长度为2 32次方的整数环(这个环被称为一致性Hash环),根据节点名称的Hash值(其分布为[0, 23 2次方-1])将服务器节点放置在这个Hash环上,然后根据数据的Key值计算得到其Hash值(其分布也为[0, 2 32次方-1]),接着在Hash环上顺时针查找距离这个Key值的Hash值最近的服务器节点,完成Key到服务器的映射查找。

这种算法解决了普通余数Hash算法伸缩性差的问题,可以保证在上线、下线服务器的情况下尽量有多的请求命中原来路由到的服务器。

一致性hash和普通hash区别?相关推荐

  1. 2016 -Nginx的负载均衡 - 一致性哈希 (Consistent Hash)

    Nginx版本:1.9.1 算法介绍 当后端是缓存服务器时,经常使用一致性哈希算法来进行负载均衡. 使用一致性哈希的好处在于,增减集群的缓存服务器时,只有少量的缓存会失效,回源量较小. 在nginx+ ...

  2. vue路由的两种模式:hash与history的区别

    前言:众所周知,vue-router有两种模式,hash模式和history模式,下面来看看两者的区别. 一.基本情况 直观区别:hash模式url带#号,history模式不带#号. 1.hash模 ...

  3. 一致性Hash算法(hash环)

    一致性Hash(DHT)性质 考虑到分布式系统每个节点都有可能失效,并且新的节点很可能动态的增加进来,如何保证当系统的节点数目发生变化时仍然能够对外提供良好的服务,这是值得考虑的,尤其实在设计分布式缓 ...

  4. 后缀数组 + Hash + 二分 or Hash + 二分 + 双指针 求 LCP ---- 2017icpc 青岛 J Suffix (假题!!)

    题目链接 题目大意: 就是给你n个串每个串取一个后缀,要求把串拼起来要求字典序最小!! sum_length_of_n≤5e5sum\_length\_of\_n\leq 5e5sum_length_ ...

  5. Algorithm:C++语言实现之SimHash和倒排索引算法相关(抽屉原理、倒排索、建立查找树、处理Hash冲突、Hash查找)

    Algorithm:C++语言实现之SimHash和倒排索引算法相关(抽屉原理.倒排索.建立查找树.处理Hash冲突.Hash查找) 目录 一.SimHash算法 1.SimHash算法五个步骤 2. ...

  6. Mysql 优化器内部JOIN算法hash join On-Disk Hash Join Grace Hash Join Hybrid hash join过程详解

    Mysql 各种hash join算法讲解 hash join的概述 提到hash join之前自然得说Nest loop join,以两个表的关联为例,它其实是个双层循环,先遍历外层的表(n条),再 ...

  7. python hash函数_Python hash()函数

    python hash函数 Python hash() is one of the built-in function. Today we will look into the usage of ha ...

  8. Android集成Facebook登录时遇到的问题invalid key hash.the key hash

    一.Facebook:登录功能已停用,我们已停用通过嵌入式浏览器登录Facebook的功能 错误提示: 为保护账户安全,我们已停用通过嵌入式浏览器登录Facebook的功能.若要继续,请更新登录使用的 ...

  9. Hash(哈希)简述 —— Hash函数、Hash值、HashTable、HashMap

    总览 - Hash(哈希.散列) Hash是一种 散列函数或方法 的统称. · 该方法就是:把任意长度的输入通过散列算法变换成固定长度的输出,该输出就是散列值.-- (散列方法) · 这种转换是一种压 ...

  10. Adaptive Hash Index(自适应hash索引)

    文章目录 1.1 什么是hash索引 1.2 什么是自适应hash索引 1.3 自适应hash索引原理 1.4 相关变量 1.5 监控指标 1.6 总结 1.1 什么是hash索引   哈希索引基于哈 ...

最新文章

  1. 谷歌浏览器安卓版_谷歌翻译(在线翻译)下载-谷歌翻译下载安装安卓版v5.12.0...
  2. Ubuntu下的重要配置文件修改前要先备份
  3. Java 8 Friday:可选将保留为Java中的一个选项
  4. Plist文件和字典转模型
  5. linux变量最大长度,51CTO博客-专业IT技术博客创作平台-技术成就梦想
  6. 帮管客CRM客户管理系统
  7. Visual Studio2010重新安装后,冲突问题
  8. 深入理解docker graph driver - DeviceMapper
  9. Python语言介绍
  10. Altium Designer PCB常用规则中英文对照
  11. 单片机驱动为什么要设置为低电平有效?
  12. html爱情意思,1一9爱情数字什么意思 1到9数字爱情含义
  13. 关于QImageReader多次调用read失败的问题
  14. python javascript人工智能_Python,Java和JavaScript哪个编程语言未来发展空间更大?...
  15. SpringBoot整合模板FreeMarker篇
  16. matlab 利用polyfitpolyval函数进行基线矫正【matlab程序】
  17. java中long类型的空值怎么表示,【关于long类型的转换】传进来的是String类型是或null或0如何转成long类型...
  18. Socket和ServerSocket(建立客户端和服务器端)
  19. 【Koltin Flow(二)】Flow操作符之末端操作符
  20. wordpress编辑器遇到了未知错误

热门文章

  1. 纪录片《舌尖上的中国》火了
  2. mysql安装到最后一步无响应的问题超简单最有效解决
  3. 如何使用java调取支付宝沙箱实现模拟支付?
  4. 如何成为一名优秀的网络推广专员
  5. Install Shield 脚本(总)
  6. Veeam Backup Replication 11 百度网盘下载
  7. 优化页面打开速度(一)
  8. OTP动态口令的Java实现
  9. 网页制作课作业基于HTML+CSS+JavaScript+jquery仿慕课网教学培训网站设计实例 企业网站制作
  10. 【JAVA 杨辉三角 数学文字游戏】