页面导航
项目经验 MySQL 系统设计 高并发 Spring事务 HR面 更新 2026-06-02

京东技术产品面经:项目挑战、MySQL优化与购物车设计

京东2026校招技术产品面经,涵盖项目挑战、MySQL优化、购物车系统设计及事务、HR面等,助你全面备战。

公司 京东
岗位 技术产品
方向 技术
行业 互联网
招聘类型 校园招聘
年份 2026

面经正文

1. 介绍你做过的一个最有挑战性的项目

回答思路

京东技术面非常注重工程能力的深度,要展示你对系统设计的全局思考,而非只会写业务代码。

  1. 项目背景:规模、业务场景、你的角色。
  2. 挑战定义:是技术挑战(高并发/数据一致性),还是工程挑战(跨团队协作/需求多变)?
  3. 你的解法:核心思路和具体技术方案。
  4. 结果与反思:量化数据 + 如果重来会有什么改变。

回答示例

我做过最有挑战性的项目是一个大学图书馆座位预约系统(面向全校3万名学生)。

挑战点:开放预约时(每天早上8点整),3万学生同时涌入,系统出现严重的接口超时和座位超订问题——同一个座位被多人预约成功。

我的解决方案

第一,前端限流:预约按钮点击后立即置灰(防重复提交),同时加入前端队列(最多500人同时进入预约流程);
第二,Redis原子扣减:将每个座位的可预约状态存入Redis(seat:available:A101 = 1),用Lua脚本原子执行"查询+扣减",保证同一座位只有一次成功:

if redis.call('GET', KEYS[1]) == '1' then
    redis.call('SET', KEYS[1], '0')
    return 1
end
return 0

第三,异步落库:Redis扣减成功后,将预约消息写入RabbitMQ,消费者异步写入MySQL,避免大量同步DB写入压垮数据库;
第四,补偿机制:MQ消费失败时(死信队列)触发自动重试,重试3次后人工告警。

结果:8点开放时并发峰值约3000 QPS,系统稳定运行,零超订,数据库QPS下降75%。

2. MySQL优化:一条慢SQL如何定位和优化?

回答思路

京东仓储/物流数据量巨大,MySQL优化是必考题,要给出完整的排查 → 优化流程。

  1. 发现问题:慢查询日志、监控告警。
  2. 定位问题:EXPLAIN分析执行计划,重点看type/key/rows字段。
  3. 优化手段:索引优化、SQL改写、表结构调整、读写分离/分库分表。

回答示例

第一步:发现慢SQL
通过慢查询日志(long_query_time = 1)或数据库监控工具(如Prometheus + Grafana)发现执行时间超过阈值的SQL。

第二步:EXPLAIN分析
执行EXPLAIN SELECT ... 重点关注:

  • type:ALL(全表扫描,最差)→ index → range → ref → const(最优),目标是达到range及以上;
  • key:是否用到了预期的索引;
  • rows:预估扫描行数,越小越好;
  • Extra:是否出现Using filesort(文件排序,意味着无法利用索引排序)或Using temporary(使用临时表)。

第三步:常见优化手段

  1. 建/修正索引:根据WHERE/ORDER BY/JOIN条件设计联合索引,遵循最左前缀原则;
  2. SQL改写:避免SELECT *(减少数据传输)、用LIMIT限制返回行数、将子查询改为JOIN;
  3. 覆盖索引:在索引上直接包含查询所需字段,避免回表;
  4. 分页优化:深度分页LIMIT 10000, 10性能差,改为游标分页(WHERE id > last_id LIMIT 10);
  5. 读写分离:将读请求路由到从库,降低主库压力。

3. 请设计一个"京东购物车"的后端数据结构

回答思路

系统设计题,考察对实际业务的工程化思维,要考虑登录/未登录状态、数据存储选型、高并发写入。

  1. 需求分析:未登录用户(临时购物车)vs 登录用户(持久化购物车)。
  2. 数据结构设计:用户ID + 商品SKU + 数量 + 价格快照(下单时价格可能变动)。
  3. 存储选型:Redis(高频读写)+ MySQL(持久化)。
  4. 合并逻辑:未登录购物车在登录后如何合并。

回答示例

需求拆分:

  • 未登录用户:购物车存在浏览器本地(localStorage)或后端临时存储(以device_id为key);
  • 登录用户:购物车持久化存储,多端同步。

数据结构设计:
Redis Hash结构:
key: cart:{user_id}
field: sku_id
value: {quantity, price_snapshot, add_time}
用Hash的原因:HSET/HGET/HDEL操作单个商品O(1),HGETALL获取全量购物车O(n),性能高。

MySQL作为持久化备份:

CREATE TABLE cart (
    id BIGINT PRIMARY KEY,
    user_id BIGINT NOT NULL,
    sku_id BIGINT NOT NULL,
    quantity INT NOT NULL,
    price_snapshot DECIMAL(10,2),
    created_at DATETIME,
    updated_at DATETIME,
    INDEX idx_user_id (user_id)
);

合并逻辑:用户登录后,将本地临时购物车中的商品逐一与服务端购物车合并(同一SKU数量相加),合并后删除临时购物车。

价格快照的意义:记录用户加入购物车时的价格,结算时与实时价格对比,展示"比加入时降价XX元"是促进转化的重要产品细节。

4. 算法题:合并K个升序链表

回答思路

京东笔试高频题,要掌握堆(优先队列)方案,时间复杂度O(nk log k)。

回答示例

public ListNode mergeKLists(ListNode[] lists) {
    PriorityQueue<ListNode> heap = new PriorityQueue<>(
        (a, b) -> a.val - b.val
    );
    for (ListNode node : lists) {
        if (node != null) heap.offer(node);
    }
    ListNode dummy = new ListNode(-1);
    ListNode cur = dummy;
    while (!heap.isEmpty()) {
        ListNode minNode = heap.poll();
        cur.next = minNode;
        cur = cur.next;
        if (minNode.next != null) {
            heap.offer(minNode.next);
        }
    }
    return dummy.next;
}
// 时间复杂度 O(nk log k)

5. Redis的主从复制原理是什么?如何解决主从脑裂问题?

回答思路

京东Redis高可用必备知识,主从脑裂(split-brain)是生产环境的真实风险。

  1. 主从复制原理:全量同步(RDB)+ 增量同步(命令传播),断点续传(backlog)。
  2. 主从脑裂问题:网络分区导致从库被选为新主,多主同时写入造成数据分裂。
  3. 解决方案:合理配置min-slave-to-write/min-slave-max-lag,强制主库写入前确认从库数量。

回答示例

Redis主从复制原理:
分为三个阶段:

  1. 全量同步:
    • 从库向主库发送PSYNC ? -1(请求全量同步);
    • 主库执行BGSAVE生成RDB快照,同时记录后续命令到repl_backlog缓冲区;
    • 将RDB文件发送给从库,从库接收后清空本地数据,加载RDB;
    • 将缓冲区中的增量命令发送给从库执行。
  2. 增量同步(命令传播):
    • 主库将每个写命令同时发送给所有从库(主库推送模式)。
  3. 断点续传(Redis 2.8+):
    • 从库重连时发送PSYNC {runid} {offset},主库判断偏移量是否在repl_backlog中(默认1MB),如果在则只发送缺失的命令,避免全量同步。

主从脑裂问题:
网络分区时,主库和从库断开连接,如果从库被哨兵/Cluster自动选为新主,而原主库未感知(新主写入),网络恢复后会产生两个主库,导致数据分裂(旧主的数据覆盖新主,或两主数据不一致)。

解决方案:

min-slave-to-write 2 # 主库写入前至少等待2个从库确认
min-slave-max-lag 10 # 从库延迟超过10秒,主库拒绝写入

这样当网络分区时,如果只有1个从库存活,主库自动降级为只读,强制等待更多从库恢复,避免两个主库同时写入。

6. 算法题:求两个字符串的最长公共子序列(LCS)

回答思路

动态规划经典题,京东笔试高频,dp数组的维度设计是核心难点。

  1. dp[i][j]含义:s1前i个字符和s2前j个字符的LCS长度。
  2. 状态转移:如果s1[i-1]==s2[j-1],则dp[i][j]=dp[i-1][j-1]+1;否则dp[i][j]=max(dp[i-1][j], dp[i][j-1])
  3. 复杂度:O(mn)时间,O(min(m,n))空间优化。

java
public int longestCommonSubsequence(String s1, String s2) {
int m = s1.length(), n = s2.length();
// dp[i][j]: s1[0..i-1] 和 s2[0..j-1] 的LCS长度
int[][] dp = new int[m + 1][n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
dp[i][j] = dp[i - 1][j - 1] + 1;
} else {
dp[i][j] = Math.max(dp[i - 1][j], dp[i][j - 1]);
}
}
}
return dp[m][n];
}

// 空间优化版 O(min(m,n)):滚动数组,只需保留上一行
public int longestCommonSubsequenceOptimized(String s1, String s2) {
if (s1.length() < s2.length()) {
String tmp = s1;
s1 = s2;
s2 = tmp; // s2取较短
}
int m = s1.length(), n = s2.length();
int[] prev = new int[n + 1];
int[] cur = new int[n + 1];
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1.charAt(i - 1) == s2.charAt(j - 1)) {
cur[j] = prev[j - 1] + 1;
} else {
cur[j] = Math.max(prev[j], cur[j - 1]);
}
}
int[] tmp = prev;
prev = cur;
cur = tmp; // 交换并清空cur
Arrays.fill(cur, 0);
}
return prev[n];
}


### 7. 什么是依赖注入?Spring中@Autowired和@Resource的区别?

<strong>回答思路</strong>
Spring框架基础题,京东技术面常见,要说清楚两者的实现原理和区别。

*   依赖注入(DI):Spring自动为Bean注入依赖,而非Bean自己new依赖。
*   @Autowired:byType注入(按类型),配合@Qualifier可指定bean名称。
*   @Resource:byName注入(默认按名称),找不到再按类型。
*   实际选择:如果同一个接口有多个实现,@Autowired+@Qualifier更灵活。

<strong>回答示例</strong>
依赖注入(DI)是IOC的实现方式。传统写法中,ServiceA需要ServiceB,ServiceA自己new ServiceB(),造成强耦合;DI后,Spring容器在创建ServiceA时,自动把ServiceB的实例注入进去,ServiceA不需要关心ServiceB是如何创建的。

<strong>@Autowired(Spring原生)</strong>:

*   默认按类型注入,从容器中找类型匹配的Bean;
*   如果容器中有多个相同类型的Bean,会抛出`NoUniqueBeanDefinitionException`,需要配合`@Qualifier("beanName")`指定具体Bean;
*   可以标注在字段、构造函数、setter方法上。

<strong>@Resource(JDK标准)</strong>:

*   默认按名称(`@Resource(name="xxx")`),找不到再按类型;
*   如果不指定name,先按字段名去容器中找,找不到再按类型;
*   不支持按类型多个候选。

<strong>实战选择</strong>:同一接口有多个实现时,用`@Autowired + @Qualifier("实现Bean名")`;同一接口只有一个实现时,两者差别不大,用哪个都行,但`@Autowired`更符合Spring生态的惯例。

### 8. 京东的库存系统如何设计?如何防止超卖?

<strong>回答思路</strong>
电商核心系统设计题,京东的库存管理是业内标杆,要展示完整的库存架构和防超卖机制。

*   库存分层设计:活动库存(秒杀)/ 可售库存 / 预占库存 / 实物库存。
*   防超卖核心:乐观锁(版本号/状态机)+ Redis原子扣减。
*   下单链路:锁库存(Redis预占)→ 支付(实际扣减)→ 取消/超时回滚。

<strong>回答示例</strong>
<strong>库存分层架构</strong>:
活动库存(Redis,精准备)→ 预占库存(Redis,有限时间内有效)→ 实物库存(MySQL,持久化)

*   <strong>活动库存(如秒杀)</strong>:在活动开始前,将秒杀商品的库存量(可能只有100件)预加载到Redis,所有扣减在Redis完成。

<strong>防超卖机制——Redis Lua原子扣减</strong>:
```lua
local stock = redis.call('GET', 'sku:stock:' .. KEYS[1])
if tonumber(stock) <= 0 then
    return 0, 'STOCK_EMPTY'
end
redis.call('DECR', 'sku:stock:' .. KEYS[1])
return 1, 'SUCCESS'

Lua脚本保证判断和扣减的原子性,不会出现两个请求同时读到库存=1、同时扣减为0的超卖情况。

下单链路中的库存流转

  1. 用户点击下单 → Redis原子扣减活动库存,返回成功 → 订单创建(状态=待支付);
  2. 用户完成支付 → MySQL实物库存扣减(乐观锁)→ 订单状态变更为已支付;
  3. 用户取消订单或支付超时(如30分钟)→ Redis活动库存回滚(INCR)+ 预占库存释放 → MySQL库存不变(实物还未真正扣减)。

这种设计保证了超高并发的秒杀场景下Redis承担所有压力,MySQL不会被直接击穿。

9. 什么是Spring事务的传播行为?@Transactional有哪些失效场景?

回答思路
Spring事务是京东Java岗必考题,要覆盖7种传播行为 + 常见失效场景。

  • 7种传播行为:REQUIRED(默认)/ REQUIRES_NEW / NESTED 等。
  • 失效场景:private方法(非代理)、同类内部调用、本地数据库无事务、外部事务未覆盖。
  • 解决方案:编码式事务(TransactionTemplate)、AOP切面捕获异常。

回答示例
Spring事务传播行为(7种)

传播行为 说明
REQUIRED(默认) 有事务则加入,无则新建
REQUIRES_NEW 总是新建事务,挂起外部事务
NESTED 有事务则在嵌套点创建Savepoint,无则新建
SUPPORTS 有则加入,无则不以事务运行
NOT_SUPPORTED 以非事务运行,挂起外部事务
MANDATORY 必须在事务中运行,否则抛异常
NEVER 必须在非事务中运行,否则抛异常

@Transactional失效的常见场景

  1. private方法:Spring AOP基于代理(Proxy),代理只能拦截public方法,private方法不受事务控制;
  2. 同类内部调用:在ServiceA的methodA()中直接调用this.methodB(),不走代理,走的是目标对象的直接调用,@Transactional不生效;
  3. 异常被catch吞掉:如果业务方法内部catch了异常但没有重新抛出,Spring事务管理器感知不到异常,不会回滚;
  4. 异常类型不匹配:默认只对RuntimeExceptionError回滚,Checked Exception不会触发回滚(除非rollbackFor=Exception.class);
  5. 事务传播行为不当PROPAGATION_REQUIRES_NEW会挂起外部事务,如果外部需要看到内部事务的提交结果就会出问题。

10. HR面:你对京东的"客户为先"价值观有什么理解?

回答思路
京东文化题,结合自己的实际经历来回答,展示真诚的思考而非背诵。

  • 对"客户为先"的理解:不是"服务客户",而是"以客户视角做决策"。
  • 结合经历:举一个你主动以用户视角改进工作的例子。
  • 表达期待:说明你在京东能如何实践这个价值观。

回答示例
我对"客户为先"的理解是:不是口号,而是每次做决策时的第一性问题。

在我做项目时,有一次我完成了商品详情页的改版,从技术角度看代码质量很高,页面加载速度也优化了40%,我很满意。但上线前让用户测试时,发现新的页面布局把用户最关心的"价格"和"评价"藏到了页面下方,需要滚动才能看到——用户在旧版上是直接能看到这些信息的。

这件事让我意识到,技术做得好,不等于用户用得好。从那之后,我在每个功能开发前,都会问自己:"如果我是用户,我会不会用?会不会觉得麻烦?"这个习惯后来帮我避免了好几次"技术自我感动"的设计。

京东"客户为先"对我来说,就是这种思维——在每一个细节上,都站在用户的角度去判断什么更重要,而不是以开发者的便利为优先。

常见问题 FAQ

京东技术产品2026届校园招聘面经主要适合谁参考?

这篇面经适合准备京东技术产品2026届校园招聘面试的同学参考,尤其适合用来了解面试流程、常见问题、岗位考察重点和复盘方向。

京东技术产品面试通常会重点考察哪些能力?

通常会结合岗位要求考察专业基础、项目经历、业务理解、沟通表达和解决问题能力。建议结合面经中的题目,把自己的经历整理成可追问的案例。

如何使用这篇京东技术产品面经准备面试?

可以先通读正文了解流程,再整理高频问题和回答思路,最后把答案替换成自己的项目、实习或校园经历,形成更真实的表达。

面经中的回答思路可以直接背诵吗?

不建议直接背诵。回答思路更适合用来理解考察点,真正面试时应围绕自己的经历、岗位要求和现场追问灵活组织答案。