• 18 哈希算法的应用和一致性哈希


    什么是哈希算法

    哈希=散列=Hash,所以哈希算法即散列函数。
    哈希算法定义:输入任意长度的二进制串,将其映射为固定长度的二进制串,这个映射的规则就是哈希算法。输出的二进制串就是哈希值,也叫散列值。
    哈希算法的要求:
    1、从哈希值不能推导出原始数据(所以哈希算法也叫单向哈希算法)
    2、对输入数据敏感,哪怕只修改了一个bit,得出的哈希值也要大不相同
    3、散列冲突的概率要低,对不同的原始数据,哈希值相同的概率要很低。
    4、哈希算法的执行效率要尽量高效,针对较长文本,也要尽快算出哈希值。
    下面是哈希算法的七个经常应用。

    应用于安全加密

    常用哈希算法的加密算法有MD5和SHA。对于应用于加密的哈希算法而言,上面四条要求中,有两项是最重要的,
    1、不能从哈希值反向推导出原始数据,这是加密的最基础要求和目的。
    2、散列冲突的概率要很小。理论上是没办法做到完全不冲突的,所以只能尽量减少发生冲突。
    为什么不能做到0冲突呢,举一个MD5的例子,
    例如MD5的哈希值是一个固定的128位二进制串,表示的长度是有限的,最多表示2128 个数据,即位置是有限的。但是我们的输入哈希算法的值是无限的。即对于2128 个位置,有2128 +1个数的时候,比如有一个位置上的数是大于1的,即存在哈希值相同的现象,出现散列冲突。所以哈希值越长的哈希算法,散列冲突概率越低。

    应用于唯一标识

    举例,在海量图库中,输入一张图片,如何判断该图片在图库中已经存在?
    首先排除通过元数据搜索(即图片名称),因为可能存在名称相同但是内容不相同的图片,或者名称不相同但是内容相同的图片。
    比较笨的方法是通过二进制码串对比,因为计算机中所有文件都能被转换成二进制码串。所以拿要查找的图片的二进制码串和库中所有 的二进制码串做比对即可。二进制码串一致就代表两张图片相同。但是一张图片小则几十K,大则几十M,对比是很耗时的。
    最好的方法是通过唯一标识。对每一张图片,从每张图片的二进制码串取前面100个字节,中间100个字节,后面100个字节,然后通过哈希函数将这三百个字节转化为一个哈希字符串用来做唯一标识,然后通过唯一标识进行判断是否在图库中。
    继续提高效率,将唯一标识存储在散列表中,在散列表中查询是否存在该唯一标识。

    应用于数据校验

    举例基于P2P协议的BT下载,例如下载一个2G的电影,这个电影文件会被分割成100个块,每个块大小20M,然后通过网络传输到客户端。
    因为网路是不完全的,或者存在下载过程中出现错误或者被宿主机器恶意修改,就会导致合并的电影不能观看。
    要如何进行数据校验呢
    1、对100个块文件进行哈希算法并且保存在种子中。基于哈希算法对输入值非常的敏感的特性,只要文件块被修改或者出现错误,算出的哈希值是不同的。所以在下载完后,需要对下载完的文件进行同意求哈希值,然后跟种子种保存的哈希值算法做对比。

    应用散列函数

    实际上散列函数也是哈希函数的实现的一种。
    只是散列函数对比哈希函数,散列函数对散列冲突的要求降低了很多,因为只要不是很严重,都可以通过开放寻址法或者链表法结局。
    除此之外,散列函数对是否能通过反向破解原数据也不重要。散列函数更关注的是散列后的值能否平均分配。散列函数的算法一般比较简单,只追求效率。

    应用于负载均衡

    负载均衡算:轮询,随机、加权轮询等。
    如何实现以粘滞的负载均衡(在同个客户端上同一个会话的所有请求都在同一个服务器上)呢?
    最直接方法:建立一个映射关系表,表由客户端ip或者是会话ID组成 和服务器编号的映射关系组成。客户端每次会话请求都从映射表中查询路由到的服务器编号,随之找到对应的服务器,进行连接。
    但是这种方法有两个弊端:
    1、如果客户端很多,那么映射表很大。容易造成内存空间浪费。
    2、客户端上线下线,服务器扩容缩容,都会造成映射失效,这样维护成本很大。
    解决方法:
    1、对客户端IP或者会话ID进行哈希函数处理,生成哈希值。
    2、用哈希值与服务器列表大小做一个取模运算,最终得到的值就是哪台服务器的编号。同一个IP就能都路由到同一个后端服务器。

    应用数据分片

    例如有1t的搜索日志文件,如何能快速统计某个关键词被搜索的次数呢。
    解决方法:对数据进行分片,然后多台机器同时处理,提高处理速度。
    例如:
    1、有1台主机,n台从机,主机负责读取关键词和哈希函数计算以及用哈希值跟n取模,算出从机的序号
    2、算出从机序号后,把关键词发给该从机,该从机维护一个散列表,计算关键词到该从机的次数
    3、如果同一个关键词就会作为key被分配到同一台从机上。要查询某个查询记录时就可以分词,然后把关键词发送到台从机取计算关键词出现的次数,然后个兵取出结果。

    应用于分布式存储

    存储海量数据时,一台机器存储不够时, 可以将数据分布在多台机器上。那么如何决定将哪个数据存储到那台机器上呢,可以利用上面数据分片的思想:通过哈希算法对机器台数取模,得出机器序号然后将数据分布在多台机器上。
    但是这里有个问题:如果机器不够了,增加了机器台数,例如原来10台机器,现在11台,以前是按10取模,现在要按11台取模,那么原来13这个数据原本是在3号机器的,现在就被分配到了2号机器。
    因此这里所有的数据都要重新算哈希值,然后迁移到正确机器上,这种行为相当于缓存中的数据都一瞬间失效,所有数据请求都会穿透缓存,直接去请求数据库,然后产生雪崩效应压垮数据库。
    所以需要引进一种新的哈希算法,叫一致性哈希算法。
    假如有k台机器,数据的哈希值范围是[0,MAX],将整个区间分成m个小区间,大于k,然后每天机器就负责m/k个区间。当有新机器加入时,就把某几个区间的数据从原来的机器迁移到新机器上就行,不用全部哈希和迁移全部数据,也保持了数据量的平衡。
    重点:
    因为IPv4的地址是4组8位2进制数组成,所以【0-232 】中可以保证每个ip都有唯一的映射。
    例如有10台机器A-J,每台机器都有ip地址。先对每台机器的ip然后对232 取模算出一个整数,所以这个整数必然是在【0-232 】中,取ABC为例子
    在这里插入图片描述

    例如我们查找某条数据,hash(x)% 232 取模,这条数据肯定是在【0,232】这个闭环圆里面某个点。

    在这里插入图片描述

    此时以图中黄点为例,顺时针走遇到第一台服务器A,那么黄点数据就会被存储到服务器A中,即C->A区间的数据会被缓存到A服务器,A->B中的区间的数据被缓存到B,以此类推,这个就叫一致性哈希算法。

  • 相关阅读:
    vue开发一、在Vue中引入ElementUI二、在Vue中使用阿里图标库
    贪心算法-会议室问题
    半导体动态杂谈
    VectorCAST测试工具环境搭建
    「学习笔记」二分图
    IDEA 关闭SpringBoot启动Logo/图标
    【高并发项目实战】自适应高并发复杂场景的订单拆分算法工具
    抖音SEO源码
    【redisson学习笔记】
    前端实现菜单&按钮级权限
  • 原文地址:https://blog.csdn.net/weixin_43859562/article/details/127426595