引言在软件开发的快速发展领域中,人工智能已成为一股变革力量,重塑了开发者编写、审查和维护代码的方式。Cursor 作为一款 AI 驱动的代码编辑器,因其理解代码库、提供复杂代码结构建议并显著提高开发者生产力的能力而备受关注。在 Cursor 看似神奇的功能背后,是一套精心设计的基础设施,能够可靠地大规模运行。Cursor 的 CTO 兼联合创始人Sualeh Asif 在斯坦福 CS153 大规模基础设施课程中深入探讨了这一主题。下文是对其内容的总结,尤其值得关注的是 Sualeh 分享了 Cursor 在数据库选型和使用上的经验教训。📺 https://www.youtube.com/watch?v=4jDQi9P9UIw
图片
Cursor 的规模现状Cursor 在过去一年中实现了百倍甚至更高的增长。在自定义模型方面,每天处理约 1 亿次模型调用,这个数字确实令人生畏。Cursor 已成为前沿模型流量的重要组成部分,并开始托管一些大型模型。在索引系统方面,每天处理约 10 亿文档,公司成立以来累计处理了数千亿文档。一些数据存储已经变得相当庞大,Cursor 现已成为一个具有规模的服务,这一路走来积累了许多宝贵经验。Cursor 的核心基础设施Cursor 目前有三个核心基础设施部分:首先是索引系统,其中最著名的是检索系统。Cursor 投入大量精力索引 GitHub 和其他资源,以便真正理解用户的代码库,这些代码库可能与 Instacart 或其他大型公司的规模相当。其次是模型部分,包括在每次按键时运行的自动补全模型。这意味着 Cursor 每秒处理约 20,000 次模型调用,通过一个由约 2,000 台 H100 或类似 GPU 组成的机群。这些基础设施分布在全球各地,包括美国东海岸、西海岸(弗吉尼亚州和凤凰城)、伦敦和东京等地。这样的全球分布确保了无论用户身在何处,都能获得相对快速的自动补全体验。第三个核心部分是流式基础设施,用于存储传入的数据并用于筛选和各种后台运行的任务。这不是实时查询的部分,而是用来每天改进 Cursor 体验的基础设施。索引系统的演变索引系统最初是 GitHub 上的一个项目,后来团队意识到如果要求用户点击多个按钮来索引他们的代码库,没有人会这么做。因此,他们决定让索引过程完全自动化,在用户打开编辑器时自动进行,无需询问任何问题,除非代码库规模特别庞大。索引系统的工作原理是在客户端和服务器上计算所谓的 Merkle Tree。每个文件都会被哈希处理,每个文件夹的哈希值是其子项哈希值的组合,直到根哈希值。这样,当用户重新打开电脑或从一年前的版本检出代码时,Cursor 可以确定哪些内容发生了变化。系统会比较客户端和服务器上的根哈希值,如果不同,则至少有一个文件夹发生了变化。然后,系统会逐层深入,找出具体哪些文件夹和文件发生了变化。这是一个服务器和客户端之间的来回通信过程,双方都知道文件状态的某些信息,并试图协调这些状态。数据库演进之路:YugaByte - PostgreSQL - S3在 Cursor 的快速增长过程中,数据库基础设施经历了一段引人深思的演变历程,这段经历提供了宝贵的技术选择教训。最初,作为数据库爱好者的 CTO Sualeh 选择了 YugaByte 作为索引系统的基础,因为它理论上可以无限扩展,类似于 Google 备受推崇的 Spanner 数据库。然而,现实很快给了团队一记重击:尽管投入了大量资金,他们始终无法让 YugaByte 稳定运行。这一经历教会了他们一个重要教训:在实际应用中,简单可靠往往胜过理论上的完美方案。转向 AWS 的 PostgreSQL RDS 后,系统立即展现出惊人的稳定性和性能,一切「如魔法般顺畅」。Sualeh 由此建议开发者们:选择大型云服务提供商的解决方案,他们知道自己在做什么,他们的工具经过充分验证。这一阶段的成功让团队得以专注于业务增长而非基础设施问题,系统平稳运行了约八个月。然而,随着数据量增长到 22TB(RDS 限制为 64TB),新的挑战浮出水面。问题根源在于 PostgreSQL 的更新机制:与 MySQL 直接修改记录不同,PostgreSQL 的更新实际上是"删除+添加"操作。对于 Cursor 这种以频繁更新为特点的工作负载(用户不断输入代码),这意味着系统产生了大量「墓碑」记录(被标记为删除但未物理移除的记录)。PostgreSQL 依靠名为 「vacuum」 的后台进程清理这些记录并回收空间,但在数据量达到临界点后,vacuum 进程无法跟上删除速度,导致系统崩溃 (编者注:指的是 PG 上臭名昭著的 xid transaction wraparound)。数据库开始表现得像一辆发动机故障的汽车,勉强启动后很快就再次熄火。在一次严重的服务中断期间,团队尝试了多种应急措施:删除外键以减轻数据库负担、尝试快速删除最大的表(占用 20TB)、手动清理事务等。甚至联系了 AWS 的 RDS 架构师,但得到的回应却是「你们麻烦大了」。转机出现在一位团队成员的创新尝试中。在危机中,CTO 要求他尝试将最大的表(存储代码块的表)迁移到对象存储(如 AWS S3)上。令人惊讶的是,这一方案比其他所有修复尝试都更快地解决了问题。这次经历启发了团队重新思考数据存储策略。Sualeh 指出了数据库世界的一个新趋势:在对象存储(如 S3、R2 或 Blob)之上构建数据库系统。对象存储已经被优化到极致,具有极高的可扩展性、相对较快的速度和无与伦比的可靠性—「世界上没有什么比对象存储更可靠的了」。数据库最困难的部分之一是存储层,它容易变得混乱且需要精心设计以避免数据损坏。而利用对象存储可以规避许多这样的复杂性。Sualeh 提到了这一趋势的成功案例,如被 Confluent 收购的 Warp Stream 公司,他们将 Kafka(一个著名但难以管理的流处理系统)迁移到了对象存储上。受此启发,Cursor 团队正在进行一个新项目,目标是将整个系统迁移到对象存储,完全消除中间的数据库层。正如 Sualeh 幽默但深刻地总结:"扩展数据库的最佳方式就是根本不使用数据库。"这段数据库演变之旅不仅展示了技术选择的重要性,也反映了在面对快速增长时如何灵活调整架构策略。从理论上完美的 YugaByte,到实用的 PostgreSQL,再到最终的对象存储解决方案,每一步都蕴含着宝贵的工程智慧。推理服务的挑战在推理服务方面,Cursor 面临着许多挑战。Sualeh 指出,推理服务在全球规模上运行时,即使是最大的提供商也仍在摸索前进。一个关键挑战是「冷启动问题」。想象一个每秒处理 10 万个请求的系统,如果所有节点都宕机,当你尝试重启时,最初启动的少数节点会被所有用户的请求压垮,导致这些节点在能够健康运行之前就被杀死。这形成了一个恶性循环,使系统难以恢复。为了应对这种情况,Cursor 实施了用户优先级系统,或者在极端情况下,同时限制所有用户的访问。其他公司如 WhatsApp 则使用前缀策略,优先恢复某些关键前缀,而不是尝试同时为所有用户提供服务。Sualeh 坦言,所有模型提供商历史上都有可靠性问题,这是基础设施规模化的固有挑战。拥有和扩展基础设施很大程度上是一种「高风险熵管理」——随着规模扩大,世界会不断引入新的攻击向量,系统必然会出现故障,关键在于如何应对这些事件。结语Cursor 的基础设施扩展之旅充满了挑战和学习。从最初的快速增长到处理每天数十亿文档和上亿次模型调用,团队不断调整和改进他们的系统架构。特别是在数据库方面,从 YugaByte 到 PostgreSQL RDS 再到对象存储的演变,展示了如何根据实际需求和挑战调整技术选择。正如 Sualeh 所强调的,在大规模基础设施中,系统必然会出现故障,关键在于如何应对这些事件并从中学习。Cursor 团队的经验为所有正在构建和扩展技术基础设施的团队提供了宝贵的见解和教训。


慷慨的麦片
1 声望0 粉丝