ITPub博客

首页 > 数据库 > 数据库开发技术 > 节流器剖析,第 3 部分 — PlanetScale

节流器剖析,第 3 部分 — PlanetScale

数据库开发技术 作者:ITPUB社群 时间:1970-01-01 08:33:44 0 删除 编辑

这是三部分博客系列的最后一部分。如果您错过了之前的文章,可以通过阅读第一部分和第二部分来了解。在这篇结论中,我们将讨论节流器客户端及其身份、协作、优先级和约束问题。

识别客户端

我们的关注点继续放在异步、批量和海量操作上,例如 ETL、数据导入和模式变更。调用这些操作的组件就是节流器的客户端。这些组件需要将操作分解为合理的小子任务,并定期向节流器请求继续执行的许可。这是一种协作模型,客户端请求许可,我们稍后会讨论另一种设计。但首先,我们建议客户端应向节流器表明自己的身份。

即使只是为了分析或调查事件或能够生成指标的高层次目的,您通常也想知道哪些操作在什么时间被节流。您希望能够判断出每日聚合 ETL 作业在 07:00 到 07:25 之间大部分时间被节流。或者大约在 12:00,节流器正在处理来自多个客户端的请求,包括数据导入、对 customers 表的模式迁移以及每小时清理作业。

但客户端识别也服务于运营目的。是否可以将一个特定作业优先于其他作业?或者调低一个作业的优先级,或者暂时完全搁置它?如何优先处理某一类客户端?只有当我们能够清晰地区分客户端时,才能回答这些问题。

对客户端请求进行优先级排序是否有意义?让我们从一个看似极端的场景开始,这个场景将突显优先级排序的风险。

豁免与饥饿

在协作模型中,客户端向节流器请求许可。一个不守规矩的客户端可能会忽略连接节流器,直接发送一些海量工作负载。或者节流器可能有一种机制来豁免来自特定客户端的请求。最终结果是一样的:所有客户端都遵守规则,但有一个客户端获得了无限制操作的免费通行证。

回到复制延迟,假设客户端的工作负载耗尽了资源,导致复制延迟飙升至数分钟,远超节流器的阈值。没有任何东西能阻止这个客户端,它持续对数据库施压数小时。在此期间,来自所有其他客户端的请求都被持续拒绝。这就是饥饿场景。

豁免是有风险的,因为它不仅阻碍其他参与者的操作,还可能降低系统性能,这与节流器存在的根本原因背道而驰。在某种意义上,它破坏了规则;然而,正如我们稍后将讨论的,它也有其用武之地。

优先级排序

一种更安全的方式是在规则范围内行事。与其豁免,我们可以考虑优先级排序,或者更准确地说,降低优先级。这可以通过掷骰子来实现:客户端向限流器请求许可。限流器可以选择掷一个骰子,如果结果是,比如说,1 或 2,就完全拒绝该请求,而不考虑系统指标。因此,我们设定了一个被拒绝请求的比例。

被拒绝的客户端会退避,休眠一段时间,然后重试。因此数据库的负载会降低,代价是推迟了潜在的客户端工作。但如果我们能有选择地对一个客户端设置高拒绝率,同时对另一个客户端设置低(或零)拒绝率,那么我们就有效地将第二个客户端的优先级置于第一个之上:第一个客户端将花费更多时间退避,即使数据库指标是健康的。在此期间,第二个客户端将有更多机会完成自己的工作。

需要强调的是,两个客户端仍然遵守规则:如果数据库指标不健康,任何一方都不会获得执行操作的许可。只是其中一个有时甚至没有机会去检查那些指标。

在另一种模型中,可以将限流器配置为对所有客户端拒绝一定比例的请求,然后对某个特定客户端设置更低或零拒绝率。因此,一种安全地将一个客户端的优先级置于其他客户端之上的方式是降低所有其他客户端的优先级。

基于不同指标的限流

不同客户端基于不同指标进行限流是否合理?例如,一个客户端基于复制延迟进行限流,而第二个客户端基于复制延迟和负载平均值进行限流。

仔细来看,这是一个豁免场景。当第二个客户端基于负载平均值进行限流时,第一个客户端实际上被豁免了检查负载平均值。如果第一个客户端的工作负载确实将负载平均值推高到超过其阈值,那么第二个客户端就会陷入饥饿状态。它永远没有机会运行。

然而,这其中有细微差别。并非所有任务都是平等的。有些复制数据,有些清除数据。有些在写入争用激烈的高负载表上工作,有些处理不在内存中的旧数据。这些不同的任务对系统会有不同的影响。在实践中,工程师或管理员会熟悉特定任务的影响类型,并可以显式地为该任务指定特定的指标。这是否意味着我们必须对所有其他客户端应用相同的指标?逻辑上是肯定的,但在实践中,并非如此。在上面的例子中,第一个客户端被豁免了检查负载平均值,但它可能对指标本身并没有显著影响。如果即使没有第一个客户端,负载平均值也会很高,那么对该客户端进行限流可能根本没有任何效果,所以我们不如直接让它完成任务。在运维系统时,有一些实际考虑因素值得我们审视。

豁免在哪些情况下有意义

没有什么会永远持续。如果一个客户端在总共 12 小时的运行时间中被饿死 10 分钟,这可能不是什么大问题。

如果一个任务必须不惜一切代价运行(例如,修复故障),并且这会将资源推到超出我们在正常时期期望看到的水平,那就顺其自然吧。

如果客户端是系统本身不可或缺的一部分,并且由于数据流设计而经过限流机制,且不处理海量数据变更,那么我们可能且应当将其完全豁免。

分类与细分

如果客户端能够在不同层级上标识自身,这将更为有益。例如,在 Vitess 中,客户端可以被标识为 d666bbfc_169e_11ef_b0b3_0a43f95f28a3:vcopier:vreplication:online-ddl。这是一个 ID 为 d666bbfc_169e_11ef_b0b3_0a43f95f28a3 的 vreplication 任务,具体运行的是 vcopier 流程,代表一次 online-ddl schema 迁移。

通过这种身份标识方案,可以按类别对所有 online-ddl 任务进行优先级提升(或降低),或者仅针对某个特定任务,或者完全豁免所有 vcopier 流程。

在可观测性方面,这使得按请求类别分析限流器访问模式变得更加容易。

没有什么是永恒的

任务和操作最终会完成。但为你设置的任何规则加上时间限制也是个好主意。如果你豁免了某一类客户端,那么最好让该豁免在某个时间点过期。在高峰时段收到意外工作负载时,将所有任务降低优先级几个小时,或者在持续调查期间这样做,都是有用的。

协作与强制执行

我们已经讨论了异常(或故障)客户端跳过限流器检查的可能性。这在协作式设计中是一种可能的场景。另一种限流强制执行设计将限流器置于客户端和系统之间。限流器作为代理运行,或与现有代理集成,以便能够对客户端请求进行限流。Vitess 的事务限流器就是如此,它可以在系统性能下降时主动延迟数据库查询执行。客户端无法绕过限流器,甚至可能不知道它的存在。因此,识别客户端变得更加复杂,限流器必须依赖客户端/连接/查询提供的领域特定属性,才能区分客户端并实施所需的优先级排序。

结论

虽然我们主要讨论了数据库系统的限流,但所阐述的原则应适用于所有系统和服务的限流器。限流器的动态控制绝对至关重要,而在生产系统中,对特定请求或任务进行优先级排序或推回的能力也是必不可少的。


转载声明:本文为转载整理,原文版权归原作者及原站点所有。

原文来源:PlanetScale Blog

原创地址:https://planetscale.com/blog/anatomy-of-a-throttler-part-3

原文作者:PlanetScale Blog;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2022-11-21

  • 博文量
    1059
  • 访问量
    546558