面灵AI→

多益网络 软件工程师 秋招一面

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

《面试题目》

  1. 请先做一下自我介绍
  2. 实习拷打
  3. Linux 中如何定位某个端口被哪个进程占用?
  4. Linux 环境变量、Shell 变量和进程环境之间有什么区别?
  5. MySQL 的聚簇索引和二级索引在查询路径上有什么区别?
  6. 哪些情况下索引可能无法有效使用?
  7. 为什么给一个字段建立了索引,查询速度仍然可能没有提升?
  8. 联合索引中,字段顺序应该如何选择?
  9. 使用分页查询时,为什么页码越大越慢?如何改进?
  10. MySQL 的隔离级别分别解决什么问题?为什么可重复读仍然可能出现复杂并发现象?
  11. Redis 适合保存哪些数据?哪些内容不应该直接放入 Redis?
  12. Redis 的缓存击穿、缓存穿透和缓存雪崩分别如何处理?

《参考解析》

  1. 定位端口占用:ss -lntp | grep <port> 或 lsof -iTCP:<port> -sTCP:LISTEN 能直接给出进程号;知道进程号之后用 ps -fp <pid> 看启动命令、readlink -f /proc/<pid>/exe 看真实可执行文件、ls -l /proc/<pid>/fd 看它打开了哪些文件。容器场景要同时查宿主机端口和容器内部端口,只看一边经常得出「端口没被占用」的错误结论。
  2. Shell 变量 / 环境变量 / 进程环境:Shell 变量只在当前 shell 进程内有效;export 之后才会进入子进程的环境块。进程的环境在启动那一刻就被复制下来,之后再改 shell 变量不会影响已经跑起来的进程——tr '\0' '\n' < /proc/<pid>/environ 看到的才是它真正拿到的环境。另外不同启动方式加载的配置文件不同(登录 shell 读 /etc/profile,systemd 读 Environment=,容器读 Dockerfile 里的 ENV),「本地能跑线上不能跑」很多时候就是这里对不上。
  3. 聚簇索引 vs 二级索引:InnoDB 的聚簇索引按主键组织,叶子节点存整行数据;二级索引的叶子节点只存索引列 + 主键值。走二级索引查询时,如果需要的列不全在索引里,就得拿主键回聚簇索引再查一次,这就是回表。所以「查询返回的列」和「查询条件」一样重要——把返回列也放进索引就是覆盖索引,能直接省掉回表。
  4. 索引失效的常见场景:对索引列做函数或表达式运算(DATE(create_time) = ...)、隐式类型转换(字符串列传数字)、前导通配符 like '%x'、联合索引没用上最左列、or 连接了非索引列、选择性太差(取值只有几个)、数据量太小优化器认为全表扫更快、以及范围条件后面的联合索引列用不上。判断方式只能是 EXPLAIN 看实际执行计划,光看 SQL 形式会误判。
  5. 建了索引为什么还是慢:优化器是按成本选路径的,不是「有索引就用」。区分度低、回表量大、统计信息过期、数据倾斜、缓存导致测试结果失真,都会让它放弃索引。另外索引本身也有维护成本(写放大、页分裂、空间),所以索引不是越多越好——先看 EXPLAIN ANALYZE 的估算行数与实际行数差多少,再决定是改 SQL 还是改索引。
  6. 联合索引字段顺序:原则是「等值条件在前、范围条件在后」,同时兼顾排序需求。比如固定有 tenant_id = ? and event_type = ? and created_at between ? and ?,那 (tenant_id, event_type, created_at) 能让前两列做精确定位、第三列做范围扫描,是最优的。不要把「区分度最高的放最前」当铁律——如果最左列是范围条件,后面的列就完全用不上了。
  7. 深分页优化:limit 100000, 20 会先扫描并丢弃前 10 万行。改成游标分页(where id > ? order by id limit 20)能直接跳到起点;排序字段不唯一时用组合游标 where (created_at, id) < (?, ?)。前提是排序字段上有索引、字段稳定(不会在翻页过程中被更新),并且要明确「翻页期间有新增/删除」时希望看到什么语义。另一种做法是延迟关联:先用覆盖索引把主键查出来,再 join 回原表取数据。
  8. 隔离级别与可重复读:读未提交会脏读;读已提交解决脏读但同事务内两次读可能不同;可重复读让普通一致性读在整个事务里看到同一个快照;串行化用更强并发限制换一致性。InnoDB 的 RR 靠 MVCC 提供快照读,靠 Next-Key Lock 处理当前读——所以「普通 select 不出现幻读」和「for update 下仍要考虑间隙锁」是两件事,隔离级别不能脱离具体 SQL 讨论。
  9. Redis 的适用边界:适合热点查询结果、session、分布式锁状态、排行榜、计数器、限流令牌、短期任务状态——共同点是访问频繁、结构明确、丢了能重建。不适合当永久数据库:不可恢复的账务数据、没有持久化策略的大对象、无限增长的日志,都不该直接塞进来。使用前要先把 key 命名规范、TTL、容量上限、序列化格式、热 key 与大 key 的处理、淘汰策略、数据重建方式定下来。
  10. 穿透 / 击穿 / 雪崩:穿透是查不存在的数据,用布隆过滤器、空值缓存、参数校验挡;击穿是单个热点 key 过期的瞬间大量请求打到后端,用互斥锁、逻辑过期或后台异步刷新;雪崩是大量 key 同时失效或整个集群不可用,用过期时间加随机值、分批预热、多级缓存和限流降级。三者的共同前提是「缓存命中失败时后端能不能扛住」,所以熔断降级和热点探测要一起做。