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