从立项到上线三个月:面试鸭在线刷题工具的产品与技术复盘
面试鸭从立项到正式上线前后花了三个月。这三个月里我几乎每天都在和题目、代码、反馈打交道中间踩了不少坑也把一些一开始没想清楚的问题慢慢理明白了。做这款在线面试刷题工具的初衷其实很朴素每到招聘季技术群里总能看到大量程序员在多个平台之间来回切换——在力扣刷算法、在牛客翻面经、在小程序里背八股、在博客翻源码解析准备一次面试至少要开五个网站。信息太碎效率太低。我就想做一个把面试准备真正串起来的工具让准备面试的人只打开一个页面就够了。面试鸭就是带着这个目的上线的。这篇文章不做什么产品宣讲纯粹从产品思路、题库体系设计、技术实现和运营踩坑几个维度做个复盘。如果你也在做工具型产品或者正在准备面试这应该能给你一些参考。1. 立项思考程序员刷题这件事到底差一个什么工具1.1 刷题之痛不是题不够而是场景太碎先聊几个实际场景。校招同学准备秋招通常要做这几件事算法题要去力扣刷这是基本功计算机网络、操作系统这些基础题要去牛客或者别人整理的PDF背Java或前端框架的原理要去掘金、CSDN找文章最近的大厂面试题要去小红书、公众号里搜项目讲解思路又要单独准备。每样都是还行但组合起来就是一团乱麻。我见过有人把PDF题手动做成刷题软件也见过有人专门买纸质题库逐页扫描。这些做法本身很聪明但它恰好说明一个事实市面上的工具没有解决好系统化准备面试这件事。PDF和刷题软件的差别在于交互不在内容。你照样不知道该先刷哪些题、哪些是高频考点、自己的薄弱点到底在哪。另一个痛点是无重点刷题。不少人打开力扣从第1题开始往下一题一题做做到第800题就坚持不下去了。这种刷法看起来很努力实际上前100题里超过一半都不太可能在面试中出现。力扣的题是给算法训练用的不是给面试准备的两者有关联但不完全是一回事。准备面试最需要的不是无限多的题目而是一条清晰的路径先掌握哪些知识点每个知识点做哪些代表性题目达到什么程度算过关然后进入下一个阶段。而市面上的刷题工具很少有把这件事讲明白的。1.2 产品定位从刷题工具升级为面试陪练面试鸭这个产品名取的是面试压的谐音意思有两层一是帮你压中面试题二是帮你压过面试。名字听起来轻松一点程序员之间聊天氛围也比较随意太正经的名字反而没有传播感。定位上面试鸭不是另一个力扣做得是面试全流程的陪练。力扣解决的核心问题是你会不会写这段代码而面试鸭要解决的问题是你能不能通过这场面试。这两个目标的高度不一样。能不能通过面试除了算法能力还涉及基础知识的准确度、表达的逻辑性、面对追问时的临场反应。我们的目标用户主要有三类。第一类是校招应届生他们最大的困惑是怎么在有限时间内覆盖尽量多的考点第二类是准备跳槽的社招程序员他们需要的是按岗位方向定制的面试题而不是泛泛的算法题第三类是转码人群他们大多自学了编程基础但对整个知识体系没有完整概念需要有一条清晰的学习和刷题路径。从这三类人群出发面试鸭在功能上做了三个取舍一是明确按岗位方向分题库后端、前端、算法岗各看各的内容二是在题目之外加入回答思路和考察点模块引导用户理解题目背后的真实意图三是增加了模拟面试模式尽可能还原面试现场的提问节奏。2. 题库体系把力扣刷题攻略变成真正可落地的路线2.1 题库不是越大越好内容产品冷启动最大的坑就是想着我先把题库做到一万题再上线。事实证明题库数量根本不是核心竞争力用户要的是质量和路径不是数量。力扣现在已经有三千多道题但大多数人真正认真做完的不会超过两百道热门经典题其实就那几百道。很多人收藏了一堆力扣刷题攻略leetcode刷题指南但真正能按攻略执行下来的人少之又少原因不是攻略写得不对而是攻略和题库之间没有打通——你在攻略里看到建议刷数组专题还得回到题库里去手动找对应的题单。面试鸭的做法是直接砍掉低频知识只保留高频考点。题库按知识点树组织每个知识点下只收录最经典、面试中出现频率最高的题目。算法部分我们把力扣里出现频率最高的 hot 100 和剑指 Offer 经典题做了重组不是照搬原题而是参考同样的考点用同类型题目或者改编题来承载。这样既规避了直接搬运的版权问题也让用户练的题目和面试场景更贴合。除了算法题和岗位基础题我们还保留了一些细分场景的题库方向比如针对软考初级程序员的公共基础题或者网络设备方向的数通刷题需求。这些需求量不大但用户群非常精准。做这类细分子题库的初衷是看到了专业领域刷题工具的参考价值比如 hdlbits 这种专门做数字电路刷题的网站用户量不大但评价极高。它验证了一件事在一个足够垂直的领域里把题库做到够用、准确、有讲解比大而全的题库更有生命力。2.2 从力扣刷题顺序中提炼的知识点树面试准备最需要的是顺序感。刷题顺序不对会极大打击信心。我见过不少人一上来就啃动态规划被难题劝退之后放弃了整个准备计划。正确的路径绝对不应该是从题目编号第1题开始而应该按照知识点本身的依赖关系来推进。面试鸭在冷启动阶段就内置了一份标准刷题顺序这个顺序参考了主流力扣刷题顺序攻略也参考了各个大厂实际面试中出现知识点的频率第一梯队数组、链表、栈、队列、哈希表。这五个知识点是面试中最基础也是最高频的双指针、滑动窗口等技巧也都建立在这上面。第二梯队二叉树、堆、排序、二分查找。树结构是面试常客大多数中等题都跟二叉树有关。第三梯队回溯、贪婪、动态规划、图。这些属于进阶内容通常出现在二面或三面。每个知识点下我们会明确标注必刷题单和扩展题单。必刷题单控制在十道左右都是这个知识点里最典型、面试最高频的题扩展题单留给学有余力的人。用户完成了必刷题单系统才会解锁下一个知识点的推荐。这样做的好处是用户不需要自己去研究刷题攻略产品已经把路线踏好了。这套设计的核心思想是少而精。每周认真消化十道高质量题目弄懂每道题的考察点、解题思路、可能出现的追问远比每天刷五十道题但转头就忘更有效。很多人刷题数量不少面试一追问就露馅原因就是看过答案和真正理解之间差了十万八千里。2.3 面试真题与场景模拟题的建设算法之外面试里更让人头疼的是八股文和场景题。所谓八股并不是贬义词它就是岗位基础知识。Java后端要会聊JVM内存模型、并发编程、Spring的Bean生命周期、MySQL索引结构和Redis缓存策略前端要会聊事件循环、闭包、虚拟DOM、组件通信。这些知识点都有标准答案但面试官在简历上随便挑一个点就能问出三层是什么、为什么、有什么坑。面试鸭对这类题目的处理方式是每道题提供考察点解析和回答框架而不是直接甩一个标准答案。比如讲一下MySQL的索引失效场景回答框架会让你先答索引失效的几种典型场景再补充底层原因基于最左前缀匹配、基于回表的成本分析最后结合实际业务给一个优化的例子。这样用户不是背答案而是在学一套组织表达的方式。场景题更考验经验。比如你的服务突然变慢了怎么排查这种题没有标准答案但回答的广度、顺序、深度能直接反映出候选人有没有做过线上问题处理。面试鸭把这类场景题和具体的知识点绑定比如排查类问题绑定Linux命令、JVM调优、数据库慢查询优化几个知识点用户做完题会收到一份能力雷达图能直观看出自己在哪个环节最薄弱。做这些内容最大的感受是题目本身只是骨架讲解和引导才是血肉。用户需要的不是一个答案而是怎么想到这个答案的完整链路。3. 核心功能与实现细节让刷题真正有效3.1 记忆曲线与错题回流机制第一次做刷题类产品的人容易忽略复习这个环节。刷题只完成了一半另一半是巩固。产品里如果只有做题和看解析用户大概率是刷了就忘过两周又回来从第一题开始。面试鸭内置了一套轻量级的复习机制参考艾宾浩斯遗忘曲线但做了简化没有搞得很玄乎。具体逻辑是用户每做错一道题系统会把这个题目自动加入错题本并按照第1天、第3天、第7天、第15天四个时间点生成复习任务。每完成一次复习用户可以标记已掌握或者仍不熟不熟的题会延长到第30天再次出现。这个功能落地的时候一开始想得很复杂要给每道题建立用户状态要用定时任务扫描数据库还要计算复习计划。后来想开了其实就是一个任务表加一个定时查询。用户相关的状态存在 MySQL 里当天需要复习的用户 ID 列表用 Redis 存一个集合定时任务每小时扫一次向有复习任务的用户推送站内信和邮件通知。这里有一个非常关键的设计复习题的排序不能是简单的 FIFO要让用户感觉越来越会。我们的策略是优先出那些曾经做错、最近复习过、再次做对率达到 80% 以上的题目让用户每次打开复习列表都有一种我都学会了的正反馈而不是连续看到一堆完全不会的题导致直接关掉页面。下面是复习任务的数据结构设计简单但够用CREATE TABLE review_task ( id BIGINT PRIMARY KEY AUTO_INCREMENT, user_id BIGINT NOT NULL, question_id BIGINT NOT NULL, task_due_date DATE NOT NULL, review_times INT DEFAULT 0, last_review_result TINYINT DEFAULT 0, status TINYINT DEFAULT 0, KEY idx_user_due (user_id, task_due_date) ) ENGINEInnoDB;3.2 模拟面试模式怎么设计很多刷题工具都有模拟考试功能但做得好的不多。原因在于考试和面试是两种完全不同的场景。笔试要求的是在规定时间内把代码写出来面试考查的是思考过程、表达和应对追问。面试鸭的模拟面试分三种模式。基础模式是限时答题适合算法练习岗位定制模式是按照用户选择的岗位方向随机抽题题目混合了算法、基础和场景题自由组卷模式适合已经有明确目标公司的用户比如选了字节和阿里系统会按这两个公司历年面试的知识点分布权重来出题。模拟面试的核心功能有两个录音和自评。做题过程中用户可以用录音功能录下自己的口述答案结束后回放。这个功能看着简单实际效果出奇地好。大多数人第一次听自己的面试回答录音都会惊到——原来自己的表达这么混乱、停顿这么多、废话词那么密集。这是任何文字解析都给不了的反馈。自评环节我们做了四个等级选项完全不会、不太会、基本掌握、非常熟练。不少用户会在这四个选项里纠结觉得自己基本掌握了但其实只是勉强做对。所以我们在提交自评后会弹出一个思考提示让用户尝试在 60 秒内不看解析用自己的话把这道题的思路讲出来。能讲清楚才算真的会。3.3 技术选型与架构取舍技术选型没有太多花哨的地方核心原则是团队熟悉、生态成熟、扛得住初期流量。前端选了 Vue3 加 TypeScript构建工具用 Vite。选择 Vue 而不是 React很大程度上是因为团队几个人对 Vue 更熟而且中文社区资料极其丰富遇到问题基本都能搜到答案。现在很多从黑马程序员这类机构出来的前端同学学的就是 Vue3 的整套体系后续社区合作也方便。前端项目的整体结构参考了目前主流的 Vue3 基础到实战的项目组织方式request 封装、路由守卫、Pinia 状态管理、组合式 API 拆分请求逻辑。后端用的是 Java Spring Boot。没有选 Go 或者 Node也是同样的原因——团队主力语言是 JavaSpring 生态成熟后面要加功能、招人、扩展都方便。数据存储方面题目、用户、做题记录这些核心数据放 MySQL 里表结构按业务拆得比较散用多张表组织而不是单表大字段。热题数据、排行榜、打卡状态放 Redis这一块一定要放缓存因为刷题列表的访问频率极高直接打 MySQL 会被打穿。搜索功能前期用 MySQL 的全文索引等题库量上来之后再考虑上 Elasticsearch 做更复杂的搜索和标签过滤。部署用 Docker Compose 加 Nginx一台 4 核 8G 的云服务器就够了。上线初期根本不需要上 K8s那是给自己找事。上线前我们还做了两个细节优化。一个是打点日志用户每一次进入页面、点击题目、提交答案、标记复习都会产生一条日志。这一步前期觉得麻烦后期做留存分析和内容优化的时候帮了大忙。另一个是接口幂等用户在移动端网络不稳定时容易重复提交答案前端做了防抖后端做了基于请求 ID 的去重防止同一道题被记录两次做题结果。// 前端提交答案时的防抖处理 const answerSubmitLock ref(false); async function submitAnswer(questionId, answer) { if (answerSubmitLock.value) return; answerSubmitLock.value true; try { await api.submitAnswer({ questionId, answer }); await loadReviewTask(); } finally { setTimeout(() { answerSubmitLock.value false; }, 300); } }3.4 移动端适配和小程序规划上线第一周后台统计里有 40% 的访问来自手机浏览器这让我们意识到移动端体验比想象中更重要。程序员刷题场景大量发生在通勤地铁、午休间隙不是所有人都愿意坐电脑前刷题。移动端第一步没有做原生 App而是先做了响应式适配同时考虑后期做微信小程序。小程序对这类工具型产品很友好不需要下载、分享方便、还能通过服务号做复习提醒。技术方案上后续会尝试用 uni-app 或者 Taro 复用现有 Vue3 的代码基础不用完全重写。4. 冷启动与增长运营一个刷题产品如何让用户留下来4.1 内容共建发动有经验的人写题工具型产品最尴尬的是内容冷启动。没有用户就没有人贡献题解没有题解就没有用户来看。为了打破这个循环我们走了先线下后线上的路子。上线之前我找了技术社群里十几位在大厂工作的朋友每人认领一个专题负责写这个专题下的题目讲解和回答框架。报酬不高主要靠共建者这个身份认同来驱动大家愿意帮忙是因为自己跳槽时也被刷题折磨过想为后来的人做点实事。题目讲解有个硬性要求不能只给答案必须写出思考链路。比如一道二叉树的中序遍历题讲解中要说明为什么递归写法空间复杂度是 O(log n)、迭代写法怎么用显式栈模拟递归、morris 遍历怎么做到 O(1) 空间。用户看一道题相当于体验到三种层次的解法。上线之后我们开放了用户投稿入口每个人都可以提交题目解析或者面经。为了保证质量所有投稿走投稿-初筛-专业审核-上线四道流程。专业审核由共建者轮流负责保证每篇内容至少经过两个人的校验。4.2 与程序员内容生态的联动内容产品最有效的推广方式不是投广告而是和技术内容生态做联动。这个领域里有一批非常优秀的内容创作者比如做编程导航的程序员鱼皮他们对工具型产品的认知很深帮忙推荐的转化效果远远好过广告投放。我们在推广上做了三类事情。第一是和培训机构的知识体系结合比如不少后端同学都是沿着黑马程序员这条学习路线走过来的从 Java 基础入门到框架进阶。面试鸭试着把这些学习路线的知识点和题库做了映射学完一章就可以在平台上做配套练习相当于把刷题变成了课程的课后作业。第二是深入到程序员聚集的社群里做口碑。程序员接单群、外包交流群、技术交流群这些地方的共同特征是大家经常讨论面试行情、接单报价、职业规划。表面看接单和刷题没什么关系但仔细观察会发现接单群里最活跃的那批人恰恰是最在意自身技术积累的人。不少人开玩笑说刷题刷好了接单报价都能谈高一点。这话虽然不够严谨但把技术水平提上来之后再去面试或者接单底气确实会不一样。第三是内容种草。我们写了免费的《程序员面试高频 100 题》手册放在官网可以留邮箱领取。手册把面试中最高频的一百个考点整理成了目录每个考点只写要点不展开用户想深入看就得来平台。这个钩子看着简单实际引流效果最稳定。4.3 留存手段与产品迭代节奏工具型产品的生死线是留存刷题工具更是如此。用户可能因为一次面试准备下载下来面试结束后就再也不用。这种事想挡是挡不住的不如接受它然后把准备周期内的体验做到极致。留存手段我们做了四层。第一层是每日一题和连续打卡最基础的激励方式不复杂但有效。第二层是排行榜但不是总榜而是本周榜和知识点榜。总榜永远是前面几个大神新人看不到希望周榜给了每个人上榜机会。第三层是错题周报每周末把用户这周的刷题数据、薄弱知识点、需要复习的题目用邮件发过去。打开率意外地高很多人是在周报邮件里才第一次注意到自己的知识薄弱点。第四层是社区氛围每道题下面可以评论求助老用户会帮新用户答疑问答之间就会产生内容沉淀。产品迭代上我们的原则是每周一个小版本每两周一个大版本。第一个月重点做功能和题库补全第二个月开始根据用户反馈做体验优化比如把题目加载速度提上去、把解析区的排版调清晰第三个月才慢慢开始做运营向的功能比如打卡分享图、邀请奖励。这个节奏很重要千万别在早期堆运营功能产品和内容都还没稳搞再多活动也留不住人。5. 上线踩坑实录这些问题你也会遇到5.1 题目内容与版权风险这是刷题类产品最容易踩的坑而且是那种踩了就可能直接导致项目终止的坑。最早我们想省事直接抓取力扣的题面、牛客的面经、其他博客的解析。还好在正式上线之前团队里有人提了一句题面也是受版权保护的别乱抓我们才停下手。后来花了一周时间把所有直接抓取的题目全部换掉。方法是自己按照考点编写同类型题目或者使用开源协议明确的题库面经全部做脱敏处理去掉公司名、面试官姓名等可识别信息。这里建议大家一定要重视。做题库类产品题目内容来源必须合规。如果用别人的原题和题解哪怕只差一个转载注明出处也会出问题。正确做法是要么完全原创要么找到授权明确的开源题库要么只做考点归纳和思路整理不复制原文。5.2 推荐系统冷启动难题我们一开始就上了个性化推荐结果效果很惨。没有用户行为数据的时候推荐算法做出来的结果和随机排序差不多甚至更差因为算法会把一些冷门题推给新用户用户一看不会做直接流失。后来把推荐策略退回到冷启动模式新用户注册后先按标准知识点顺序推荐必刷题单收集到足够的做题数据大约 20 道题之后再根据对错情况调整推荐权重。同时我们给每道题打上了难度、知识点、面试热度、公司偏好几个标签推荐时优先推面试热度高、知识点匹配度高的题目。这个调整上线后新用户第二天的做题量提升了 30% 左右。这告诉我们一个朴素的道理在产品早期不要迷信算法老老实实把内容组织好比任何炫技的推荐模型都管用。5.3 技术层面的性能问题上线第一天就遇到了慢查询。用户集中访问题目列表页数据库 CPU 直接飙高。排查后发现是题目表缺少组合索引列表页筛选条件里岗位 知识点 难度三个字段没有走到索引。加了一个联合索引之后问题立刻缓解。第二个坑是打卡接口的并发问题。每天早高峰9点到10点和晚上22点到23点会有大量用户集中打卡。我们一开始是直接写 MySQL 计数表结果数据库连接池被占满。后来改成 Redis 先记打卡状态和计数再异步把明细刷到 MySQL。用户看到的是秒级响应数据库压力也降下来了。第三个是图片资源加载慢。题解里配的示意图比较多一开始直接放服务器本地访问量一大就拖慢页面。后来把图片全部搬到了对象存储用了 CDN 加速问题解决。这种问题属于不做不知道做了才后悔没早点做。5.4 上线初期常见的运营问题运营上我们很快发现用户自驱力远比想象中低。很多用户注册后第一天刷了十几道题第二天就忘记登录了。单纯的签到提醒不够我们做了更侵入的触达每天固定时间推送你有一道复习题待完成的通知标题会带上题目类型和知识点名称比如【今日复习】数组三数之和的思路你能复述吗。这种带具体内容的推送效果比快来打卡好得多因为用户点进来知道自己要干什么。另一个容易忽略的点是用户反馈渠道。产品刚上线时用户会在各个地方吐槽在技术群里说、在小红书发帖、在应用商店打分唯独不在产品里点反馈按钮。我们花了很大力气把应用商店评论、社区帖子里的反馈捞回来整理成需求池然后定期在更新公告里说明你提的需求这周已经上线了。当用户感觉自己的建议被采纳时传播意愿是非常强的。下面整理一下上线以来遇到的主要问题做成一个速查表后续做同类产品的朋友可以直接参考问题现象根因解决方案题目列表接口慢页面加载超 2 秒缺少联合索引岗位、知识点、难度加联合索引打卡接口崩溃早高峰超时直接写库连接池占满Redis 记录 异步落库图片加载慢题解图转圈本地存储对象存储 CDN新用户流失严重次日留存不足 20%推荐算法冷启动回归基础刷题顺序积累数据后再个性化用户反馈分散吐槽在外部平台缺少反馈入口站内反馈 外部舆情收集重复提交答案做题记录存了两条网络波动重复请求前端防抖 后端幂等5.5 对后续版本的想法面试鸭肯定不是做一个刷题网站就结束了。下一步计划有几个方向但都不会一次性全铺开会按优先级逐步推进。第一优先是微信小程序版。程序员刷题的时间碎片化严重小程序是最轻的载体也能配合服务号做复习提醒。目前移动端 H5 版已经适配得差不多了小程序只是在工程层面重写业务逻辑可以复用。第二是 AI 模拟面试官。这个功能需要接大模型能力让 AI 扮演面试官根据用户的回答进行追问。难点不是识别语音而是怎么设计追问逻辑让追问真的往深处挖而不是每次都问同样的套话。这一步需要比较多的语料打磨不会很快上线。第三是企业端合作。现在题库里的大厂面试题都是来自面经和公开资料缺少真正来自企业内部的一手题目。如果能和企业 HR 或技术团队合作做企业真题专区对企业和求职者都有价值。当然这个牵扯到授权和合规问题要谨慎推进。结尾一点实操体会做了三个月面试鸭最大的体会是工具本身只是壳真正难的是内容质量和用户信任。刷题这件事用户投入的是时间时间比钱更值钱。如果我们的题目不准确、讲解不清晰、推荐路径不合理用户试个两三次就会彻底离开而且会告诉身边所有人别来。所以我的建议是做任何工具型产品第一版宁可功能少一点也要把核心内容做扎实。把 100 道题的命中率和讲解质量提上去比堆 1000 道凑数题有用得多。第二是要建立反馈闭环每个版本都要告诉自己我改了什么改完之后要看数据变化而不是自嗨。第三是别怕用户用完就走刷题产品本身就带有阶段性属性用户来的时候让他觉得值比想方设法把他留在产品里更有意义。最后分享一个我们总结出来的刷题小技巧每周挑出十道题不多刷但每道题都要做到能不看解析、完整口述一遍解题思路并且把题目和答案里的为什么都讲清楚。坚持一个月你会发现面试时的表达能力和思维清晰度上升一个台阶。面试鸭后续也会沿着这个方向继续迭代做一个对程序员真正有用的在线面试刷题伙伴。