面试复盘:哔哩哔哩、蔚来、字节跳动、小红书面试与总结
在这次面试过程中,我遇到了一些技术性问题,虽然有些难度,但也促使我深入思考了很多基础知识和工程实现的细节。在面试的过程中,我有一些收获,也发现了自己的一些不足,下面是我对各个面试环节的详细复盘。
#### 哔哩哔哩实习二面(zlx)
**1. 大量的 `TIME_WAIT` 或 `CLOSE_WAIT` 出现怎么办?会有哪些影响(端口占用角度)?**
在这个问题中,我首先讲解了 `TIME_WAIT` 和 `CLOSE_WAIT` 的定义,指出它们都是TCP连接的状态。`TIME_WAIT` 状态通常在连接关闭后进入,目的是确保所有数据都被传输并处理完。`CLOSE_WAIT` 状态则表示本地端收到了对方的关闭请求,但本地端尚未关闭连接。
如果大量的 `TIME_WAIT` 或 `CLOSE_WAIT` 状态占用端口,会导致系统资源的浪费,可能导致端口耗尽,从而影响新连接的建立。通常的解决方式包括:
- **调整TCP连接的超时参数**:可以通过调整操作系统内核的 `tcp_fin_timeout` 等参数,减少 `TIME_WAIT` 状态的持续时间。
- **复用端口**:在一些高并发场景下,可以使用 `SO_REUSEADDR` 或 `SO_REUSEPORT`,来复用端口。
- **使用 `keepalive` 参数**:对于长时间运行的连接,可以考虑设置 `TCP_KEEPALIVE` 参数,避免不必要的连接占用资源。
面试官似乎对我的回答比较认可,继续提了几个相关的问题,比如如何优化TCP连接管理,如何避免端口泄漏等。
---
#### 蔚来实习一面(zlx)
**八股问题:**
- **git 合并冲突你喜欢用 `merge` 还是 `rebase`?**
我选择了 `rebase`,因为它能够保留更加干净的历史记录,使得提交历史看起来更加线性。但在多人协作开发时,`merge` 可能更加安全,因为它保留了分支的历史。如果是自己的单独开发,`rebase` 能有效避免分支历史的杂乱。
- **git 如何推送到多个版本上?**
在这方面我回答了使用 `git push` 的 `--all` 参数或者在不同的远程仓库配置多个 `push` 目标来推送到多个版本。但我意识到,这个问题可能更多是在问如何进行版本发布管理,在这方面我可以进一步学习。
- **Go 协程和 Java 线程的区别?**
Go 协程是由Go runtime管理的轻量级线程,它们共享地址空间,启动和销毁成本低。相比之下,Java 线程是由操作系统管理的,通常启动和销毁的开销较大。Go 协程的调度是由Go运行时负责的,而Java线程则由操作系统调度。
- **MySQL 查询优化:**
在谈到查询优化时,我分享了常见的优化方法:
1. **使用索引**:确保 WHERE 子句、JOIN 操作的字段上有索引。
2. **避免全表扫描**:避免在大数据表上进行全表扫描,尤其是在查询中涉及 `LIKE` 和 `OR` 时。
3. **优化查询结构**:减少子查询,避免嵌套查询,使用 `EXPLAIN` 分析查询计划,找出瓶颈。
4. **合理使用缓存**:使用查询缓存和应用层缓存减少数据库的访问次数。
---
#### 字节跳动二面(挂)
**1. 自我介绍:**
我简要介绍了自己的项目经验和技术栈,包括后端开发和数据库优化等方面,但面试官对于我如何调研后端技术更有前景的部分提了更多问题,这一块我的回答显得有些浅显,可能没有准确把握面试官的期望。
**2. 一个记录用户登录登出的日志文件,如何从日志文件中得到一天最大同时在线人数?**
我首先提到可以通过记录每个用户的登录登出时间来计算,并使用布隆过滤器来判断是否在线。布隆过滤器可以有效地减少空间消耗,但也会带来一定的误判率。面试官问得很深入,这个问题让我对如何在大数据量场景中进行优化有了更深的思考。
**3. 计算机学习经历和难题:**
我被问到最难的事情是什么,回答了四元数问题。在项目中,四元数用于导航系统和成像系统中,它们在三维空间中的旋转运算非常复杂。由于项目涉及到大量的四元数运算,如何高效计算是我面临的挑战之一。
**4. 算法题:**
我被问到了一道 SQL 查询的算法题,要求找出相同的人。这一题让我回想起了 SQL 查询优化中的一些技巧,如何设计高效的查询条件来提高性能。
---
#### 小红书二面(挂)
**1. 为什么选择 Gin 框架?与其他框架或 Go 的 net 包有什么优势?**
在这一题中,我提到 Gin 是 Go 语言中一个高效的 Web 框架,它提供了更高效的路由匹配和中间件支持,适用于高并发场景。与 `net/http` 包相比,Gin 进一步封装了很多操作,简化了开发流程。
**2. Goroutine 栈内存不够的情况下会扩充,什么情况下扩充,怎么监控?**
我解释了 Goroutine 的栈内存会在需要时自动扩展,默认从 2KB 开始,扩展到更大时是由 Go 的运行时调度器负责管理的。我提到可以通过 `GODEBUG` 环境变量来监控和调试 Goroutine 的栈内存情况。
**3. Golang 错误处理:**
关于 Golang 的错误处理机制,我回答了 Go 的错误处理相对繁琐,因为每个函数都需要显式地返回错误,但也可以通过自定义错误类型和包来简化错误的判断和处理。
---
#### 总结
面试过程中,我意识到自己对于一些基础概念理解得不够深入,特别是在分布式架构和高并发场景下的优化措施方面。在后续的学习中,我会更加注重对操作系统、数据库、网络协议等基础技术的深入理解,争取在以后的面试中能够更加自信地应对相关问题。同时,我也会多做一些项目实战,提升自己的技术积累和解决问题的能力。