面灵AI→

58 同城 C++ 一面:突增流量、短链、大文件与推送系统设计

轮次
一面
时间
2026-10
来源
牛客网

《面试题目》

  1. 你的系统怎么应对突增流量?
  2. 反爬虫你了解吗?常见手段和对抗?
  3. 高并发下计数器(如帖子的浏览量)怎么设计?
  4. 短链服务怎么设计?
  5. 图片和视频这类大文件怎么存取?
  6. 搜索的排序策略?相关性怎么工程化?
  7. 推荐系统召回路 C++ 能做什么?
  8. 消息推送(push)系统怎么设计?

《参考解析》

突增流量:先保命,再扩容,最后复盘。 监控先行(QPS、P95/P99、错误率、饱和度),没有监控就不知道何时该动手;入口层限流(令牌桶/漏桶,按用户、IP、接口分级),非核心功能降级(推荐、评论、历史记录),缓存挡读(热点 key 预热、本地缓存 + Redis),写路径用 MQ 削峰、异步化;服务无状态化才能水平扩,扩容要提前备机器、验证镜像和依赖。事后再看瓶颈在哪:是带宽、连接数、数据库还是下游,把临时预案固化成可演练的开关,而不是每次靠人肉。

反爬虫是成本博弈,不是追求 100% 拦截。 识别手段:IP/UA/Referer 频控、设备指纹、行为特征(请求间隔、鼠标轨迹、页面停留)、账号关联图谱、验证码/无感验证。对抗会升级到代理池、真实浏览器内核、分布式低速抓取,所以防守要分层:静态资源加签名与过期时间、接口做鉴权和业务校验、关键数据做脱敏与限频、异常行为进人机验证。误伤真实用户是最大代价,策略要能灰度、能回滚、能按业务线配置。

计数器:分片 + 批量 + 近似展示。 单 key 自增会被热点打爆,做法是计数 key 加随机后缀分成 N 片,读时聚合;写走本地内存累加,按秒/分钟批量刷 Redis,再异步落库;对实时性要求低的展示数可以近似(用户看不出个位数差异),但计费、库存这类必须准。要注意刷写失败的重试与对账,以及进程重启时本地计数丢失的补偿。

短链:发号 + base62 + 缓存 + 302。 长链入库拿自增 ID(或号段/雪花),转 62 进制得到短码,冲突可用唯一索引兜底;读路径先查缓存,未命中回源,跳转用 302 便于统计(要 CDN 缓存就用 301)。防遍历可以加随机位或签名,防滥用要做域名黑名单、有效期和访问频控。存储只需 短码 → 长链,外加创建者、过期时间、点击统计。

大文件:对象存储 + CDN + 分片直传。 客户端向服务端要临时凭证,直传 OSS/S3,服务端只存元数据(路径、大小、类型、哈希);大文件分片上传 + 断点续传,合并时校验分片完整性;播放/展示走 CDN,图片按需生成缩略图并缓存,视频转码异步做。安全上要限类型、限大小、扫描恶意内容,私有文件用带签名的临时 URL。

搜索排序:多阶段 + 可评估。 召回(倒排、向量、规则)→ 粗排(轻量模型)→ 精排(CTR/CVR 模型)→ 重排(多样性、业务规则、去重)。相关性工程化靠 query 理解(分词、同义、纠错、意图)、字段权重、BM25/向量融合,以及离线评测集(NDCG、MRR)和在线 A/B(点击率、转化率)。badcase 要能归因到某一层,否则调权重只是碰运气。

推荐召回路里 C++ 的价值是「低延迟的批量计算」。 多路召回合并、去重、截断、向量检索(HNSW/IVF)、特征拼接与批量打分,都是计算密集且对 P99 敏感的部分;C++ 适合做这些基础组件和高性能服务,但模型训练、特征生产、策略编排通常在 Python/Java 侧。边界要划清:别把所有业务逻辑塞进 C++,可维护性和迭代速度同样重要。

推送系统:人群圈选 → 通道分发 → 送达回执。 运营配置任务,离线/实时画像圈人,按设备与通道(厂商 push、APNs、短信、站内信)分发;做频控、免打扰、去重和优先级,失败重试与降级;全链路记录发送、送达、点击,做效果归因。量大时用消息队列解耦,通道侧做限流和熔断,避免一个通道挂了拖垮全部。