Sync Engines:数据同步引擎的未来
instant
instant
PricingExamplesEssaysDocs
Discord
GitHubLogin
Sign up
Sync Engines are the Future (数据同步引擎是未来趋势)
Nikita Prokopov Mar 17th, 2025
大家好!我是 Niki,也被称为 @nikitonsky。你可能因为 DataScript、The Web After Tomorrow 或者 Your frontend needs a database 而认识我。去年 12 月,我加入了 Instant,继续我在浏览器中引入数据库的旅程。 这是我的使命:
现代浏览器是一个操作系统。现代 Web 应用是一个分布式应用。因此,任何 Web 应用开发者都面临着一个众所周知、广为人知、且臭名昭著的难题:数据同步。
听着,我见多识广。 我见过潮流来来去去。 我已经看到数据同步在过去的二十年里被当作一个不存在的问题来对待。 你有 XHR。 你有 fetch。 你有 REST 和 GraphQL。 你还想要什么?
问题是,所有这些工具都是低级的。 它们解决了获取数据一次的问题。 但是获取数据是一个持续的过程:数据随着时间而变化并变得陈旧,请求失败,更新到达的时间晚于你可能想要的时间,或者顺序错误。 错误总会发生。 偶尔的 if (!response.ok)
并不能让你走得很远。
fetch(newRequest('/user/update',{method:'POST'})).then((response)=>{
if(!response.ok){
// Do what? Pretend it never happened?
// 怎么办?假装什么都没发生?
// Stop the entire application?
// 停止整个应用程序?
// Retry? What if user already issued another update that invalidates this one?
// 重试? 如果用户已经发布了另一个使该更新无效的更新怎么办?
// What if update actually got through?
// 如果更新实际上已经通过了呢?
}
});
而且你不能放弃并宣布一切都无效。 你必须继续工作。 你需要一个系统。你无法在单个请求的层面上解决这个问题。
在 同时开发产品 的情况下尝试解决数据同步问题也是不明智的。 这些问题需要耐心、彻底性和广泛的测试。 它们不能匆忙完成。 而且你已经有一个你不知道如何解决的问题:你的产品。 尝试同时解决这两个问题,结果两个都失败 [1]。
有趣的是,边缘情况在项目之间并没有那么独特。 每个人都希望他们的数据同步。 每个人都希望他们的数据正确并只交付一次。 每个人都希望它快速、紧凑且及时。 这是库的完美用例。
这样的库会被称为数据库。 但是我们习惯于将数据库视为与服务器相关的东西,一个在数据中心运行的大盒子。 不一定是这样! 数据库有两个部分:存储数据的地方和传递数据的地方。 第二部分通常缺失。
考虑一下:我们希望两台计算机进行通信并协调如何同步数据。 显然,两台计算机都需要运行一些代码,并且该代码需要兼容。 简而言之,我们希望在前端运行数据库。 仅仅通过一些简单的 JSON 协议或通用的 JDBC 驱动程序“获取数据”是不够的。 随着双方的数据在完全独立的时间线上发生变化,你需要推送、拉取、协调、协商、验证、重试、防范。 数据同步是一个复杂的问题,客户端需要像后端一样复杂。它们需要协同工作。
但是一旦你做到了这一点,你就自由了。 你将获得为你同步的数据——比你手动操作更可靠和高效。 你将能够像处理所有本地数据一样处理你的数据,并且大部分时间都可以忘记同步。
在一个完美的世界中,一切都解决了,编程会是什么样子? 99% 的业务逻辑,1% 的设置,对吗? 纯粹的数据和对数据的操作。 人们不想要四分之一英寸的钻头,他们想要四分之一英寸的孔。 将其转述为编程:人们不想要数据库。 他们想要数据。
嗯,这就是数据同步引擎应该解决的问题——纯粹、干净、功能性的业务代码,与不可靠的网络带来的恐怖分离。 我一生中最美好的时光是当我处理本地数据并_其他东西_在后台同步它时。
你也会得到一个数据库。 这听起来可能存在争议,但数据库可以很好地管理数据。 查询更简洁,访问速度更快,数据更有组织。 我自己是一个极简主义者,但是当从(本地)数据库查询某些东西时,它们会更好。 也会更快。
for(id of ids){
const user = users[id];
for(const post_id of user.post_ids){
const post = posts[post_id];
for(const comment_id of post.comment_ids){
const comment = comments[comment_id];
if(comment.author_id=== id){
// there must be a better way...
// 一定有更好的方法...
}
}
}
}
快速:当你想要按作者查询帖子,以及按帖子查询作者时,应该使用什么数据结构? 或者:我还没有见过一个代码库为其查询的数据维护单独的内存索引。 或者,它是否进行了哈希连接? 通常它是某种形式的四个嵌套循环,循环遍历无法控制的映射和数组组合。 我不评判——我经历过——但是有些工具可以为你更好、更快地完成它。 也更容易阅读。
然后是 SQL。 它是最好的,也是最坏的。 我休息了几年,我完全忘记了它可以做哪些疯狂的事情——但也忘记了一些简单的事情有多么疯狂。 像下面这样简单的事情
const query ={
goals:{
todos:{},
},
};
通过 SQL 查询时会变成
SELECT g.*, gt.todos
FROM goals g
JOIN(
SELECT g.id, json_agg(t.*)as todos
FROM goals g
LEFTJOIN todos t on g.id = t.goal_id
GROUPBY1
) gt on g.id = gt.id
当然,有历史遗留问题、现有的工具以及所有的教学材料。 很难替换 SQL,而且要击败它难上加难。 我只想说:如果你因为 SQL 而不喜欢数据库,我理解你。 真的。 我明白。 你并不孤单。
我确切知道的是,你可以在没有 SQL 的情况下到达你要去的地方。 我使用 Datalog 一段时间了,并且在没有接触 SQL 的情况下完成了所有相同的事情。 我知道这是可能的——我自己已经看到了。 还有其他同样强大的查询语言,可以用(可能)更好的人体工程学来完成实际工作。 SQL 不是终点。
那么,数据同步引擎的意义是什么? 我有一个理论,即每次重大的技术转变都发生在堆栈的一个部分与另一部分崩溃时。 例如:
- Web 应用使得跨平台开发崩溃。 现在,你不再需要开发两个或三个版本的应用,而是开发一个可以在任何地方使用的应用!
- Node.js 使得客户端和服务器开发崩溃。 你得到一种语言而不是两种! 你可以在它们之间共享代码!
- Docker 使得开发和生产之间的区别崩溃。
- React 使得 HTML 和 JS 崩溃,Tailwind 使得 JS 和 CSS 崩溃。
那么数据同步引擎又如何呢? 它们使数据库和服务器崩溃。 如果你的数据库足够智能且足够强大,那么你为什么还需要服务器? 托管数据库使你免于托管的恐怖,并让你的数据自由地流向前端。
我从没想过这在实践中是可能的,但是后来 Roam Research 证明我错了。 在公开后的头几年,他们没有一个服务器。 一切都同步到 Firebase 并从 Firebase 提供服务。 这简直就是梦想。
这或多或少地涵盖了所有内容。 我们正在构建一个数据同步引擎,因为临时地、视情况而定地同步数据既困难又容易出错。 我们也在构建它,因为我们相信它可以以有意义的方式简化堆栈。 毕竟,我们也希望我们的 AI 霸主能愉快地编程。
感谢 Stepan Parunashvili、Joe Averbukh 和 Kevin Lynagh 审阅了本文的草稿。 [1] 除非你拥有无限的时间和资源。 是的,Figma 和 Linear 都在构建产品的同时构建了他们的同步引擎。 例外情况总是存在。
Instant Engineered in San Francisco ExamplesEssaysDocsDiscordGitHubPrivacy PolicyTermsLogin Signup