当前位置: 首页 > news >正文

我用 AI 模拟字节跳动三面,系统设计轮答到一半面试官沉默了

备选标题:

  • 让 AI 面 AI:字节三面实录,面试官追着 Feed 流方案问了 10 分钟
  • 模拟字节跳动三面,AI 求职者的 LRU Cache 写对了,但漏了一个致命细节

场景设定:字节跳动 · 后端资深工程师 · 抖音团队
参与角色:AI 面试官(Claude)vs AI 求职者(GPT-4o)
人类裁判:我(击歌吟)


🎬 第一面(基础算法)

面试官问:

实现一个 LRU Cache,支持 get(key) 和 put(key, value),要求 get 和 put 都是 O(1)。说说你的设计思路,为什么不用 FIFO 或 LFU?

求职者答:

选「哈希表 + 双向链表」。哈希表 O(1) 查节点,链表维护访问顺序。每次访问一个 key,节点移到链表头;淘汰时删链表尾。

classDLinkedNode:def__init__(self,key=0,val=0):self.key=key self.val=val self.prev=Noneself.next=NoneclassLRUCache:def__init__(self,capacity:int):self.capacity=capacity self.cache={}self.head=DLinkedNode()self.tail=DLinkedNode()self.head.next=self.tail self.tail.prev=self.headdefget(self,key:int)->int:ifkeynotinself.cache:return-1node=self.cache[key]self._move_to_head(node)returnnode.valdefput(self,key:int,value:int)->None:ifkeyinself.cache:node=self.cache[key]node.val=value self._move_to_head(node)else:node=DLinkedNode(key,value)self.cache[key]=node self._add_to_head(node)iflen(self.cache)>self.capacity:removed=self._remove_tail()delself.cache[removed.key]def_move_to_head(self,node):self._remove_node(node)self._add_to_head(node)def_add_to_head(self,node):node.prev=self.head node.next=self.head.nextself.head.next.prev=node self.head.next=nodedef_remove_node(self,node):node.prev.next=node.nextnode.next.prev=node.prevdef_remove_tail(self):node=self.tail.prev self._remove_node(node)returnnode

FIFO 完全不考虑访问频率,可能淘汰热点数据。LFU 按频率淘汰看似公平,但维护每个 key 的计数成本高,而且存在"缓存污染"——一个 key 短期高频访问后长期不用,占着位置不释放。LRU 是平衡方案,实现简单,对多数业务场景效果够好。

🧑‍⚖️ 我的点评

代码结构清晰,用了虚拟头尾节点简化边界——很多候选人会漏这个细节。LRU 跟 FIFO/LFU 的对比也没跑偏。

但需要补刀的地方:

  • 没提 OrderedDict。Python 3 的 OrderedDict 底层也是双向链表 + 哈希表,面试可能追问底层实现。
  • LRU 的缺陷没说:批量遍历场景下,一次读操作就把整个链表顺序打乱了,热点数据可能被错误淘汰。

评分:⭐⭐⭐⭐ 通过


🎬 第二面(进阶算法)

面试官问:

抖音每天海量视频被点赞。实时返回 Top K 热门视频,热度按 24 小时内点赞数计,每 5 分钟更新一次。算法和架构怎么设计?

求职者答:

两阶段走。数据聚合层用 Redis Sorted Set(key=视频,score=点赞数),Top K 计算层维护一个最小堆

importheapqfromdatetimeimportdatetime,timedeltaclassTopKTracker:def__init__(self,k:int,window_hours:int=24):self.k=k self.window=timedelta(hours=window_hours)self.heap=[]self.scores={}self.exists=set()defrecord_like(self,vid:str):self.scores[vid]=self.scores.get(vid,0)+1score=self.scores[vid]ifvidinself.exists:heapq.heapify(self.heap)else:heapq.heappush(self.heap,(score,vid))self.exists.add(vid)whilelen(self.heap)>self.k:_,v=heapq.heappop(self.heap)self.exists.discard(v)defget_top_k(self):returnsorted(self.heap,key=lambdax:-x[0])

生产上还可以用 Count-Min Sketch 做近似计数,内存开销比精确计数小两个数量级。

用户点赞事件

Kafka 缓冲

Flink 窗口聚合
(24h滑动窗口)

Redis Sorted Set

TopK Calculator
最小堆 + Time decay

推送到 CDN 缓存

🧑‍⚖️ 我的点评

分层的架构思路对的:消息队列 → 流计算 → 存储 → 计算 → 推送,是生产级方案。提到 Count-Min Sketch 加分。

但代码有两个问题:

  • heapq.heapify()是 O(n) 的!更新操作应该用heapq._siftdown或直接全量重建,面试中这可能被追问。
  • 没有时间衰减。24 小时点赞数如果不做衰减处理,凌晨峰值会长期霸榜。应该给更早的点赞降权。

评分:⭐⭐⭐ 通过(有瑕疵)


🎬 第三面(系统设计)

面试官问:

设计抖音关注页 Feed 流。用户打开 App → 看到关注的人发布的视频 → 按时间倒序。要求:

  1. 日活 3 亿,人均关注 200 人
  2. 发布后 10 秒内粉丝可见
  3. 高可用,不丢数据

画架构图,说明读写路径。

求职者答:

推拉结合方案。大 V(粉丝 > 10 万)用拉模式,普通用户用推模式。

粉丝Feed 服务Timeline Cache关系服务API创作者粉丝Feed 服务Timeline Cache关系服务API创作者发布视频查粉丝列表返回粉丝(区分大V/普通)推入普通粉丝Timeline记录大V最新视频刷新Feed读取个人Timeline合并大V最新视频返回合并后Feed

为什么这样设计:纯推模式下,大 V(假设 5000 万粉丝)发一条视频要写 5000 万个 Timeline,IO 爆炸。纯拉模式下,每次刷新要查 200 个关注对象的视频再 merge,延迟高。推拉结合分摊压力——大 V 只在粉丝刷新时计算,避免写放大。

存储选型:Timeline 用 Redis Sorted Set(video_id + timestamp),每个用户只存 200 条,多了就淘汰最早。关注关系用 MySQL + Redis 缓存。视频元数据用 CDN + MySQL。

🧑‍⚖️ 我的点评

推拉结合方案没选错。100 个面 Feed 系统的人里,70 个说纯推、20 个说纯拉、10 个能说推拉结合——你属于最后那批。大 V 阈值区分也合理。

但你漏了几个关键点,面试官大概率会换着角度追问:

  • 10 秒可见怎么保证?推模式的瓶颈在写扩散延迟——一个人关注了 200 个普通用户,Timeline Cache 可能只覆盖了其中 150 人的近期视频,剩下 50 人需要 fallback 逻辑现场拉取。
  • 冷启动问题。新用户刚注册关注 50 人,Timeline Cache 是空的,第一次刷新全是 miss——不预热你的数据库会被打穿。
  • 容量估算。3 亿用户 × 200 条缓存 = 600 亿条记录。需要多少台 Redis?单实例扛多少 QPS?这些数字面试官很在意。

评分:⭐⭐⭐⭐ 通过


📊 总结

轮次题目AI 表现结果
一面LRU Cache基础扎实,实现规范⭐⭐⭐⭐ 通过
二面Top K 实时排名架构合理,代码有 O(n) 隐患⭐⭐⭐ 通过
三面Feed 流系统设计推拉结合,架构完整⭐⭐⭐⭐ 通过

总体评价:三面全过。基础算法扎实,系统设计有全局视野。

比真人面试差在哪:AI 的答案"太干净"了——没有真实面试中的犹豫、追问、修修补补的过程。比如第二面的 heapify O(n) 问题,真人面试官追问一句,候选人可能直接懵掉。另外缺少了对规模的本能恐惧——600 亿个 KV 意味着什么,AI 只用一句话带过,但真实工程师会当场算机器成本。

比真人面试好在哪:覆盖面广,从数据结构的底层实现到高并发系统架构都能串起来。不会出现"这题我背过但换个说法就懵了"的情况。思维链完整:抛出方案 → 分析利弊 → 给出理由。


信息来源说明:

  • ✅ 已验证:LRU Cache 双向链表实现、推拉结合 Feed 架构
  • 💡 推断:大 V 阈值(10 万粉丝)为合理推测,实际字节内部阈值可能不同
http://www.jsqmd.com/news/950584/

相关文章:

  • 用AI写论文为何越用越累?复盘我的踩坑经验与正确用法
  • 【v 2.7.5 新版】爆火 Open Claw 完整部署教程(含安装包)
  • 用树莓派搭建Pi-Hole:打造无广告家庭网络的完整指南
  • 2026苏州全城免砸砖修瓷砖空鼓靠谱吗?本地实测真实效果 - 苏易修缮
  • 智能担保不是加AI,而是重定义风险契约——基于27家金融机构实测数据的5维评估模型
  • 从零打造模型火箭自动化发射台:机电一体化与嵌入式系统实战
  • 2026年 工业环保设备厂家推荐榜:重庆/福建/贵州除尘净化、一体化喷淋废气及固废处理节能公司深度解析 - 品牌企业推荐师(官方)
  • 2026年广州/东莞搬家服务TOP5榜单:精品搬家、厂房搬迁、日式搬家及设备搬运公司实力推荐 - 品牌企业推荐师(官方)
  • STM32F103驱动LD3320离线语音识别工程(Keil MDK可直接编译)
  • 2026年6月上海钻戒回收实地测评|靠谱回收渠道筛选、门店地址与报价 - 奢侈品回收评测
  • PHY与MAC接口
  • AI支付不是加个API!——金融级LLM推理引擎部署的4层安全沙箱设计(FIPS 140-3/等保2.0三级双认证实录)
  • PCB外层及高端制程收放板方案:效率与防护的分段配置
  • ESP32 PWM技术详解:从LED调光到电机控制的全方位实战指南
  • 3分钟解锁B站缓存视频:m4s-converter让你珍藏的视频永不丢失
  • 2026苏州姑苏/相城/高新瓷砖翘边起拱怎么办?本地老师傅对症解决 - 苏易修缮
  • GTC泽汇:“服务器订单持续升温中”
  • 惠州彩盒定制商家盘点:适配多行业需求的合规服务商 - 互联网科技品牌测评
  • 技术赋能:AKShare如何重构Python金融数据获取体验
  • 数组与字典解决方案第二十八讲 从两列数据中提取重复数据并排重处理
  • 2026 北京闲置钻石、钻戒变现指南,亲测这家体验超好 - 奢侈品回收测评
  • 从零开始电路设计:光控夜灯实战与创客电子入门
  • 烟台外墙保温水包砂技术全解析 本土品牌实测案例复盘 - 奔跑123
  • 【JPCS (ISSN:1742-6596)出版 | 汉口学院主办 | EI会议稳检索 | 优秀论文将推荐至期刊】2026年电气自动化、自主系统与智能制造国际学术会议 (EASIM 2026)
  • 从汽车悬架到手机防抖:阻尼振动微分方程在工程中的那些实用案例
  • MATLAB泰森多边形生成工具包:支持自定义边界裁剪与空间点位判定
  • 从Excel发福利到AI动态激励:一家上市企业用117天完成智能福利整合的完整技术迁移日志(含K8s部署失败回滚实录)
  • 2026 年 6 月证券刷题避坑指南:免费高效工具实测全解 - 讲清楚了
  • 2026 GEO 技术实战:从原理到落地,中小企业 AI 获客全栈指南
  • 服务器上百台,SSH逐台装监控到猴年马月?我用Ansible三分钟全部搞定