面灵AI→

字节 GMPT 后端日常实习一面:HashMap、Kafka 与缓存一致性

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 你对大学所读的软件工程专业有什么看法?
  2. 什么时候能到岗?最多能实习几个月?
  3. 最近有看什么书吗?和计算机相关的,讲讲你的收获与心得。
  4. 介绍一下你这两个项目,项目来自哪里,是你构思的吗?
  5. 项目有实际落地上线吗?做这两个项目遇到的最大困难是什么?平时怎么用 AI?结合实际项目讲一个具体使用 Codex 的场景。
  6. java.util 包了解过吗?
  7. HashMap 的底层结构是怎样的?具体怎么插入数据?
  8. Lua 脚本为什么能保持原子性?了解过底层原理吗?
  9. 缓存穿透是什么?
  10. Kafka 的可靠性与高性能是怎么保证的?
  11. 平时使用 Kafka 这类中间件时,遇到的最大困难是什么?
  12. 详细讲讲 Kafka 的 offset。
  13. 为什么另一个项目不用 Kafka,却用了 Redis Stream?
  14. 缓存与数据库的最终一致性怎么做到?
  15. 算法题:把一个数字转成字符串(要考虑正负号和小数点)。

《参考解析》

HashMap 是数组 + 链表 + 红黑树。插入时先算 key 的 hash(扰动函数让高位参与运算),再对数组长度取模定位桶;桶为空直接放,有冲突就挂链表,链表长度超过 8 且数组长度不小于 64 时转红黑树;负载因子 0.75,超过阈值扩容为两倍并重新分配。JDK 8 的扩容会保留节点相对顺序,避免并发下的死链。

Lua 脚本的原子性来自 Redis 单线程执行:脚本作为一个整体被 Redis 执行,期间不会插入其他命令,所以「读-判断-写」不会被并发打断。它不是数据库事务,没有回滚,脚本里报错前面的写仍然生效。

缓存穿透是查不存在的数据,请求绕过缓存直打数据库。解决用布隆过滤器提前拦截,或把空结果也缓存一个短过期时间。

Kafka 的可靠性靠副本(replication)、acks=all、ISR 机制和幂等生产者;高性能靠顺序写磁盘、零拷贝、批量发送、分区并行和页缓存。offset 是消费者在分区内的消费位置,提交 offset 表示「这条及之前已处理」,重复消费和丢失都源于提交时机。

选 Redis Stream 而不是 Kafka,通常是因为数据量小、部署成本低、复用现有 Redis,且只需要简单的消费组语义;Kafka 更适合高吞吐、长期保留、多消费者的场景。

缓存与数据库一致性:常用 Cache Aside,写时先更新数据库再删除缓存,配合延迟双删或订阅 binlog 异步删除;强一致要靠分布式锁或让读请求串行化,但代价高,多数业务接受最终一致。