一致性hash面试题_java面试算法

一致性hash面试题_java面试算法为什么要用一致性hash算法?在学习一致性hash算法之前,首先要考虑下为什么要使用它,使用它能解决什么样的问题。带着问题去学习相信理解起来会更容易。大家都知道我们在使用redis分片技术,mycat对数据库进行分库分表时都会面临数据操作规则的问题;比如我们把一条记录存入redis3服务器,那么我们获取的时候如果不指定规则就会根据key在所有的redis服务器中进行遍历查找,显然这种情况是…


Jetbrains全系列IDE稳定放心使用

为什么要用一致性hash算法?

在学习一致性hash算法之前,首先要考虑下为什么要使用它,使用它能解决什么样的问题。带着问题去学习相信理解起来会更容易。

大家都知道我们在使用redis分片技术,mycat对数据库进行分库分表时都会面临数据操作规则的问题;比如我们把一条记录存入redis3服务器,那么我们获取的时候如果不指定规则就会根据key在所有的redis服务器中进行遍历查找,显然这种情况是我们不想看到的。所以这时候我们就需要引入一些规则来确保数据放入某个redis服务器,取的时候直接去对应的服务器进行查询,而不需要遍历多台服务器。常用的规则有根据hash值来决定存放位置。比如存入一个记录时,我们根据key进行hash运算再用hash值与服务器的数量进行取模:hash(key)/3=X;得出的结果就是记录存放的服务器位置,查询的时候按照相同的公式进行计算,这样就不会遍历所有的服务器,从而大大提供了性能。

虽然使用hash算法可以提高性能,但是也会有一些缺陷,主要体现在服务器数量发生变化(增加/减少)时,所有缓存的位置都会发生改变。例如我们要增加一台缓存服务器(之前三台),hash算法如下hash(key)/4=X;这种情况带来的结果就是服务器数量发生变化时会造成缓存失效,此时请求会发往后端数据库,可能导致缓存雪崩问题。我们不允许这种现象发生,但是利用hash值取模进行缓存时这种情况无法避免,为了解决这些问题,hash一致性算法诞生了。

一致性hash算法背景

一致性哈希算法在1997年由麻省理工学院的Karger等人在解决分布式Cache中提出的,设计目标是为了解决因特网中的热点(Hot spot)问题,初衷和CARP十分类似。一致性哈希修正了CARP使用的简单哈希算法带来的问题,使得DHT可以在P2P环境中真正得到应用。

一致性hash算法:

一致性hash算法也是使用取模的方法,只是上述hash算法是对服务器数量记性取模运算,而一致性hash是对2^32取模。也就是说一致性hash算法将整个hash空间组织成一个圆环:

计算一致性hash步骤如下:

1 首先根据缓存服务器的ip,端口等信息算出哈希值,并将其配置到个数为2的32次方的圆上。

2 然后同样的方法算出存储数据的键的哈希值,并映射到相同的圆上。

3 从数据存储位置开始顺时针查找,将数据保存到找到的第一个服务器上,如果超过2的32次方仍然找不到服务器就会保存在第一台服务器上;取值操作完全相同。

整个环按照顺时针方向进行组织。然后可以用服务器ip,port作为key进行hash从而确定在环中的位置,对数据进行存储时也进行相同的hash算法对key运算确定数据在此环上的位置,从此位置沿顺时针开始遇到的第一个服务器就是数据存放的服务器:

一致性hash面试题_java面试算法

 

当添加一台redis缓存服务器时,只有增加服务器的位置和逆时针方向第一台服务器之间的键会受影响:

一致性hash面试题_java面试算法

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

hash环的数据倾斜问题:

一致性hash算法在服务节点太少的情况下容易因为节点部分不均匀造成数据倾斜问题(数据大部分集中在一台缓存服务器);

一致性hash面试题_java面试算法

为了解决这种数据倾斜问题,hash算法引入了虚拟节点机制,即对每一个服务节点计算多个哈希,每个结果未知都放置一个此服务节点,称为虚拟节点,数据定位算法不变,只是多了一个虚拟节点到实际节点的映射,例如定位到NodeA#1,2,3三个虚拟节点的数据均定位到NodeA节点,这样就解决了服务节点少时的数据倾斜问题。在实际应用中,通常将虚拟节点数设置为32甚至更大,这样即使很少的服务节点也能做到相对均匀的数据分布。

一致性hash面试题_java面试算法

一致性hash特性说明:

平衡性(balance)

平衡性是指hash的结果能够尽可能分布有缓存中去,这样可以使得所有的缓存空间都得到利用,当数据出现负载不均时,则采用虚拟节点平衡数据。

单调性(monotonicity)

单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲区加入到系统中,那么哈希的结果应能够保证原有已分配的内容可以被映射到新的缓冲区中去,而不会被映射到旧的缓冲集合中的其他缓冲区。

分散性(spread)

在分布式环境中,终端有可能看不到所有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。

负载(load)

负载问题实际上是从另一个角度看待分散性问题,终端有可能看不到所有的缓冲从而导致不同的key 保存到了相同的位置。

 

现在一致性hash算法在分布式系统中得到了广泛应用,例如memcached,redis等分布式缓存数据库,要注意的是服务端本身不提供分布式cache的一致性,而是由客户端提供的。一致性hash算法是分布式组件负载均衡的首选算法,它即可在客户端实现,也可以在中间件上实现:其应用有:

分布式散列表(DHT)设计;

分布式关系数据库(mysql),分库分表时计算数据与节点的映射关系;

分布式缓存;

RPC框架dubbo,用来选择服务提供者;

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/185674.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • Navicat for oracle创建数据库

    Navicat for oracle创建数据库前言其实在Oracle中的概念并不是创建数据库,而是创建一个表空间,然后再创建一个用户,设置该用户的默认表空间为我们新创建的表空间,这些操作之后,便和你之前用过的mysql数据库创建完数据库一模一样了(如果你用过mysql的话,当然如果Oracle是你用的第一个数据库系统,那上面这段话其实看不看并不重要)。但是,鉴于很多用过mysql的用户,在刚开始使用Oracle的时候都会不知道如何创建数据…

    2022年7月13日
  • 两、三级联动菜单,简单的实现(2)

    两、三级联动菜单,简单的实现(2)

    2022年1月9日
  • docker部署jenkins安装使用教程_docker封装python程序

    docker部署jenkins安装使用教程_docker封装python程序前言使用docker安装jenkins环境,jenkins构建的workspace目录默认是在容器里面构建的,如果我们想执行python3的代码,需进容器内部安装python3的环境。进jenki

    2022年7月31日
  • JDK下载安装及环境变量配置的图文教程(详解)「建议收藏」

    JDK下载安装及环境变量配置的图文教程(详解)「建议收藏」学习Java,需要下载并安装JDK(JavaDevelopmentKit,Java开发工具包);而为了能够快捷打开java程序,就需要按照操作系统的要求进行环境变量的配置。一、下载并安装JDK(一)下载JDK搜索“jdk官方下载”或是直接进入Sun公司的官网(https://www.oracle.com/)…

    2022年6月1日
  • dlsym用法_DLSS模式

    dlsym用法_DLSS模式dlsymdlsym,dlvsym-从一个动态链接库或者可执行文件中获取到符号地址。用法#include<dlfcn.h>void*dlsym(void*handle,constchar*symbol);#define_GNU_SOURCE#include<dlfcn.h>void*dlvsym(void*handle,char*symbol,char*version);Linkwith-ldl.详解函数dlsym()的第

    2022年10月23日
  • 软件版本号命名规范1.0.0.1什么意思_医疗器械软件版本号命名规范

    软件版本号命名规范1.0.0.1什么意思_医疗器械软件版本号命名规范软件版本号命名规范总原则标准的版本号必须采用XYZ的格式,并且X、Y和Z为非负的整数,禁止在数字前方补零版本是严格递增的,此处是:16.2.0->16.3.0->16.3.1在发布重要版本时,可以发布alpha,rc等先行版本alpha和rc等修饰版本的关键字后面可以带上次数和meta信息版本的优先层级指的是不同版本在排序时如何比较。判断优先层级时,必…

    2022年9月10日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号