美文网首页算法
你真的了解HASH吗?

你真的了解HASH吗?

作者: 沈先生的影子 | 来源:发表于2020-11-30 14:38 被阅读0次

    什么是Hash?什么是Hash表?什么是Hash冲突?

    HASH

      哈希(散列)是指:任意长度的输入经过hash算法转化为固定长度的输出。

        public static String strToHashKey(String k) {
            String tmpKey;
            try {
                final MessageDigest mDigest = MessageDigest.getInstance("MD5");
                mDigest.update(k.getBytes());
                tmpKey = bytesToHexString(mDigest.digest());
            } catch (NoSuchAlgorithmException e) {
                tmpKey = String.valueOf(k.hashCode());
            }
            return tmpKey;
        }
    
        private static String bytesToHexString(byte[] b) {
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < b.length; i++) {
                String hex = Integer.toHexString(0xFF & b[i]);
                if (hex.length() == 1) {
                    sb.append('0');
                }
                sb.append(hex);
            }
            return sb.toString();
        }
    
        public static void main(String[] args) {
            String str = "TEST_HASH_01_STR";
            String str2 = "TEST_HASH_02_STR";
            String str3 = "TEST_HASH_03_STR";
            String str4 = "TEST_HASH_04_STR";
    
            System.out.println(str + "的hash值= " + strToHashKey(str));
            System.out.println(str2 + "的hash值= " + strToHashKey(str2));
            System.out.println(str3 + "的hash值= " + strToHashKey(str3));
            System.out.println(str4 + "的hash值= " + strToHashKey(str4));
        }
    
    控制台输出
    --------------------------------------------------------
    TEST_HASH_01_STR的hash值= 488ffb5451eca9a66e5841f2d33127c7
    TEST_HASH_02_STR的hash值= 4f637e42de1540f7f51687a1e776a5aa
    TEST_HASH_03_STR的hash值= 2008b46e01406eb4a44d3176a23cdec2
    TEST_HASH_04_STR的hash值= 3e8eb32d529479a488201c53232e79df
    

    哈希的使用

    Hash取模 (hash(输入) % n)

      现在有3个服务器,要做负载均衡,就可以对请求的ip地址或者用户的id等使用Hash函数,然后将计算得出的Hash值对机器数取模,余数为几,就把请求分配到相应的服务器上。

    Hash%机器数量

      缺点:新增服务器或者服务器宕机的时候,绝大多数请求基本上都需要重新映射到另一个节点。这种变动有时候是不能接受的。比如在Web负载均衡的场景下,session会保存在每个节点里。当然,如果你是“无状态”的服务,那不会存在这个问题。因为如果增加或者删除了一个节点,就会导致几乎所有的数据都需要重新迁移。

    一致性Hash

      尽可能降低分布式环境下,通过哈希定位运算确认元素位置的集群服务受机器数的影响,避免使用固定值取模,改为范围定位的方式。

    上面的取模运算的除数是机器数,而一致性Hash的除数是2^32(int类型的最大值)。从0到232 - 1,首尾相连构成了一个环。

    一致性哈希

    我们先对服务器节点的IP进行Hash,然后除以2^32
    得到服务器节点在这个Hash环中的位置。如果有请求进来了,同样进行Hash然后处于2^32求余。如果落在Hash环上,然后顺时针找到第一个节点,这个节点就负责处理这个请求。

    优点:解决因为横向伸缩导致的大规模数据变动。
    缺点:一致性Hash算法在节点数量较少的时候,会出现分布不均匀的问题。
    解决方案就是在Hash环上增加虚拟节点。

    虚拟节点

    哈希的应用

      1.密码学和数字签名。
      2.文件的完整性检查。
      3.基于HASH的数据结构。

    哈希算法的特点

      1.不可逆:不可以根据hash值计算出原值。
      2.效率高,HASH运算能快速计算出结果。
      3.冲突少,优秀的哈希算法具备的特点。

    哈希算法

    (1)MD4

      MD4(RFC 1320)是 MIT 的Ronald L. Rivest在 1990 年设计的,MD 是 Message Digest(消息摘要) 的缩写。它适用在32位字长的处理器上用高速软件实现——它是基于 32位操作数的位操作来实现的。

    (2)MD5

      MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组,其输出是4个32位字的级联,与 MD4 相同。MD5比MD4来得复杂,并且速度较之要慢一点,但更安全,在抗分析和抗差分方面表现更好。

    (3)SHA-1及其他

      SHA1是由NIST NSA设计为同DSA一起使用的,它对长度小于264的输入,产生长度为160bit的散列值,因此抗穷举(brute-force)性更好。SHA-1 设计时基于和MD4相同原理,并且模仿了该算法。

    什么是Hash表?什么又是Hash冲突?

    HASH表

      哈希表是基于数组的一种存储方式,它主要由哈希函数和数组构成。当要存储一个数据的时候,首先用一个函数计算数据的地址,然后再将数据存进指定地址位置的数组里面。这个函数就是哈希函数,而这个数组就是哈希表。

    哈希冲突

      哈希是通过对数据进行再压缩,转为为固定长度的输出。但由于通过哈希函数产生的哈希值是有限的,而数据可能比较多,导致经过哈希函数处理后仍然有不同的数据对应相同的值。

    哈希冲突的影响因素

    装填因子(装填因子=数据总数 / 哈希表长)、哈希函数、处理冲突的方法

    HASH冲突的解决方案

    三种解决hash冲突的方法.jpg

    1.开放地址方法

    (1)线性探测

      按顺序决定值时,如果某数据的值已经存在,则在原来值的基础上往后加一个单位,直至不发生哈希冲突。

    (2)再平方探测

      按顺序决定值时,如果某数据的值已经存在,则在原来值的基础上先加1的平方个单位,若仍然存在则减1的平方个单位。随之是2的平方,3的平方等等。直至不发生哈希冲突。

    (3)伪随机探测

      按顺序决定值时,如果某数据已经存在,通过随机函数随机生成一个数,在原来值的基础上加上随机数,直至不发生哈希冲突。

    2.链式地址法(HashMap的哈希冲突解决方法)

    对于相同的值,使用链表进行连接。使用数组存储每一个链表。

    优点:

    (1)拉链法处理冲突简单,且无堆积现象,即非同义词决不会发生冲突,因此平均查找长度较短;

    (2)由于拉链法中各链表上的结点空间是动态申请的,故它更适合于造表前无法确定表长的情况;

    (3)开放定址法为减少冲突,要求装填因子α较小,故当结点规模较大时会浪费很多空间。而拉链法中可取α≥1,且结点较大时,拉链法中增加的指针域可忽略不计,因此节省空间;

    (4)在用拉链法构造的散列表中,删除结点的操作易于实现。只要简单地删去链表上相应的结点即可。

    缺点:
      指针占用较大空间时,会造成空间浪费,若空间用于增大散列表规模进而提高开放地址法的效率。

    3.建立公共溢出区

      建立公共溢出区存储所有哈希冲突的数据。

    4.再哈希法

      对于冲突的哈希值再次进行哈希处理,直至没有哈希冲突。

    相关文章

      网友评论

        本文标题:你真的了解HASH吗?

        本文链接:https://www.haomeiwen.com/subject/vtkrwktx.html