字节 GMPT 后端日常实习一面:HashMap、Kafka 与缓存一致性
- 轮次
- 一面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 你对大学所读的软件工程专业有什么看法?
- 什么时候能到岗?最多能实习几个月?
- 最近有看什么书吗?和计算机相关的,讲讲你的收获与心得。
- 介绍一下你这两个项目,项目来自哪里,是你构思的吗?
- 项目有实际落地上线吗?做这两个项目遇到的最大困难是什么?平时怎么用 AI?结合实际项目讲一个具体使用 Codex 的场景。
- java.util 包了解过吗?
- HashMap 的底层结构是怎样的?具体怎么插入数据?
- Lua 脚本为什么能保持原子性?了解过底层原理吗?
- 缓存穿透是什么?
- Kafka 的可靠性与高性能是怎么保证的?
- 平时使用 Kafka 这类中间件时,遇到的最大困难是什么?
- 详细讲讲 Kafka 的 offset。
- 为什么另一个项目不用 Kafka,却用了 Redis Stream?
- 缓存与数据库的最终一致性怎么做到?
- 算法题:把一个数字转成字符串(要考虑正负号和小数点)。
《参考解析》
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 异步删除;强一致要靠分布式锁或让读请求串行化,但代价高,多数业务接受最终一致。