网易后端开发面经 · 2024 秋招

网易后端开发工程师 2024 秋招完整面经:3 轮技术面 + HR 面,算法题涵盖链表重排、岛屿数量、LRU Cache 设计,考察 Java 并发、MySQL 索引与 Redis 分布式锁。

网易后端开发面经 · 2024 秋招

岗位:后端开发工程师(网易云音乐社交社区)
背景:双非本科 + 985 硕士,Java 技术栈,2 段实习
结果:OC,年薪 35w+(Base + 年终 + 补贴)
时间线:8.20 投递 → 8.28 一面 → 9.8 三面 → 9.12 OC


网易面试风格

网易面试整体节奏比较温和,注重基础扎实和逻辑思维:

  • 算法难度中等:以 medium 为主,hard 题出现较少
  • 基础比重高:Java 并发、JVM、Spring、MySQL 是重点
  • 业务场景务实:偏向社交、音乐、游戏等网易核心业务场景
  • 面试官态度友好:更像技术交流,压力面较少

一面(8.28):基础 + 算法

面试官:网易云音乐评论服务组
时长:55 分钟

Java 基础(15 分钟)

  • “HashMap 的 put 过程详细说说。”

    • hash → 数组索引 → 链表/红黑树处理冲突 → 扩容(2 倍、rehash)
  • “ConcurrentHashMap 的线程安全是怎么实现的?”

    • JDK 1.7:分段锁(Segment)
    • JDK 1.8:CAS + synchronized(桶级别锁),扩容时多线程协助迁移
  • “volatile 和 synchronized 的区别?volatile 一定能保证可见性吗?”

    • volatile:可见性 + 禁止指令重排,不保证原子性
    • synchronized:可见性 + 原子性 + 有序性(Monitor 规则)
  • “线程池的核心参数有哪些?怎么配置?”

    • corePoolSize、maximumPoolSize、keepAliveTime、workQueue、handler
    • IO 密集型:core = CPU * 2;CPU 密集型:core = CPU + 1

算法题 1:Reorder List(LeetCode 143)

重排链表:L0→L1→…→Ln-1→Ln 变成 L0→Ln→L1→Ln-1→…

三步法:

def reorderList(head):
    if not head or not head.next:
        return

    # 1. 找到中点(快慢指针)
    slow, fast = head, head
    while fast.next and fast.next.next:
        slow = slow.next
        fast = fast.next.next

    # 2. 反转后半部分
    prev, curr = None, slow.next
    slow.next = None  # 断开
    while curr:
        next_temp = curr.next
        curr.next = prev
        prev = curr
        curr = next_temp

    # 3. 交替合并
    first, second = head, prev
    while second:
        tmp1, tmp2 = first.next, second.next
        first.next = second
        second.next = tmp1
        first, second = tmp1, tmp2

算法题 2:Number of Islands(LeetCode 200)

岛屿数量,经典 DFS/BFS。我选了 DFS 写,因为代码更短。

def numIslands(grid):
    if not grid:
        return 0
    rows, cols = len(grid), len(grid[0])
    count = 0

    def dfs(r, c):
        if r < 0 or r >= rows or c < 0 or c >= cols or grid[r][c] != '1':
            return
        grid[r][c] = '0'
        for dr, dc in [(-1, 0), (1, 0), (0, -1), (0, 1)]:
            dfs(r + dr, c + dc)

    for r in range(rows):
        for c in range(cols):
            if grid[r][c] == '1':
                count += 1
                dfs(r, c)
    return count

追问:“如果用 BFS 怎么写?” → 用队列代替递归,其他逻辑一样。


二面(9.1):项目 + 场景

interviewer:云音乐社区推荐组
时长:65 分钟

项目深挖(20 分钟)

我实习做的是基于 Redis 的实时排行榜系统:

  1. “排行榜用 Redis 的什么数据结构?”

    • Sorted Set(ZSet),score 作为排序依据
  2. “如果score 相同怎么排序?”

    • 默认按 member 字典序排;如果需要自定义,把 score 放大 10^6 倍,低 6 位存时间戳
  3. “用户量很大,单 ZSet 放不下怎么办?”

    • 按时间段分片(日榜/周榜/月榜),或按用户分段(前 1000 名一个 ZSet,其余一个)
  4. “如果排行榜数据丢了怎么恢复?”

    • RDB 定期快照 + AOF 增量日志;核心榜单有数据库异步备份

算法题:Design LRU Cache(LeetCode 146)

哈希表 + 双向链表的经典题目。

class Node:
    def __init__(self, key=0, val=0):
        self.key = key
        self.val = val
        self.prev = None
        self.next = None

class LRUCache:
    def __init__(self, capacity):
        self.capacity = capacity
        self.cache = {}  # key -> Node
        # 伪头部和伪尾部
        self.head = Node()
        self.tail = Node()
        self.head.next = self.tail
        self.tail.prev = self.head

    def _remove(self, node):
        node.prev.next = node.next
        node.next.prev = node.prev

    def _add_to_head(self, node):
        node.next = self.head.next
        node.prev = self.head
        self.head.next.prev = node
        self.head.next = node

    def _move_to_head(self, node):
        self._remove(node)
        self._add_to_head(node)

    def _pop_tail(self):
        node = self.tail.prev
        self._remove(node)
        return node

    def get(self, key):
        if key in self.cache:
            self._move_to_head(self.cache[key])
            return self.cache[key].val
        return -1

    def put(self, key, value):
        if key in self.cache:
            self.cache[key].val = value
            self._move_to_head(self.cache[key])
        else:
            if len(self.cache) >= self.capacity:
                tail = self._pop_tail()
                del self.cache[tail.key]
            node = Node(key, value)
            self.cache[key] = node
            self._add_to_head(node)

追问:

  • “获取 API 时间复杂度?put 呢?” → 都是 O(1)
  • “如果要支持缓存过期呢?” → 每个 node 加 expire_time,定时清理或在 get 时检查
  • “Redis 的 LRU 怎么实现的?” → 近似 LRU,随机采样淘汰最久未访问的

MySQL 索引(15 分钟)

  • “InnoDB 的聚簇索引和非聚簇索引有什么区别?”

    • 聚簇索引:数据行存在叶子节点(主键索引)
    • 非聚簇索引:叶子节点存主键值,需要回表查数据
  • “联合索引 (a, b, c) 的命中场景?”

    • 最左前缀:a、ab、abc 能命中;bc、c 不能
  • “有一个查询 WHERE a > 1 AND b = 2,索引怎么建?”

    • (b, a):先精确匹配 b,再范围查 a,能走索引
    • (a, b):a 范围查询后,b 的索引失效

三面(9.5):架构 + 综合

面试官:云音乐社区架构组
时长:60 分钟

场景设计:评论系统

要求设计网易云音乐歌曲评论系统:

我的方案:

用户评论 ──▶ API Gateway ──▶ 评论服务
                          │
                          ├──▶ Redis:热门评论缓存(ZSet 按热度排序)
                          ├──▶ MySQL:评论内容 + 评论关系(主从)
                          └──▶ ES:评论搜索(全文检索)
                          │
                          └──▶ Kafka:评论事件流(审核、通知)
  • 热评算法:点赞数 × 0.7 + 回复数 × 0.2 + 时间衰减 × 0.1
  • 分页策略:按热度排序用 ZSet,按时间排序用时间戳游标
  • 敏感词过滤:Trie 树前缀匹配 + 命中即拦截
  • 防刷:同一用户 1 分钟内最多 3 条,验证码触发

追问:

  • “如果周杰伦发新歌,评论瞬间 100 万条怎么办?” → 写操作异步化(先写消息队列,消费者批量入库);读走 CDN + Redis 缓存
  • “评论的点赞数怎么保证高并发下的正确性?” → Redis INCR 原子计数 + 定时刷盘到 MySQL

手撕代码:合并 K 个有序链表

LeetCode 23,经典题目。写了归并分治版本:

def mergeKLists(lists):
    if not lists:
        return None

    def mergeTwo(l1, l2):
        dummy = ListNode(0)
        curr = dummy
        while l1 and l2:
            if l1.val < l2.val:
                curr.next = l1
                l1 = l1.next
            else:
                curr.next = l2
                l2 = l2.next
            curr = curr.next
        curr.next = l1 or l2
        return dummy.next

    # 分治合并
    def mergeRange(lists, left, right):
        if left == right:
            return lists[left]
        mid = (left + right) // 2
        l1 = mergeRange(lists, left, mid)
        l2 = mergeRange(lists, mid + 1, right)
        return mergeTwo(l1, l2)

    return mergeRange(lists, 0, len(lists) - 1)

复杂度:时间复杂度 (O(N \log k)),空间复杂度 (O(1))(迭代版)或 (O(\log k))(递归版栈空间)。


四面(9.8):HR 面

时长:20 分钟

  • 自我介绍和项目经历
  • 为什么想来网易?对云音乐有什么了解?
  • 薪资期望,其他 offer 情况
  • 反问:团队技术栈、新人培养

复盘与建议

网易后端面试通关密码

维度权重准备要点
基础35%Java 并发(ConcurrentHashMap、线程池)、JVM、Spring
算法30%LeetCode Hot 100 medium,链表/树/哈希表高频
项目20%能讲清楚技术选型、复杂度、扩展方案
场景15%社交场景(评论、点赞、关注)、排行榜、消息系统

高频考点

  1. 链表操作:反转、合并、重排、环检测(网易特别喜欢链表)
  2. Java 并发:volatile、synchronized、CAS、AQS、线程池
  3. MySQL 索引:聚簇/非聚簇、最左前缀、覆盖索引、回表
  4. Redis:ZSet 应用场景、持久化、过期策略、缓存一致性
  5. 场景设计:评论系统、点赞系统、用户关系(关注/粉丝)

网易 vs 其他公司对比

公司算法难度基础深度面试氛围
网易⭐⭐⭐⭐⭐⭐⭐友好
字节⭐⭐⭐⭐⭐⭐⭐⭐紧凑
阿里⭐⭐⭐⭐⭐⭐⭐⭐⭐深度追问
美团⭐⭐⭐⭐⭐⭐⭐务实

网易面试整体难度适中,基础扎实、项目能讲清楚的同学通过率较高。建议重点准备 Java 基础和链表/树类算法题。

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页