redis的哈希算法和java的HashMap有什么差别

这个问题是一个面试官问到的

到现在我也没明白,他具体要问哪个?

有查了一些资料

本来大概也知道旧版的HashMap基本上就是传统的数组+链表的方式实现,

1、对key进行hash算法,取模,比如取模20,那么数组的长度就是20

2、那么如果取模的话一定存在某些key在同一个数组索引中(也称为同一个桶中),也可以叫hash冲突,这些概念都只是为了帮助理解,没必要太纠结

那么如何解决hash冲突?就是上面说到的链表,桶中将会转换成链表结构

我们可以理解为数组是一个一级索引,链表中才是真正的表数据

为什么不直接用全数组的形式:空间问题

缺陷:

1、哈希冲突频繁情况下,性能问题:可能需要进行重新分配桶

2、链表数据量大的情况下,查询性能的问题

Java8之后增加了红黑树的实现,红黑树是自平衡的二叉树,能实现良好的查询性能,相应的就是解决链表数据量大的情况下,查询性能的问题(单桶数据量大)

那么我们再看看redis,redis中也是有hash的数据类型

由于redis使用的不是java语言,源码并未过多分析,这边参考下这个博客:https://blog.csdn.net/mccand1234/article/details/93411326

从这边来看的,这里采用的应该和旧版的HashMap实现没有太大差别。

所以我不太明白之前的面试官是挖坑给我,还是另有所指

所以在学习redis的同时,这边又涉及到一个切片的问题,切片这边指的是当系统承载的访问量、数据量越来越多的情况下,单机甚至普通的集群业务分层都无法满足的情况下,需要进行更细的切分

常用的三种切分方式:

  1、取模Hash

  2、随机(适用于消息队列模式,即不管你往哪一台机子存数据,都有消费者阻塞读取,消费掉这个数据)

  3、一致性Hash

这边也涉及到了hash算法,所以我也不太清楚是否面试官问的是这个

取模算法理论上和Java的HashMap应该也是差别不大

一致性Hash则有些不同

  1、构建一个0~2^32的一个环形空间(逻辑)

  2、通过对nodeName或者IP等进行hash函数取值,对应到这个环形空间的某个位置,代表具体的物理节点

  3、客户端访问的时候对数据也进行一样的hash函数取值,对应到环形空间的某个位置,注意一般这里不会直接能找到物理节点,而是通过一个顺时针或者逆时针的方式来获取,这也是这个环形空间的存在意义(帮助理解)

  

存在的问题:

  1、新增节点:会对相近的节点造成影响,导致原来指向相近节点的客户端,被重新指向新节点,造成缓存穿透;但是一般只影响一个节点,且如果只是作为缓存使用(而非数据库),应该是可以容忍的

  2、数据倾斜的问题,数据分布可能会集中到某几个节点中;这个和HashMap的桶中个别数据量特别大是一样的道理。解决方式:可以通过一些虚拟节点,来让环形中的节点更均匀

原文地址:https://www.cnblogs.com/gabin/p/13670935.html