2

【译】十年磨一剑:EdgeDB 简史——PEP、uvloop 与 asyncpg

 2 years ago
source link: https://my.oschina.net/edgedb/blog/5428647
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

【译】十年磨一剑:EdgeDB 简史——PEP、uvloop 与 asyncpg

原文《Building a production database in ten years or less》 发布于 2022 年 1 月 25 日,作者 Yury Selivanov(@1st1)。

本文特设 HN 讨论区

终于,你厌倦了 $此处填入你常用的数据库品牌,忍无可忍,只能亲自下场,轮一个新的数据库。你有一堆想法,写了很多笔记,坚定不移地相信这就是全世界期待已久的数据库。现在要做的就只剩下,辞掉工作,几个月肝出 1.0 来,对吧?

也许你可以做到!但是——委婉地说——那与我们的经历有些不同。

在即将进入 EdgeDB 后 1.0 时代之前,我们想要回顾一下曾经走过的路——坎坷却充满意义,而且总是比我们想象的要长得多。一路上我们附带搞出了两个主要的开源项目(uvloopasyncpg),为 Python 语言引入了 async/await 关键字,成长为了一个 10 人的开源公司,以及总结出了一些经验教训(希望能长记性),希望对其他想轮数据库的人有帮助。🚀

经过了 2100 个 PR、4600 次集成测试,我们将在农历虎年正月初十——也就是一个星期之后——发布 EdgeDB 的第一个稳定版,作为首届 EdgeDB Day 活动的一部分,该“微型会议”将以线上直播的方式,在两个小时之内,通过一系列闪电演讲,为您解答关于 EdgeDB 的疑问:它有什么用、graph-relational 数据库是什么、明星功能 EdgeQL 等等。

线上直播在油管,可免费注册;会后译者将尝试制作中文字幕并发于 B 站。

让我们回到最初的开始。

2008 年:MagicStack

这一年,我和我的 EdgeDB 联合创始人 Elvis 一同创建了 MagicStack 公司,一个小而精的软件开发作坊。几年里,我们服务了大量不同的客户,从早期创业公司,到财富 500 强的公司如通用电气和微软。

2009 年至 2014 年:一团“乱麻”

我们很早就意识到了,自己在不同项目上一遍一遍地重复解决着同样的问题。这是一种累赘,并且会从本应有趣且充满创造性的工作中抢走时间。

因为厌倦了现有技术,又被 Google Wave 撩了一把,于是我们选择了孵化一套自己的工具集,主要是用 Python 写的,用在了不同的外包项目中。

  • 基于组件的声明式用户界面生成器。(眼熟?)
  • 一个用于构建后端服务的 RPC 库,支持装饰器和一些“元编程”的功能。
  • 一个用于将媒体元素和样式表加载到 Python 文件中的打包器。

office-2010.jpg

这其中的王牌则是一个叫做“乱麻”(Caos,意大利语“混乱”的意思,译注)的数据层“超级 ORM”,提供了:

  • 一种面向对象的 schema 定义语言,语法类似 YAML。
  • 支持 schema 混入式组合、索引、约束、动态计算属性以及丰富的自省功能。
  • 一种支持查询组合与深层嵌套的查询语言(自然地就被叫做 CaosQL 了,乱麻语)。

“乱麻”能解析“乱麻语”查询、按照当前 schema 验证查询合法性并将它们编译成等价的 SQL 语句。在当时,这就是我们的秘密武器,我们在快速交付的同时,还做到了快乐交付。每做一个项目,“乱麻”都能得到一些改进。许多现在 EdgeDB 的重要概念,在当时的“乱麻”里就已经有了,比如链接、schema 多继承、简便的嵌套查询以及对自省功能的重点照顾。

caos.jpg

因为我们的代码严重依赖“元编程”,所以在 2012 年下半年,当 Python 社区开始寻找志愿者,为 Python 设计一个更好的自省 API(PEP 362)时,我们把握住了这个机会,第一次大举进军开源届,因为我们的 RPC 库同样也需要这个自省 API。

pycon-2013.jpg

之后没多久,我就开始向 asyncio 提交 PR,并在后来的 2013 年成为一名 Python 核心开发者。在 2013 至 2015 年间,我和 Elvis 开启了输出模式,向 Python 语言本身及其生态环境贡献了更多的代码和项目。

2014 年:游艇汇

时值 2014 年,我们选择启动一个自己的产品,因为不想继续再做咨询了。“乱麻”已经给我们打好了十分出众的技术基础,所以我们的第一个产品自然应该是……游艇租赁。你没听错,产品就叫“游艇汇”。

那几个月的努力虽然命途多舛,但还是很有趣的。用“乱麻”和积累的其他工具集,我和 Elvis 得以在破纪录的时间里做出了核心产品,但我们却没有同样迅速地意识到,游艇租赁并不是一门靠谱的生意,真是活到老学到老。

boats-boats-boats.jpg

事后,我们重新检视了过去 7 年攒下来的这些轮子,大部分已经被以 JavaScript 生态为主的其他人超越了——React 替代了我们的组件式 UI 库,GraphQL 能处理我们 RPC 库的大部分场景,我们的打包器现在也可以用更好的 Webpack 来替代了。

我们唯独没有在数据库层面看到类似的行业突破,而且老实说看上去还在走下坡路——我们眼睁睁地看着剥离了 schema 的 NoSQL 数据存储软件起高楼,就感觉整个软件行业跟 SQL 和关系模型纠结了许多年后,忽然就决定集体投降了。

直到那一天晚上,我和 Elvis 轻快地走在多伦多下班的小路上,忽然就顿悟了。“乱麻”就代表了技术前进的新方向——不是作为一个 ORM 框架,而是一个数据库。

not-an-orm.jpg

2015 年:I/O 的纠结

要在 EdgeDB 上取得进展,我们仍需打造几个重要的基础设施。

我们最初的计划是,将“乱麻”从一个 Python 的框架,重构为一个完备的数据库服务器,可以处理通过网络收到的查询请求。而为了能够支持成千上万的并发连接数,我们无法用多线程的阻塞式 I/O 模型(原因可以另写一篇博客了),只能采用异步模型。

差不多的时间里,我们也在设计 EdgeDB 的 Python 客户端库的预设 API,但很快就在数据库事务 API 上碰了钉子——那时后的协程还在用 yield from,所以语句长的让人头大:

tx = yield from conn.start_transaction()
try:
    print(yield from tx.query('...'))
except Exception:
    yield from tx.rollback()
    raise
else:
    yield from tx.commit()

我们意识到,如果 Python 能够原生支持 async with 语法,那么事务的写法就可以十分雅致。于是我就打算搞一个 PEP。

async with conn.transaction() as tx:
    print(await tx.query('...'))

很快,PEP 的草稿就扩增了 async for(用以支持异步数据库游标)和基本的 async/await。我花了几个星期肝出了 PEP 492,并在 2015 年四月完成了全部工作,最后赶在 Python 3.5 的功能冻结之前通过了审议,PEP 492 正式成为 Python 的一部分。如此重大的提案能被 Python 社区采纳,是我经历过的最刺激的一件事。

2016 年初:Cython 粉墨登场

当我们开始意识到纯 Python 的速度已经无法满足 EdgeDB 处理 I/O 的需要时,我们抓来了 Cython 做小白鼠,因为我们可以用类似 Python 的语法,来快速搭建媲美原生性能的原型。于是我们又花了几个星期的时间,把 libuv 嫁接到了 Cython 上,而 libuv 原本是一个为 Node.js 打造的非阻塞 I/O 网络库。

uvloop.jpg

这就是 uvloop,可以直接用来替换 Python 内置的 asyncio 事件循环核心,并提供 2—4 倍的性能提升。当时写 uvloop博客文章浏览量还挺大的,uvloop 也几乎一夜爆红,现在被我们用在 EdgeDB 里当垫脚石。

2016 年中:开往 Postgres 的高铁

EdgeDB 使用了 Postgres 作为底层支持,因为 Postgres 作为实打实的世界上最先进的开源 SQL 数据库,可以为更好的新型数据库抽象提供终极基础保障。

提示:许多 EdgeDB 的初学者经常困惑,如果 Postgres 已经是一个数据库了,现在 EdgeDB 又是基于 Postgres 的,那么 EdgeDB 就应该是一个 ORM(关系对象映射器)?

我们并不这么认为,因为 EdgeDB 正式地定义了自己的查询语言 EdgeQL,不仅对标 SQL 的全部功能,而且在简明程度上超越 SQL;EdgeDB 不限制使用者的编程语言,而多数 ORM 库都是为某一种特定语言设计的;EdgeDB 有自己的类型系统、标准库、二进制通讯协议、支持多种编程语言的客户端库、命令行工具、开发工作流和使用惯例,所以怎么讲 EdgeDB 都能算得上是一个数据库。

有了 async/await 关键字和一个高性能异步事件循环库,我们开始评估 Python 中异步 Postgres 驱动的现状。可惜,没有一个能打的,所以我们只好自己轮,并在过程中学习到了很多关于 Postgres 二进制协议的优缺点。

2016 年,在西班牙毕尔巴鄂举办的 EuroPython 大会上,我得以顺利演示我们的成果 asyncpg,因为在演讲前两个小时,我们才完成最后的开发工作,Elvis 一如既往地在最后一刻做出了关键的修补。八月份,我们把 asyncpg 发布在了 HN 上,自此获得了广泛的使用,在 GitHub 攒到了 5200 颗星星。

2017 年至 2018 年:我们做一个数据库吧

有了 async/await、Cython、uvloopasyncpg 的加持,我们终于可以实现 EdgeDB 了。虽然仍在全职做外包咨询,我们还是会在晚上用白板做设计,EdgeDB 现在的主体结构就是当时做出来的:类型系统、EdgeQL 语法和 SDL(schema 定义语言)。有了这些,我们开始尝试推一波技术预览版的 EdgeDB。

为了强迫我们自己按时交付,我们签下了 2018 年 PyCon 大会的金牌赞助商合同,此时距大会开幕仅剩五个月的时间。我们预定了一个展位,印制了 3500 份宣传册,能想到的都做了。自然,我们又一次压哨完成了预览版的开发,在美国克里夫兰一个不知名的民宿里熬了一宿。

booklet.jpg

结果宣传效果非常不错,PyCon 上人们很喜欢 EdgeDB,我们回答了与会者成百上千的疑问,收到的反馈堆成山,我们兑现了 EdgeDB 的交付承诺。

pycon-2018.jpg

2019 年初:第一个 alpha 版本

从这时起,我们降低了外包咨询的工作比重,减少到够糊口即可,从而腾出时间专攻 EdgeDB 的第一个 alpha 版本。前面的技术预览版虽然是个不错的原型,但想要发布第一个版本,EdgeDB 还需一些火候。

我们严肃整顿了 EdgeDB 的类型体系,优化了运算符和类型转换系统的安全性和可用性,增加了内置的 GraphQL 支持,根据我们在 asyncpg 的经验和对 Postgres 协议的了解,设计了一套 EdgeDB 的二进制通讯协议,以及基于此协议的 Python 客户端。这段时间之后,EdgeDB 的主体已然定型。

edgeql.jpg

2019 年四月,正好在展示 EdgeDB 技术预览版一年之后,我们发布了第一个 alpha 版本,并在 HN 获得了不错的反响(中文版收录在《如何让数据库工效翻十倍》)。不多久,我们另外一篇博客文章《SQL 就这?我们能做得更好》又在 HN 登顶(在 V2EX 也有不少精彩讨论)。这增强了我们的信念:人们对现有数据库的开发体验有相当程度潜在的不满,我们必须继续努力。

2019 年末:EdgeDB 公司

在 2019 年下半年,我们将公司总部从加拿大多伦多迁到了美国旧金山,并成立了 EdgeDB 公司。

sf-office.jpg

2020 年:alpha 之年

这一年里,我们的公司从最初的 3 个人成长到 9 个人,并发布了 6 个后续 alpha 版本。

alpha-year.jpg

这些版本包括了一大堆新工具,包括:

  • 一个用 Rust 写的新命令行工具(CLI);
  • 一套数据结构迁移系统(migration),以及配套的 CLI 开发工作流;
  • 持续优化的二进制通讯协议;
  • 一个 JavaScript 客户端库;
  • 备份与恢复功能;
  • 一种新的 EdgeQL 语法,用于自动创建或更新数据(upsert);
  • 以及最棒的交互式查询工具。

不嫌麻烦的话,你可以查阅我们的博客,那里有全部 6 个 alpha 版本的详细演进过程。

2021 年:beta 之年

EdgeDB 的第一个 beta 版本发布于 2021 年二月份,在后续的一年里,我们总共发布了三个 beta 版本和三个 RC 版本。

beta-year.jpg

随着 EdgeDB 的核心产品越来越成熟,我们将工作的中心转到了开发工作流上——如何让 EdgeDB 的开发者体验全面超越所有的现存数据库?包括数据库安装、数据库实例管理、执行 migration、文档阅读、命令行工具的使用、查询数据等等。

嗯……经过不懈的努力,我们重新设计了我们的命令行工具(RFC 1006),升级了客户端库,设计了更符合人类工效学的 API 接口,并增加了对 GoDeno 的支持,捎带手还修了一个 Deno TLS ALPN 的功能。我们重写了 EdgeDB 的文档,发布了一本叫做《EdgeDB 易经》的交互式图书(中文版在来的路上了!),并且还打造了一份华丽的笔记风格的 EdgeQL 教程中文版已排期!)。我们还着手开发了一个用于 TypeScript 的查询构造器,或将 ORM 扔进历史的垃圾箱——欲知后事如何,且听下回分解。👀

2022 年:飞向稳定,浩瀚无垠!

这就到了现在了,一个星期之后,我们将正式发布 EdgeDB 1.0 稳定版,希望你能喜欢。至少可以说,这是一段非凡的旅程。

这篇文章到现在都没怎么讲 EdgeDB 到底是什么,有兴趣的话,可以参加我们大年初十举办的发布活动(活动为油管英文,中文字幕版将发在 B 站),这是一个两小时的微型会议,希望能解答你的各种问题。点击领票:

Thanks to Colin McDonnell and Elvis for feedback and edits on this post.

欢迎关注我们的官方网站掘金专栏知乎专栏OSCHINA 项目主页,了解更多资讯。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK