面灵AI→

小红书后端开发岗面经合集(二):分布式锁、Redis 主从切换与网络调优

轮次
多轮面试合集
时间
2026-09
来源
牛客网

《面试题目》

面经 02 · 小红书后端开发岗(2026-03-26)

  1. 手撕:删除链表倒数第 N 个节点,考虑边界情况(本轮无自我介绍)
  2. Redis 的 zset 查询 score 在 10-k 之间的数据的时间复杂度是多少?查询 score 等于 10 的时间复杂度是多少?
  3. MySQL 的索引、联合索引、最左匹配原则

面经 03 · 小红书后端开发岗(2026-03-23)

  1. 线程池核心参数
  2. 核心线程数怎么根据场景选择配置?
  3. 说下数据库的分库分表,什么情况下分?
  4. 算法题:动态规划或多线程打印,2 选 1

面经 04 · 小红书后端开发岗(2026-03-19)

  1. 项目里 MinIO 的使用
  2. defer 的写法:一般用 defer func(){}(),还是直接用 defer func()?
  3. 两个协程交叉输出字母和数字
  4. 长度为 2n 的合法括号串

面经 05 · 小红书后端开发岗(2026-03-18)

  1. 在美团主要是做哪一块的?可以展开讲讲
  2. 接入层的异步化改造为什么要做?之前的同步是有什么问题吗?
  3. 改成了监听 binlog,是怎么解决一致性问题的?
  4. 缓存迁移当时用的整体 SOP 大概是怎样的?
  5. 迁移过程中怎么保证新集群上的数据一定是最准确的?
  6. 告警系统的动态阈值是怎么设置的?阈值和 CAT 埋点怎么定?怎么判断应该设置多少,有什么模型或算法来判断吗?线上环境可能抖动,怎么降低误告警的概率?
  7. 场景:线上集群请求量一会跌零、一会又只有两三个请求,有些集群一直有流量、有些没有流量,这种正常跌零怎么把它剔除掉?
  8. 实习过程中对 MySQL 分库分表中间件有使用或者了解吗?
  9. 限流策略里面令牌桶大概是怎么设计的?
  10. 为什么用 AT 的分布式事务?分布式事务相对来说比较重,为什么一定要用,不能用别的手段规避分布式事务?
  11. AT 大概的实现逻辑
  12. undo_log 表多久清一次?
  13. 有学过其他语言吗?
  14. 算法:合并区间

面经 06 · 小红书后端开发岗(2026-03-11)

  1. instanceof 是干什么的?了解 Java 字符串压缩吗?
  2. 写个 HTTP 响应类
  3. 设计个接口,用于判断用户是否能评论,要求 1 小时内用户不能多次发相同评论,用户量几千万,用 Redis 什么数据结构?
  4. 设计个房间列表接口,QPS 几百

面经 07 · 小红书后端开发岗(2026-03-02)

  1. 实现最长严格递增子序列的长度(要求阐述思路、编写代码并说明时间复杂度)
  2. 用递归方式实现将二叉树左节点值放到右边并连接到根节点右节点(编写代码)
  3. TCP 和 UDP 最主要的区别是什么?
  4. TCP 的拥塞控制是为了解决什么问题?
  5. 操作系统中进程和线程的区别和联系是什么?
  6. 串行程序改并行,多进程相比于多线程有什么优势?
  7. 代码调用中,同步调用和异步调用分别指的是什么?
  8. 异步调用中,调用方怎么拿到执行结果?有哪些方式?
  9. 平时用得最多的 AI 编程工具是什么?
  10. 用 AI 辅助编程过程中,有哪些发挥 AI 编码能力的经验?
  11. 编写提示词时,有针对大模型幻觉做过哪些处理?
  12. 是否试用过 Open Cloud?使用的 Open Cloud 基于哪家大模型?主要用来做什么?是安装在自己电脑还是服务器上?
  13. 是否了解 Go、Python、前端相关技术?掌握程度如何?
  14. 自己开发的项目中遇到过哪些比较奇怪的问题?如何解决的?
  15. 如果发 offer,大概什么时候可以入职?
  16. 有什么想要向面试官提问的?

面经 08 · 小红书后端开发岗(2026-03-02)

  1. Redis 实现分布式锁的底层做法是什么?
  2. Redisson 对分布式锁的封装,除了命令和过期时间,还有哪些额外机制?
  3. 什么场景下需要在 Redis 中使用 Lua 脚本?
  4. Redis 执行 Lua 脚本会中途失败吗?失败后有什么处理措施?
  5. 你开发中 Redis 用的单节点还是主从?主从故障是怎么切换部署的?
  6. Redis 哨兵的选主流程是怎样的?
  7. Redis 主从切换期间,代码里怎么处理连接不上的情况?
  8. 若要设计优化 Redis 主从切换的代码,缓存场景与分布式锁场景分别怎么做?
  9. 你当前的 Redis 实现中,主节点故障连不上会有什么影响?
  10. 抛异常后上层调用会持续尝试获取锁吗?怎么避免下游影响上游?
  11. 程序无法判断 Redis 是短暂还是长时间故障时,怎么保证快速恢复且避免频繁重连?
  12. MySQL 中索引失效的场景有哪些?是不是只要用 like 语法索引就会失效?索引失效的根本原因是什么?
  13. 现场编写单向链表删除倒数第 N 个节点的代码(需先讲思路)
  14. 毕业时间、是否能处理学校事务、年后能否实习、预期实习时长?

面经 09 · 小红书后端开发岗(2026-02-22)

  1. 说说 HTTP 的发展历程,HTTP/2 和 HTTP/3 有什么区别?
  2. TCP 的滑动窗口机制是什么?它能变小或者向左移动吗?接收方处理不过来、窗口为 0 时怎么办?
  3. 如果网络波动很大,TCP 协议有什么问题?如何优化?
  4. TCP 第一次真正发送数据是在什么时候?
  5. TCP 连接建立过程
  6. 为什么第三次握手可以带数据?为什么前两次握手不能带数据?
  7. 通过 Cookie 机制验证客户端
  8. 如果你是微信的开发工程师,如何设计「检测当前网络」功能?

《参考解析》

面经 08 · Redis 分布式锁与主从切换

  1. 分布式锁的正确实现与失败处理:加锁用 SET key value NX PX ttl 一条命令搞定,value 必须是本机唯一标识(客户端 ID + 线程 ID),释放时先比对 value 再删,这两步要用 Lua 合成原子操作,否则可能删掉别人刚抢到的锁。Redisson 在命令之外补的是:可重入(Hash 记录重入次数)、看门狗续期(默认每 10 秒把 30 秒 TTL 续回来,只有不显式指定 leaseTime 时才生效)、阻塞等待与公平锁。Lua 会中途失败吗?会——脚本执行期间 Redis 不会插入其他命令,但可能因为脚本本身报错、超时或实例故障中断,所以「原子」指的是不被并发插队,不等于「一定成功」。处理措施是:脚本要写成幂等的、先做参数校验;客户端要能区分「脚本报错」(业务逻辑问题,别重试)和「连接断了」(状态未知,必须回查锁是否还在);失败后锁可能已被部分写入,所以业务侧必须幂等,并且要有兜底的过期时间。

  2. 主从切换期间应用侧怎么扛:哨兵选主流程要讲清:多个哨兵通过发布订阅发现节点、对被判定主观下线的 master 做多数派确认(客观下线)、由 leader 哨兵按优先级与复制偏移量挑出新主,其余从节点指向新主,最后通过发布订阅通知客户端新地址。切换期间应用侧会遇到连接失败和写入落到旧主(脑裂)两类问题。代码层的处理思路是:缓存场景可以降级——读失败回源数据库,写失败短暂忽略,靠 TTL 与后续回填恢复一致性;分布式锁场景必须保守——获取锁失败就直接拒绝业务(fail-closed),绝不能「连不上就当作拿到锁」,否则并发保护直接失效。抛异常后上层不要无限重试获取锁,要有超时与熔断,并在下游失败时快速返回而不是把请求堆积在上游。「无法判断 Redis 是短暂还是长时间故障」这个问题的标准思路是:客户端做带退避与抖动的重连(避免雪崩式同时重连)、用熔断器在半开状态少量试探、把健康检查与业务超时分开,同时把「缓存不可用」和「锁不可用」的降级策略分开配置。

面经 02 / 03 / 05 · 存储、并发与分布式事务

  1. 索引与线程池的细节点:联合索引的最左匹配是回答一切索引题的地基,要能主动补一句「前导列用了范围查询之后,后面的列无法继续用于定位,只能做索引条件下推过滤」。索引失效的常见原因归到一句根本话:优化器判断走索引的代价比全表扫描更高——包括索引列被函数或表达式包裹、字段与参数类型不一致引发隐式转换、违反最左前缀、以 % 开头的 LIKE、OR 连接了没有索引的列、以及区分度太低(比如性别这种字段,优化器宁愿全扫)。所以「用了 like 就一定失效」是错的:只有前缀通配 %xxx 才用不上,xxx% 可以走范围扫描,覆盖索引下甚至能只扫索引避免回表。线程池的参数要能说出「核心线程数怎么按场景定」:CPU 密集型按核数上下取整并留出余量,IO 密集型按「核数 × (1 + 等待时间 / 计算时间)」估算,但真正的做法是先压测再定,并配合有界队列、明确的拒绝策略、可观测的活跃线程数与队列长度;线上更稳的是动态调整(配置中心下发,改 core/max/队列容量并让线程池生效)而不是写死在代码里。分库分表的判断依据是单表数据量与写入压力:单表超过几千万行或索引已经放不进内存、写入成为瓶颈时考虑分,垂直拆分先做(按业务域拆库),水平分片后要处理路由、全局唯一 ID、跨片查询与聚合、分布式事务这几个必然出现的问题。

  2. AT 模式与一致性保障:为什么用 AT 这类分布式事务?因为跨库跨服务的「本地事务 + 远程调用」无法靠单机事务覆盖,而有业务语义要求几步要么都成、要么都不成。AT 的实现逻辑是:代理数据源,执行业务 SQL 前后记录 undo_log(更新前的镜像)与全局锁,第一阶段各分支本地提交(这也是它与 2PC 的区别,不长时间占锁),第二阶段全局提交就异步删日志、全局回滚就按 undo_log 反向补偿。更该主动说的是它的边界:AT 只保证最终一致,期间数据可见;全局锁带来性能损耗;undo_log 需要定期清理(按已完成的全局事务时间归档删除,同时要防止清理掉还在等回滚的记录);对不支持的表结构与某些 SQL 有约束。规避分布式事务的手段优先级更高:能用一个库/一个服务解决的就不拆;跨服务的场景用本地消息表 + 定时补偿、事务消息(RocketMQ)、或状态机 + 对账把「强一致」换成「可收敛的最终一致」;确实需要强一致时再上 TCC 或 AT,并接受相应的复杂度与性能代价。

面经 06 · 接口设计题

  1. 两道设计题的答法:判断用户能否评论(1 小时内不能重复发相同评论、用户量几千万)用 Redis 的 string + TTL 最直接:key 设计成 comment:limit:{userId}:{contentHash},写入用 SET NX EX 3600,成功即允许、失败即拦下,一次操作完成「判重 + 计数 + 过期」,天然原子且内存可控;要防刷得更严就叠一层按用户的频率计数(INCR + EXPIRE 或用 zset 存时间戳、按滑动窗口清理),再做内容归一化(去空格、大小写、表情与标点的相似判定)避免改一个字就绕过;几千万用户不可能全量常驻内存,靠 TTL 自然淘汰即可,别用全量 set。房间列表接口(QPS 几百)的重点不在数据库而在缓存与分页:先明确排序字段与分页方式(游标分页优于 offset),用 Redis 的 zset 按热度或更新时间维护房间 ID 的有序集合,取一页只需一次范围查询,再用 pipeline 批量拿房间详情(或本地缓存 + Redis 两级);几百 QPS 对缓存来说压力很小,真正的坑是缓存与数据库的一致性、翻页时的数据抖动(新房间插入导致重复或遗漏,游标分页能缓解)、以及热点房间的缓存击穿(加互斥重建或逻辑过期)。答题时把「数据结构选择、key 设计、容量估算、失效与一致性、异常兜底」这条线走完,比给出一个方案就结束更完整。

面经 07 / 09 · 网络与编程基础

  1. TCP 滑动窗口、握手与网络优化:滑动窗口是接收方通过通告窗口做流量控制:窗口只能整体向右滑动(随 ACK 前进),不能左移——左移意味着要重新接收已确认的数据,会造成数据混乱与协议错误;窗口可以变小(接收方缓冲区被占用时),极端情况缩到 0,此时发送方必须停止发送,靠持续发送窗口探测报文等待窗口恢复,而不是盲目重传。TCP 第一次真正发送数据要区分阶段:三次握手的前两个报文不携带数据(第三个 ACK 可以携带),所以严格意义上的第一批应用数据通常随第三次握手的 ACK 一起发出。为什么前两次不能带:第一次若带数据,服务端在未确认客户端可达前就要为它分配资源,容易被伪造源 IP 的攻击者耗尽;第二次同理,且此时客户端尚未确认自己的序列号被正确接收。网络波动大时 TCP 的问题是丢包被当成拥塞信号——RTO 翻倍退避、拥塞窗口骤降,延迟抖动明显,而且 TCP 层的队头阻塞会让一个丢包卡住整条连接上的所有请求。优化方向分两层:协议层换 QUIC(基于 UDP、流级独立重传、无 TCP 队头阻塞)、KCP(牺牲带宽换延迟,适合弱网实时交互)、MPTCP(多路径并用);参数层调初始拥塞窗口、开启 TCP Fast Open、合理设置重传超时与应用层超时。

  2. 「检测当前网络」的功能设计(微信场景):把它拆成「可达性、质量、可用性」三问。可达性检测用对业务服务器(而不是第三方)的探测:应用层 HTTP 探测接口最贴近真实链路(能同时覆盖 DNS、TLS、网关),ping 只能证明 ICMP 通、很多网络会屏蔽 ICMP 所以不能单用,同时检查本地网络接口是否有地址、是否连着 WiFi 还是蜂窝。质量检测看延迟(多次探测取分位数而不是单次,避免被一次抖动带偏)、丢包率、带宽与首包时间,并区分「内网延迟」和「到服务器的延迟」来判断是本地网络问题还是服务端问题。可用性判断要给出分级结论而不是一个布尔值:直连是否可用、是否需要切换到备用域名或备用 IP、是否应该降级到弱网模式(降低图片质量、拉长超时、暂停后台同步)。工程上还要注意:探测要异步且低频、失败要退避,避免探测本身变成流量;结果要缓存并做成状态机(好 / 弱 / 断),状态切换需要连续多次采样确认,否则会在临界点来回抖动;上报的指标要能按运营商与地域聚合,方便定位区域性故障。