2024年鸿蒙最新07(1),2024年最新面试总结范文大全

img
img

网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。

需要这份系统化的资料的朋友,可以戳这里获取

一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!

简单解释:哈希(Hash)算法,即散列函数。它是一种单向密码体制,即它是一个从明文到密文的不可逆的映射,只有加密过程 没有解密过程。同时,哈希函数可以将任意长度的输入经过变化以后得到固定长度的输出。哈希函数的这种单向特征和输出数据长度固定的特征使得它可以生成消息或者数报

2. 哈希算法在分布式场景中的应用场景

Hash算法在很多分布式集群产品中都有应⽤,⽐如分布式集群架构Redis、Hadoop、ElasticSearch,Mysql分库分表Nginx负载均衡等。

2.1 请求的负载均衡

nginx的ip_hash策略,通过对ip地址或者sessionid进⾏计算哈希值,哈希值与服务器数量进⾏取模运算,得到的值就是当前请求应该被路由到的服务器编号,如此,同⼀个客户端ip发送过来的请求就可以路由到同⼀个⽬标服务器,实现会话粘滞

2.2 分布式存储

以分布式内存数据库Redis为例,集群中有redis1,redis2,redis3 三台Redis服务器。那么,在进⾏数据存储时,<key1,value1>数据存储到哪个服务器当中呢?针对key进⾏hash处理hash(key1)%3=index, 使⽤余数index锁定存储的具体服务器节点。

分库分表的数据库可以同样用类似逻辑处理

3. 哈希算法存在的问题

3.1 哈希碰撞

index = HashCode (Key) % Array.length
int index=Math.abs("Hello".hashCode())%10; (0-9)

以上面的demo为例,对象Hash的前提是hashCode()方法,那么HashCode()的作用就是保证对象返回唯一hash值,但当两个对象计算值一样时,这就发生了碰撞冲突。

当我们对某个元素进行哈希运算,得到一个存储地址,然后要进行插入的时候,发现已经被其他元素占用了,其实这就是所谓的哈希冲突,也叫哈希碰撞

简单来说,就是两个不同的待存储元素,经过哈希函数计算后得到的存储位置一样,这样两个存储元素就冲突了。举个极端的例子,当长度为10 的数组要存储11个元素的时候,那么哈希碰撞一定会发生。

3.2 哈希碰撞常见解决方式

3.2.1 开放寻址法

开放寻址法的原理是当一个Key通过哈希函数获得对应的数组下标已被占用时,就寻找下一个空档位置。
在这里插入图片描述
在Java中,ThreadLocal所使用的就是开放寻址法

3.2.2 拉链法

数组的每一个元素不仅是一个Entry对象,还是一个链表的头节点。每一个Entry对象通过next指针指向它的下一个Entry节点。当新来的Entry映射到与之冲突的数组位置时,只需要插入到对应的链表中即可,默认next指向null
在这里插入图片描述
在Java中,HashMap所使用的就是链表法。(这里留意java8中,当节点元素过多的时候,为避免链表过长,链表会调整为红黑树)

3.3 分布式环境中的问题

我们知道哈希算法中很重要的两个因素,一个是哈希表,一个是哈希函数,哈希函数的好坏决定数据能不能均衡的分布在哈希表中,如果哈希算法不好的话,可能很多值会路由到同一个位置,造成频繁的哈希碰撞。极端情况会导致哈希表退化为单链表。

哈希表的长度也是很重要的因素,如果太短的话,可能会导致很多元素挂在链表上,最终退化为单链表,如果长度过长的话,会造成内存空间的浪费。

在分布式环境中,常见的场景是服务的扩容缩容,以上面提到的例子为例,比如mysql存储到瓶颈了,我们需要扩容mysql节点,此时就需要扩容。比如双十一的时候,我们为了支持更多的请求处理,在nginx后面加了多台tomcat 服务器处理请求,在双十一过后,请求没那么多,我们可以选择释放部分服务器资源,节省服务器成本。

3.4 本质

通过上面举例子可以看到,哈希算法用的好,确实可以提高我们的查询效率。但是不管是在jdk中的hashmap扩容缩容,还是我们分布式场景中的服务器资源扩容缩容,其实本质上都是对哈希表的扩容缩容。而固定的哈希函数在扩容缩容的时候,需要存储的元素重新哈希计算元素的在扩容后的哈希表中的位置。

那么,有没有其他办法,在哈希表扩容缩容的时候,不重新计算所有元素位置呢,就是下面的一致性哈希算法

4. 一致性哈希算法

⾸先有⼀条直线,直线开头和结尾分别定为为1和2的32次⽅减1,这相当于⼀个地址,对于这样⼀条线,弯过来构成⼀个圆环形成闭环,这样的⼀个圆环称为hash环。我们把服务器的ip或者主机名求hash值然后对应到hash环上,那么针对客户端⽤户,也根据它的ip进⾏hash求值,对应到环上某个位置,然后如何确定⼀个客户端路由到哪个服务器处理呢?

在这里插入图片描述
按照顺时针⽅向找最近的服务器节点
在这里插入图片描述
假如将服务器3下线,服务器3下线后,原来路由到3的客户端重新路由到服务器4,对于其他客户端没有影响只是这⼀⼩部分受影响(请求的迁移达到了最⼩,这样的算法对分布式集群来说⾮常合适的,避免了⼤量请求迁移 )
在这里插入图片描述
增加服务器5之后,原来路由到3的部分客户端路由到新增服务器5上,对于其他客户端没有影响只是这⼀⼩部分受影响(请求的迁移达到了最⼩,这样的算法对分布式集群来说⾮常合适的,避免了⼤量请求迁移 )
在这里插入图片描述

5. 手写一致性哈希算法

5.1 普通哈希

package org.wanlong.hash;

/\*\*
 \* @author wanlong
 \* @version 1.0
 \* @description: 普通哈希
 \* @date 2023/5/23 13:37
 \*/
public class GeneralHash {

    public static void main(String[] args) {
        // 定义客户端IP
        String[] clients = new String[]
                {"102.178.122.12", "23.243.63.2", "8.8.8.8"};
        // 定义服务器数量
        int serverCount = 3;// (编号对应0,1,2)
        // hash(ip)%node\_counts=index
        //根据index锁定应该路由到的tomcat服务器
        for (String client : clients) {
            int hash = Math.abs(client.hashCode());
            int index = hash % serverCount;
            System.out.println("客户端:" + client + " 被路由到服务器编号为:"
                    + index);
        }
    }
}

5.2 一致性哈希

package org.wanlong.hash;

import java.util.SortedMap;
import java.util.TreeMap;

/\*\*
 \* @author wanlong
 \* @version 1.0
 \* @description: 一致性哈希
 \* @date 2023/5/23 13:40
 \*/
public class ConsistHash {

    public static void main(String[] args) {
        //step1 初始化:把服务器节点IP的哈希值对应到哈希环上
        // 定义服务器ip
        String[] tomcatServers = new String[]
                {"23.23.0.0", "7.4.3.1", "7.6.6.8", "6.6.7.7"};
        SortedMap<Integer, String> hashServerMap = new TreeMap<>();
        for (String tomcatServer : tomcatServers) {
            // 求出每⼀个ip的hash值,对应到hash环上,存储hash值与ip的对应关系
            int serverHash = Math.abs(tomcatServer.hashCode());
            // 存储hash值与ip的对应关系
            hashServerMap.put(serverHash, tomcatServer);
        }


        //step2 针对客户端IP求出hash值


![img](https://img-blog.csdnimg.cn/img_convert/b5a047a77d6d17fdfb419e748251634c.png)
![img](https://img-blog.csdnimg.cn/img_convert/16e4aa20ebb7d56106af52c325b6afcf.png)

**网上学习资料一大堆,但如果学到的知识不成体系,遇到问题时只是浅尝辄止,不再深入研究,那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

那么很难做到真正的技术提升。**

**[需要这份系统化的资料的朋友,可以戳这里获取](https://bbs.csdn.net/topics/618636735)**


**一个人可以走的很快,但一群人才能走的更远!不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!**

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值