快手2面 10.13
- 轮次
- 二面
- 时间
- 2026-10
- 来源
- 牛客网
《面试题目》
- 请做一下自我介绍。
- 挑一个最难的点详细说一下。
- 如何优化数据拉取这个过程的延迟?
- 有在整个链路上做优化吗?
- 说一下 pi-agent 的架构,以及对应的模块设计。
- 上下文满了有哪些处理策略?
- 为什么使用 ClickHouse?和 MySQL 有什么区别?
- 说一下 ClickHouse 的底层实现逻辑。
- Redis 为什么快?
- Redis 有哪些数据类型?
- Redis 哨兵模式和集群模式在架构上有什么差异?怎么选择?
- 集群模式怎么通信?
- 说一下 Raft 算法的大概内容。
- AI Coding:讲解你的做题思路。
- 你有什么想问我的?
《参考解析》
讲性能优化之前,先把链路的每一跳和瓶颈定位方式说清楚:「如何优化数据拉取延迟」这类问题,面试官最怕听到直接报方案(加缓存、上批量)。稳妥的顺序是:先描述链路——客户端发起、网关、服务端组装查询、存储层扫描、网络回传、前端渲染,然后说明各段的耗时占比是怎么测出来的(链路追踪打点、分位值 P99 而不是均值、慢查询日志、抓包看 RTT)。定位到瓶颈后再给手段:存储层是索引与分区没吃到、扫描行数过多,就用谓词下推、覆盖索引、预聚合;服务端是 N+1 查询或串行调用,就批量合并、并发编排、结果裁剪;网络层是包太大或往返次数多,就压缩、分页、长连接;前端是渲染卡顿,就虚拟列表与增量更新。最后一定要补一句「优化前后各是多少」以及「有没有用压测验证」,只讲手段不讲收益的答案会被继续追着问。
ClickHouse 与 MySQL 的差别不是「快慢」,而是为不同访问模式设计的存储引擎:MySQL(InnoDB)是行存加 B+ 树,按主键组织数据,擅长大批量写入下的点查和事务(ACID、行锁、MVCC),所以它服务的是在线交易。ClickHouse 是列存,同一列的数据连续存放,做 count、sum、分组聚合时只需读涉及的列,加上向量化执行与多核并行,扫描吞吐能高出一两个数量级;它用 MergeTree 系列引擎,数据按分区和排序键落成一个个 part,后台异步合并,靠稀疏主键索引 + 跳数索引做数据跳过,几乎不做逐行查找。代价也很明确:不支持高频单行更新和删除(只能 ALTER ... UPDATE 这类异步 mutation)、不支持完整事务、并发点查性能差、join 能力弱且要小心内存,所以典型架构是「业务写 MySQL,明细与日志同步进 ClickHouse 做分析与报表」。被追问「为什么选它」时,把「写少读多、按列聚合、数据量大且能接受秒级延迟」这三个条件讲出来,就说明你是按场景选的。
Redis 快的原因要答出四层,哨兵与集群的差异要落在「谁负责分片」:Redis 快不是单点原因:纯内存访问没有磁盘 IO;单线程命令执行省掉了锁竞争与上下文切换;基于 epoll 的 IO 多路复用让一个线程管理大量连接;再加上 SDS、跳表、压缩列表/紧凑编码等为特定场景优化的数据结构,以及 RESP 协议的解析开销很小。数据类型的回答不要只背五个基础类型,要把常用的扩展一起带上:String(计数、缓存、分布式锁)、Hash(对象属性)、List(队列、时间线)、Set(去重、共同好友)、ZSet(排行榜、延时队列),再加 Bitmap、HyperLogLog、GEO、Stream 这些专用结构,并说清各自的典型命令与复杂度。哨兵模式解决的是高可用:一组哨兵监控主从、主挂了做故障转移并通知客户端,但数据仍在单个主节点上,容量和写吞吐受限于一台机器;集群模式解决的是水平扩展:数据按 16384 个槽分片到多个主节点,每个主节点带从节点,客户端按槽路由。通信上有两条线要分清:客户端与节点之间用 RESP,遇到不属于本节点的 key 会返回 MOVED(永久迁移)或 ASK(迁移中临时重定向);节点之间则走一条独立的二进制集群总线(默认端口 = 服务端口 + 10000),用 Gossip 协议交换节点状态、槽位归属和故障判定,故障转移需要主节点过半投票。选型就一句话:只要高可用、数据量单机放得下,用哨兵;要突破单机内存与写吞吐、能接受客户端路由和多 key 操作受限,用集群。
Raft 用一句话概括是「先选主,再由主复制日志,多数派确认即提交」:展开讲分三块。选主:节点处于 follower、candidate、leader 三种状态之一,每个节点维护随机的选举超时,超时后自增任期(term)转为 candidate 并拉票,拿到多数票即成为 leader,任期号用于拒绝过期请求,随机超时是为了避免选票被反复瓜分。日志复制:客户端请求由 leader 追加到本地日志,再通过 AppendEntries 并行复制到 follower,只要多数节点持久化成功,leader 就推进 commit index 并应用状态机,同时把已提交位置告知 follower。安全性靠两条约束保证:一是「选举限制」,candidate 的日志必须至少和多数节点一样新才能当选,避免已提交日志被覆盖;二是「提交规则」,leader 只能提交自己任期内的日志条目。工程上还要能提到成员变更(一次只改一个节点或用联合共识)、日志压缩(快照)和网络分区下的脑裂防护(多数派才可写)。和 Paxos 的关系可以一句带过:Raft 是把 Paxos 的可理解性问题解决后的工程化版本,强调强 leader 与顺序日志。
「上下文满了怎么办」是 Agent 岗的高频题,答成一份策略清单就够:常见手段按代价从低到高排:① 截断与滑窗——保留 system prompt 与最近 N 轮,按 token 预算裁,注意别把工具调用与结果切散;② 摘要压缩——把早期对话交给模型做结构化摘要(任务目标、已确认事实、未决问题、已完成动作),用摘要替换原文;③ 外部记忆——把关键事实写进向量库或 KV 存储,用时按需检索,而不是常驻上下文;④ 分层结构——主 Agent 只持有计划与状态,细节放到子 Agent 或工具里,用完即弃;⑤ 结构化状态——把任务进度写成可序列化的状态机,每轮只带当前节点所需信息。还要提工程细节:工具返回的大结果先裁剪再入上下文(截断 + 落盘给引用 ID)、设置 token 水位线提前触发压缩而不是等报错、压缩后校验关键约束没丢(比如用户指定的格式要求)。如果能补一句「我们怎么评测压缩前后任务成功率有没有掉」,这一题就答得比别人完整。
AI Coding 环节考的是过程可见,不是手速:遇到这类限时做题,先把四步做出来:读题后复述一遍题意并确认边界(输入规模、是否允许重复、返回什么),给出暴力解与复杂度,说明瓶颈在哪,再讲优化方向,最后落代码。写的时候先搭骨架(函数签名、数据读取、返回值),再填核心逻辑,边写边把关键变量含义说给面试官听;不要闷头敲十分钟。写完主动跑一两个手写用例验证边界(空输入、单元素、全相同)。如果卡住,明说「我现在的思路是 X,卡在 Y」,让对方给提示远比自己硬撑好。平时准备可以把常见题型(数组与双指针、二分答案、DP、图搜索、字符串)各留一份模板笔记,而不是临场回忆。