Skip to content

面试速答(先看这里)

**一句话结论:**这个问题挺有意思的,如果真要对比,可以列出几十条的区别来,因为毕竟他们俩差异太大了, 一个是Redis中的,一个是Java中的,虽然都是hash结构。

60秒标准回答:

这个问题挺有意思的,如果真要对比,可以列出几十条的区别来,因为毕竟他们俩差异太大了, 一个是Redis中的,一个是Java中的,虽然都是hash结构。如果面试官问这个问题的话,我认为他可能比较关注的是这几个区别

1、底层数据结构

2、并发安全相关

**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点

回答主线:

  • **要点1:**Redis的hash结构底层是基于ziplist(压缩列表)和hashtable实现的(6.0中ziplist改为了listpack)。
  • **要点2:**ziplist用于小的hash结构,而hashtable用于大的hash结构,和zset差不多,也是可以通过配置来调整具体使用的结构的,以下两个同时满足时用ziplist,否则用hashtable。
  • **要点3:**而Java中的HashMap本身并不是线程安全的,需要用使用ConcurrentHashMap来保证线程安全。
  • **要点4:**Redis的hash结构在扩容的时候,采用一种渐进式rehash的方案,可以实现平滑扩容,避免一次性迁移所有数据导致的请求延迟。
  • **要点5:**Java中的HashMap是没有采用渐进式rehash的,而是会一次性完成整个 Map 中所有元素的迁移。

**记忆锚点:**HashMap → Redis → hash → ziplist → hashtable → rehash

关键取舍:

  • Hash 中 k-v 对的数量 <= hash-max-ziplist-entries (默认 512) 所有 k 和 v 的字符串长度 <= hash-max-ziplist-value (默认 64 字节) ziplist/listpack的优点是极其节省内存。
  • hashtable的优点是查找、插入、删除的平均时间复杂度 O(1),适合大数据量。
  • 好处和缺点刚好和上面的渐进式rehash相反,优点是不占用过多空间,缺点就是迁移过程会阻塞。

易错提醒:

  • ( Collections.synchronizedMap(new HashMap<>()) 也可以) Redis的hash结构在扩容的时候,采用一种渐进式rehash的方案,可以实现平滑扩容,避免一次性迁移所有数据导致的请求延迟。

加分表达:

  • 这个问题挺有意思的,如果真要对比,可以列出几十条的区别来,因为毕竟他们俩差异太大了, 一个是Redis中的,一个是Java中的,虽然都是hash结构。
  • 如果面试官问这个问题的话,我认为他可能比较关注的是这几个区别: 1、底层数据结构 2、并发安全相关 Redis的hash结构底层是基于ziplist(压缩列表)和hashtable实现的(6.0中ziplist改为了listpack)。
  • ziplist用于小的hash结构,而hashtable用于大的hash结构,和zset差不多,也是可以通过配置来调整具体使用的结构的,以下两个同时满足时用ziplist,否则用hashtable。

追问准备:

  • 围绕「HashMap」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「Redis」:底层原理是什么?使用时有哪些边界和常见坑?
  • 围绕「hash」:底层原理是什么?使用时有哪些边界和常见坑?
  • 如果线上出现异常,你会如何定位、验证并规避?

典型回答 ​

这个问题挺有意思的,如果真要对比,可以列出几十条的区别来,因为毕竟他们俩差异太大了, 一个是Redis中的,一个是Java中的,虽然都是hash结构。如果面试官问这个问题的话,我认为他可能比较关注的是这几个区别:

1、底层数据结构

2、并发安全相关

3、扩容机制

数据结构 ​

Redis的hash结构底层是基于ziplist(压缩列表)和hashtable实现的(6.0中ziplist改为了listpack)。

ziplist用于小的hash结构,而hashtable用于大的hash结构,和zset差不多,也是可以通过配置来调整具体使用的结构的,以下两个同时满足时用ziplist,否则用hashtable。

  • Hash 中 k-v 对的数量 <= hash-max-ziplist-entries (默认 512)
  • 所有 k 和 v 的字符串长度 <= hash-max-ziplist-value (默认 64 字节)

📄 ✅Redis的ZipList、SkipList和ListPack之间有什么区别?

打开文档:✅Redis的ZipList、SkipList和ListPack之间有什么区别?

ziplist/listpack的优点是极其节省内存。没有指针开销,内存局部性好。但是缺点就是增删改查操作(尤其是中间插入/删除)时间复杂度 O(n),效率较低。

hashtable的优点是查找、插入、删除的平均时间复杂度 O(1),适合大数据量。缺点就是内存开销较大,需要额外存储指针。

📄 ✅ZSet为什么在数据量少的时候用ZipList,而在数据量大的时候转成SkipList?

打开文档:✅ZSet为什么在数据量少的时候用ZipList,而在数据量大的时候转成SkipList?

而HashMap采用的是数组+链表+红黑树的存储结构。

📄 ✅HashMap的数据结构是怎样的?

打开文档:✅HashMap的数据结构是怎样的?

并发安全 ​

因为Redis本身是单线程执行命令的,所以所有对 Redis Hash 的操作都是线程安全的。

而Java中的HashMap本身并不是线程安全的,需要用使用ConcurrentHashMap来保证线程安全。(Collections.synchronizedMap(new HashMap<>())也可以)

扩容机制 ​

Redis的hash结构在扩容的时候,采用一种渐进式rehash的方案,可以实现平滑扩容,避免一次性迁移所有数据导致的请求延迟。但是缺点就是在数据迁移期间,内存占用是翻倍的。

📄 ✅什么是Redis的渐进式rehash

打开文档:✅什么是Redis的渐进式rehash

Java中的HashMap是没有采用渐进式rehash的,而是会一次性完成整个 Map 中所有元素的迁移。好处和缺点刚好和上面的渐进式rehash相反,优点是不占用过多空间,缺点就是迁移过程会阻塞。

但是其实HashMap也没必要搞渐进式rehash,因为HashMap一般都是存很少的数据,不像Redis一样大家会拿他来存很多东西。