在不知道工作负载之前就选定数据库实例规格,这套老旧的搭建模式一直让人头疼。整个过程通常很别扭,而且对算力的浪费感特别强,尤其在算力越来越像一种奢侈品的当下。

Lakebase Postgres 干脆把选规格这一步整个去掉了,靠的是自动扩缩容。它的响应速度来自原地调整虚拟机大小,以及一个同时跟踪 CPU、内存和数据库工作集的算法。

打开网易新闻 查看精彩图片

下面这张图展示了一批 Lakebase Postgres 数据库的自动扩缩容情况,注意这仅仅是一个小时内的变化。

打开网易新闻 查看精彩图片

把执行和存储拆开,是自动扩缩容的地基

传统 Postgres 是一个有状态的进程,绑定在特定机器和磁盘上。替换或调整那台机器,本身就是一次数据库操作,因为机器同时掌管着执行和持久化状态。

Lakebase Postgres 的架构把这两项职责分开了。计算节点因此可以启动、停止、迁移或改变规格,而不用移动底层的数据库。这是整个机制能够成立的关键基础。

实现自动扩缩容要解决两件事:第一,判断什么时候该把容量调高或调低;第二,怎么在不停止 Postgres 的情况下完成调整。

三个信号决定最终扩缩容目标

为了判断何时调整规格,Lakebase Postgres 的自动扩缩容算法跟踪三个信号,每个信号都会产生自己的目标计算规格:

  • CPU 使用情况
  • 内存压力
  • 数据库工作集大小

最终的扩缩容目标是三者中最大的那个,同时受用户为该数据库配置的最小和最大计算规格约束,也就是自动扩缩容的上下限。

CPU 信号:一分钟平均加五秒轮询

CPU 是三个信号里最直接的一个。算法会密切监视处理器的繁忙程度。

打开网易新闻 查看精彩图片

使用一分钟平均值,可以过滤掉非常短的波动,同时仍然能对有意义的需求变化做出响应。五秒的轮询间隔让系统能够随着平均值移动而更新目标。

但光看 CPU 还不够。一个查询可能在等待数据从网络传过来,这时 CPU 使用率很低,性能却很差。算法还需要把内存和缓存压力纳入考量。

内存信号:两个频率盯住耗尽风险

内存的故障模式和 CPU 不同。如果需求短暂超过可用 CPU,查询会变慢;但如果 Postgres 分配的内存超过虚拟机拥有的量,内核可能会终止进程。因此自动扩缩容对内存耗尽需要一个比 CPU 快得多的信号。

系统在两个频率上监视内存。内存目标是把使用率控制在已分配内存的 75% 以下,这些余量让系统有空间响应新的分配请求,也给客户操作系统和其他进程留出内存。

虚拟机监视器还会检查每一次提议的缩容操作。如果缩容会导致正在运行的进程没有足够空间,内存就不能被移除。

从事件驱动改成轮询,换来更可预测的行为

这套轮询方案其实替换了更早的一个设计。早期版本基于 cgroup 的 memory.high 事件,一旦越过 memory.high,Linux 会回收内存并限制 cgroup 内进程的运行。

相比之下,轮询被证明更可预测,也更容易控制。自动扩缩容的完整实现,正是建立在这种对 CPU 和内存信号的持续采样之上。