字节跳动抖音生活服务Java后端一面凉经
面试题目
一、个人 & 实习背景
- HTTP 协议讲讲
- 只是把 HTTP 改成 WebSocket,那内部处理流程或编排具体有什么变化?
- 关键是怎么把完整音频基于什么维度切割?
- 延迟从 800ms 降到 200ms,这个 800ms 是处理完成返回的时间吗?
- 是发起请求之后,完整响应吗?从请求到所有 response 收完?
- 确认一下延迟口径:是接口请求维度,从发起网络请求到数据全部接收完成?
- 端到端的链路流程说一下?
二、计算机网络 & 操作系统
- HTTP 请求信息里面有哪些内容?Request 里都有什么?
- HTTP 和 HTTPS 的区别是什么?
- HTTPS 传输过程中具体是怎么保证数据安全的?
- 现在浏览器都是多进程,进程之间协作通信方式有哪些?
- 进程之间的通信方式有哪些?
- 方法的入参、出参、局部变量在内存哪块区域?
三、Redis & MySQL & 中间件
- Redis、MySQL 这些组件用过吗?
- 缓存怎么使用 Redis?具体怎么用?
- 积分排行榜是整个站点所有用户积分排名吗?
- Redis List 有数量上限,量大后性能会有问题,几万几十万用户还能用吗?
- Redis 集群解决了什么问题?
- 排行榜是一个 key,集群怎么分?
- 100 万用户按 1 万一组分片:
- 新用户进来往哪个分片加?
- 边缘用户积分变动,跨分片时数据怎么处理?
- 有更好的方案吗?
- Redis 还用过其他功能吗?
- 不重复领优惠券是什么场景?
- Lua 脚本里查,其他人同时执行不也会有问题吗?
- Redis 持久化方式有哪些?
- MySQL InnoDB 为什么用 B+ 树?
- MQ 用过吗?了解吗?知道是做什么、解决什么问题吗?
四、项目 & 架构
- 之前做的都是 Spring Boot 单体服务吗?
- 有没有接触过微服务架构?
五、算法题
- 第 k 个排列有思路吗?
- LeetCode Hard 60. 排列序列
参考解析
HTTP 与 HTTPS 区别及 HTTPS 安全保障
HTTPS = HTTP + TLS/SSL,主要差异:端口(80 vs 443)、数据加密、身份验证。 TLS 握手流程:客户端发 ClientHello → 服务端返回证书 → 客户端验证证书并生成预主密钥(用服务端公钥加密)→ 双方各自生成会话密钥 → 后续使用对称加密传输。 核心保障:非对称加密交换密钥,对称加密传输数据,CA 证书防中间人攻击。
HTTP Request 组成
请求行(Method + URL + HTTP版本)、请求头(Host、Content-Type、Cookie、Authorization 等)、空行、请求体(POST/PUT 时携带数据)。
进程间通信方式(IPC)
管道(匿名/命名)、消息队列、共享内存、信号量、Socket、信号。浏览器多进程间常用 IPC(Chromium 用 Mojo 框架),本质是 Socket 或共享内存。
方法入参/出参/局部变量的内存区域
均存放于**虚拟机栈(Stack Frame)**中的局部变量表。每次方法调用创建一个栈帧,方法返回后栈帧出栈,内存自动释放。对象本身在堆上,栈中存的是引用。
Redis ZSet 做排行榜 & 集群分片问题
ZSet(有序集合)天然支持排行榜,底层跳表+哈希,O(log N) 插入/查询。 单 key 在集群中只能落在一个 slot/节点,无法水平扩展。 大规模方案:按分数区间分桶(如每10万分一个 ZSet key),查全榜时多桶合并;或使用 Top-K 近似算法;跨分片积分变动需先删旧桶再插新桶,可用 Lua 脚本保证原子性。
Redis Lua 脚本与原子性
Redis 单线程执行 Lua 脚本,整个脚本执行期间不会被其他命令打断,天然原子。因此”查+写”放在同一 Lua 脚本内可解决并发重复领券问题(相比 GET + SET 两步操作有竞态)。
Redis 持久化方式
- RDB:定时快照,文件紧凑,恢复快,但可能丢失最后一次快照后的数据。
- AOF:记录每条写命令,数据更安全,文件较大,恢复慢;支持 always/everysec/no 三种 fsync 策略。
- 混合持久化(Redis 4.0+):AOF 重写时以 RDB 格式存量 + AOF 格式增量,兼顾速度与安全。
MySQL InnoDB 为什么用 B+ 树
- B+ 树非叶节点只存 key,叶节点存数据,同等页大小可容纳更多索引项,树高更低(通常 3-4 层),磁盘 IO 少。
- 叶节点双向链表,范围查询只需一次定位后顺序扫描,效率高。
- 相比哈希索引,支持范围查询和排序;相比 B 树,叶节点链表使范围查询无需回溯。
MQ 的作用
三大核心价值:异步解耦(生产者/消费者独立扩展)、流量削峰(缓冲突发流量)、数据分发(一条消息多消费者广播)。常见组件:Kafka(高吞吐日志流)、RocketMQ(金融级可靠)、RabbitMQ(低延迟任务队列)。
LeetCode 60. 排列序列
核心思路:康托展开(逐位确定)。
- 预计算阶乘数组
fact[],fact[i] = i!。 k -= 1(转为0-indexed),维护可用数字列表。- 每次用
k / fact[n-1]确定当前位选第几个数,k %= fact[n-1],n--,重复直到选完。 时间复杂度 O(n²)(列表删除),空间 O(n)。
public String getPermutation(int n, int k) {
int[] fact = new int[n];
fact[0] = 1;
for (int i = 1; i < n; i++) fact[i] = fact[i-1] * i;
List<Integer> nums = new ArrayList<>();
for (int i = 1; i <= n; i++) nums.add(i);
k--;
StringBuilder sb = new StringBuilder();
for (int i = n - 1; i >= 0; i--) {
int idx = k / fact[i];
sb.append(nums.get(idx));
nums.remove(idx);
k %= fact[i];
}
return sb.toString();
}