5 小时前发布43次阅读

面试两个月,被拒了十几次,我终于想明白了一些事

独立开发商业增长付费用户

你好,我是Sia。

上周,我终于收到了那个等了很久的 offer。

你可能觉得没什么了不起。但对我来说,这背后是两个月的煎熬、十几次的拒绝,以及无数次深夜的自我怀疑

我从一所普通二本毕业,在一家小公司做了两年 Java 开发。平时写写 CRUD,改改 bug,日子过得还算安稳。直到今年开始投简历,我才发现 ——外面的世界和我想的完全不一样

第一次面试,面试官问我:“你们项目怎么做接口幂等的?”

我愣住了。幂等?好像听过,但从没真正实现过。

第二次面试,面试官问:“你们的 QPS 大概多少?有没有做过压测?”

我说了个数,面试官笑了一下,没说话。那个笑容我现在还记得。

第三次、第四次…… 连续被拒。

直到上周这家公司给了我 offer,面试官最后说了一句话:“基础不错,能看出来你最近在认真补课。

我想把这段经历里,我最痛的几个 “坑” 分享给你。希望你能绕过它们。

一、自我介绍:别把简历背一遍

前几次面试,我的自我介绍是这样的:

“我叫阿尘,毕业于 XX 学院,有 2 年 Java 经验,做过电商后台和 OA 系统,熟悉 Spring Boot、MyBatis、Redis……”

面试官听完,低头看简历,然后问:“你说说你们电商项目的亮点?”

我:……

后来我才明白:自我介绍是你唯一能主动 “画重点” 的机会。

我改成了这样:

“面试官您好,我有 2 年 Java 经验。我工作中最擅长的两件事:一是排查线上问题,二是做性能优化。

比如我们之前有个报表导出功能,10 万行数据就 OOM 了。我用了 EasyExcel 的流式处理,内存占用从 800MB 降到了 50MB

再比如,我们有个订单查询接口很慢,我通过分析慢查询日志、加联合索引、调整 SQL,把响应时间从 2 秒优化到了 100 毫秒以内

我主要想跟您聊聊我在性能优化和 Redis 实战上的经验。”

效果完全不同。 面试官立刻来了兴趣:“那个 OOM 问题,你具体是怎么排查的?”

你看,自我介绍的核心不是 “你做过什么”,而是 “你能解决什么问题”

二、索引:我踩过最深的坑

面试官问:“你们项目中索引是怎么用的?”

这个问题我答过很多次。但有一次,面试官追问了一句,让我后背发凉:

你实际工作中,有没有建了索引但没走的情况?

我沉默了。

后来我把这个问题彻底研究了一遍,现在可以很自信地回答:

常见原因有以下几种:

  1. 在索引列上做了计算或函数
-- ❌ 不走索引
SELECT * FROM user WHERE age + 1 = 20
-- ✅ 走索引
SELECT * FROM user WHERE age = 19

  1. 隐式类型转换
-- 假设id是int类型
-- ❌ 不走索引(数字字段传字符串)
SELECT * FROM user WHERE id = '123'
-- ✅ 走索引
SELECT * FROM user WHERE id = 123

  1. LIKE 以 % 开头
-- ❌ 不走索引
SELECT * FROM user WHERE name LIKE '%张三%'
-- ✅ 走索引(仅前缀匹配)
SELECT * FROM user WHERE name LIKE '张三%'

  1. 联合索引没有遵循最左前缀法则
-- 联合索引 (a, b, c)
-- ✅ 走索引
WHERE a = 1 AND b = 2
-- ❌ 不走索引(跳过了a)
WHERE b = 2 AND c = 3

我亲身踩过的坑:把索引顺序建反了,导致一条 SQL 跑了 2 秒,调整顺序后 20 毫秒。建索引不是越多越好,而是要建在刀刃上。

三、缓存穿透 / 击穿 / 雪崩:面试必考三兄弟

这三个概念,我背了无数遍。但有一次面试官说:“你别背定义,就说你项目里怎么用的。

我又卡住了。

现在的我,可以这样回答:

缓存穿透(查不到的数据)

场景:有人恶意请求id = -1的数据,每次都会打到数据库。

解决方案

// 查询不到时,缓存一个空对象,过期时间短一些
if (dbResult == null) {
    redis.setex(key, 60, "null");  // 缓存60秒
    return null;
}

缓存击穿(热点数据过期)

场景:一个爆款商品的缓存刚好过期,瞬间大量请求打到数据库。

解决方案:互斥锁,只让一个线程去查数据库。

String lockKey = "lock:" + key;
Boolean locked = redis.setnx(lockKey, "1", 10);

if (locked) {
    try {
        // 双检:再查一次缓存
        data = redis.get(key);
        if (data != null) return data;
        // 查数据库 + 写缓存
        data = db.query(key);
        redis.setex(key, 1800, data);
        return data;
    } finally {
        redis.del(lockKey);
    }
} else {
    // 短暂等待后循环重试,避免递归栈溢出
    Thread.sleep(50);
    continue;
}

缓存雪崩(大量 key 同时过期)

解决方案:过期时间加随机值,避免集体过期。

int baseExpire = 1800;  // 30分钟
int randomOffset = new Random().nextInt(300);  // 0-5分钟随机
int finalExpire = baseExpire + randomOffset;
redis.setex(key, finalExpire, value);

这三个问题,每一个我都实际遇到过。 纸上得来终觉浅,绝知此事要躬行。

四、面试官问:你还有什么想问的?

以前我总说 “没有了谢谢”。后来一个做 HR 的朋友告诉我,这个问题不是走形式,是你的加分题

我后来会问三个问题:

  1. “这个岗位进来后主要做什么业务?技术栈上有什么挑战?”

表现认真和兴趣。
2. “如果我有幸入职,您希望我前三个月重点在哪些方面提升?”

表现成长意愿和对 Leader 期待的重视。
3. “团队目前在技术上遇到的最大难点是什么?”

这个问题最加分。面试官跟我聊了十几分钟他们的慢 SQL 治理和分库分表难题。

提问环节是你最后展示自己的机会,别浪费。

最后

这两个月,我被拒绝过,被已读不回过,也被面试官怼过。

但我还是走出来了。

如果你也正在面试的煎熬中,别放弃。被拒不代表你不行,可能只是还没遇到那个匹配的机会.

为了帮助更多像我一样正在面试的朋友,如果你正在备战 Java 后端或者前端或者测试,想要真实的投递渠道,:point_right:** 点击这里进行投递吧**:https://jsj.top/f/o38ijj

完全免费,纯属互助。 希望能帮到每一个还在咬牙坚持的你。

Offer 会来的。相信我。

讨论 (0)