DynamoDB 的云原生之路 —— 流控策略的演进

简介: DynamoDB 的云原生之路 —— 流控策略的演进

概述:流控为啥重要

上云的好处在于池化资源,让多租户共享,然后按需分配,从而降低成本。但进行:

  1. 多租户隔离:用户要求可以使用其买到的流量,并且不会被其他租户影响。
  2. 资源共享:资源只能逻辑隔开,不能物理隔开,否则无法充分动态分配(超发)。

是一对相对矛盾的事情,我认为,也是云原生数据库最要解决的问题。不把这个问题解决好,则数据库:

  1. 要么平台不赚钱:比如资源静态预留,虽然可以让用户满意,总能随时用到卖给他的资源配额,但会存在巨大资源浪费,要么价格贵,要么用户不买单。
  2. 要么用户不满意:多用户共享物理资源,但非常容易进行互相影响,造成用户不能用到平台声称的配额。

DynamoDB 从静态分配开始,逐步演化出一套全局和局部组合的准入控制机制,从而实现了物理上资源共享,但又在逻辑上给用户以配额隔离,从而实现了数据库真正的云原生。下面,我依据 Amazon DynamoDB: A Scalable, Predictably Performant, and Fully Managed NoSQL Database Service[1] 这篇论文披露的细节,对其流控机制的演进过程做一个梳理,以飨诸君。

水平所限,谬误之处,欢迎在评论区指出。

木鸟杂记 https://www.qtmuniao.com/2022/09/24/dynamo-db-flow-control 转载请注明出处

开始:静态预留

这里面对的其实是一个常见的调度问题,如何将表的分片副本(table-partition-replication)调度到集群(一组物理机)上,并兼顾以下特性:

  1. 可用性:将物理机划分 AZ(Availability Zones,可用域),将不同副本调度到不同 AZ。
  2. 数据容量:其实是针对存储资源,每个物理机有容量总额,每个副本也有容量预期(能随着容量自动分裂,所以刚开始可能都比较小),表的分区副本创建时,需要为其寻找物理机资源余量大于其需求量的目标机器。比如,一个很简单的撮合策略是每次找集群中最空闲的那个机器。
  3. 流量:文中称 performance,其实包括计算资源网络带宽。分配方式和 2 类似。

本文关注重点主要在 3 上,并且引入了流量单位:读容量单位 (RCUs) 和写容量单位 (WCUs)。

最开始的策略是将表的总配额(provisioned capacity)平均分配给每个分区,比如表的总配额是 1000 RCUs,一共十个分区,每个分区 100 RCUs。则每个分区的流量不得超过 100 RCUs。

这种策略最大的优点就是实现简单,而缺点繁多。让我们仔细审视下该策略,发现它其实蕴含了一个假设:分区间的流量是均匀的。但在现实中,这种模型太理想了。而一旦分区流量不均匀,就有可能出现,某些分区由于流量大,达到了该分区配额 100 WCUs 而被限流;而另外一些流量小的分区的配额却被浪费。

初步:突发策略和自适应流量

为了给上述纯静态分配策略打个补丁,DynamoDB 开始引入了流量突发(busting)和流量自适应(adaptive)策略。

突发策略

为了应对某些分区短时突发流量(short-live spikes)的问题,DynamoDB 引入了一个补丁(workaround),如果发现某个分区瞬时流量较大,且分区副本所在节点还有余量,就临时给该副本调配一些。具体到实现上,DynamoDB 用了三个令牌桶:

  1. 分区预留令牌桶。对应前面例子中的那 100 RCUs,当分区流量不超过这个值时,允许读写且从该令牌桶中扣除相应数量令牌。
  2. 节点总量令牌桶。对应单机容量限制,所有请求到来时,都要消耗此桶中令牌。
  3. 分区突发令牌桶。当分区流量超过预留时,会检查节点总量令牌桶是否还有余量,如果有就允许该分区进行突发。

需要注意,RCU 配额用上述策略就够了,但对于 WCU 配额,DynamoDB 还加了一条限制:需要检查该分区所有副本的 WCU 总额是否超限。其想法是,RCU 可以适当多给,但 WCU 不行。实现也很朴素,每个分区(多副本会构成一个复制组) Leader 会充当协调者,进行容量信息收集和分发。

最后,该策略只用于解决 300 秒内的短时突发流量,超过了时间窗口,借调的流量是要被释放出来的。因为这部分流量属于机器中的超发流量,需要随时准备调配给本机上的其他分区副本使用。

自适应策略

那对于长时突发流量(long-live spikes)怎么解决呢?只能在不同分区中进行流量调配了。

DynamoDB 使用某个中心服务(论文中就叫 Adaptive capacity,不确定该组件是额外引入的还是属于某个中心服务的一部分),来监控每个表的总配额已耗容量

当某个表还有余量,但表的某些分区因为流量突发被限流时,可以通过按成比例控制算法(a proportional control algorithm,应该就是按流量大小比例)来给这些分区调配一些配额。并且,如果调配后,触到了所在存储节点整机配额上限,自动管理系统(autoadmin system)会将该分区迁移到相对空闲、可以提供所需配额增量的机器。

反思:分区和流控耦合

前两者最大特点是将流控分区过紧地耦合到了一块,即在分区级别做的流量控制,因此很难对一个表进行跨分区进行流量调度。而我们对用户提供的是表级别的配额抽象,因此最好隐藏分区这个物理实现,保证只要表的总配额还有余量,就能给有突发流量的数据进行分配。而不能说,一些分区流量小,但仍然占用着配额,另外一些分区流量大,但在用完了分配给其的配额后,就要被限流。

虽然自适应策略在跨分区方向做了一些改进,但仍然是补丁范畴,而不是将动态流控作为第一思想来设计。为此,DynamoDB 引入全局准入控制机制来彻底解决此问题。

改进:全局准入控制

全局准入控制(global admission control,GAC)同样使用令牌桶的实现方式,但与之前局部令牌桶不同,全局准入控制使用一种全局令牌桶,或者说分布式令牌桶。由 GAC 服务来产生令牌,请求路由实例消费令牌,来达到表粒度准入控制。

组件

image.png

                                       DynamoDB 架构

  1. GAC 服务:由一组 GAC 实例构成,以一致性哈希[2]的方式进行流量均摊。
  2. GAC 实例:使用令牌桶方式产生令牌,每个实例会维护一个或者多个表级别的令牌桶。
  3. 请求路由器:request router,GAC 的客户端,与 GAC 服务通信,获取令牌进行流控。其中,令牌是有时限的,过期不被消费也会自动销毁。

其中有个关键问题是,GAC 每次给某个请求路由实例分配多少令牌?

DynamoDB 会根据历史信息,追踪每个请求路由实例的消费速率,按速率等比例分配。那如何进行追踪呢?论文中没有提,估计是使用滑动时间窗口之类的,但这类信号也不太好做,总会出现刻画不准或延迟太大的情况,不知道 DynamoDB 具体是如何实现的。

动态均衡

与静态分区和流量配额不同,GAC 视角下的分区流量会随时变化。为了避免热点聚集导致某些存储节点被打垮,DynamoDB 实现了一套可以主动根据吞吐消耗存储量来对分区进行跨节点均衡的机制:

  1. 每个存储节点会各自进行资源用量核算,如果节点资源总用量超过节点某个百分比阈值,该存储节点就会主动向自动管理服务(autoadmin service)汇报,并给出一组待迁移副本候选列表
  2. 自动管理服务在收到请求后,会根据全局资源分布,为每个候选副本找到一个合适存储节点,同时满足开篇提到的可用性资源用量约束。

流量拆分

如果某个分区上有很大的热点,受限于所在节点负载可能仍会被限流。DynamoDB 会追踪这些热点,并统计该分区上数据的流量分布,按流量对分区进行切分。相比单纯的按中点(均衡存储资源)进行分裂,按流量分布(计算和带宽)进行切分,对于消除热点来说,可能更为本质。分区拆分后,可以按需进行迁移。

分区分裂的所需时间通常在分钟量级。

但有一些访问热点,并不能通过分区分裂来进行消除:

  1. 单数据条目热点
  2. 范围访问热点

DynamoDB 能够识别这类访问模式,从而避免在这样的分区上进行拆分。

自动配给

在创建表时就为表设定固定配额是一件很难的事情,就跟你需要预知将来一样。如果设置的多了,会造成资源浪费;设置的少了,又容易触发限流。这是静态配额的一个弊端,因此 DynamoDB 提供一种动态配额表on-demand provisioning table,然后按用实际用量计费,这也是云计算的一大特征)。

为了精确描述配额,DynamoDB 引入了衡量吞吐的概念:读写容量单位(read and write capacity units)。如果单纯用 QPS 刻画流量,显然不合适,因为每个请求所涉及的数据量是不等的。因此 DynamoDB 引入单位时间内单位流量额度:RCU 和 WCU 来对读写流量进行刻画。

在进行自动配额时,首先要准确追踪读写流量。在检测到流量突发且要触发限流时,会对配额进行指数扩充(二倍)。如果应用持续流量大于之前尖峰的二倍,则会通过按流量拆分分区等方法进一步提高整体配额。

小结

云上一个重要特征就是资源池化、按需分配精准计费,从而在整体上实现资源的充分利用,通过规模化优势抵消通用性带来的成本。

具体到云原生数据库中,便是多租户流量的自动配给。DynamoDB 通过论文披露了其从配额静态划分、打补丁演进,到全局动态划分的一个演进过程。对于国内各路号称要做云原生数据库的厂商来说,想要在保证用户体验(资源隔离)的前提下真正赚钱(资源共享),DynamoDB 的经验想必有诸多可借鉴之处。


我是青藤木鸟,一个喜欢摄影的分布式系统程序员,欢迎关注我的公众号:”木鸟杂记“,获取分布式系统入门指导和诸多论文翻译。如果感觉不错,就帮忙点个在看分享给更多人吧,感谢~参考资料

[1]Amazon DynamoDB: A Scalable, Predictably Performant, and Fully Managed NoSQL Database Service: https://www.usenix.org/system/files/atc22-elhemali.pdf

[2]wiki consistent hash: https://en.wikipedia.org/wiki/Consistent_hashing

相关文章
|
9天前
|
消息中间件 存储 Cloud Native
云原生架构下的数据一致性挑战与应对策略####
本文探讨了在云原生环境中,面对微服务架构的广泛应用,数据一致性问题成为系统设计的核心挑战之一。通过分析云原生环境的特点,阐述了数据不一致性的常见场景及其对业务的影响,并深入讨论了解决这些问题的策略,包括采用分布式事务、事件驱动架构、补偿机制以及利用云平台提供的托管服务等。文章旨在为开发者提供一套系统性的解决方案框架,以应对在动态、分布式的云原生应用中保持数据一致性的复杂性。 ####
|
3月前
|
运维 监控 Cloud Native
云原生时代的运维策略:从反应式到主动式的转变
在云原生技术日益成为企业数字化转型的核心动力时,运维团队面临着前所未有的挑战与机遇。本文将深入探讨云原生环境下的运维模式转变,从传统的反应式运维逐步向更加高效的主动式运维演进,以及这一转变如何影响企业的成本效益、系统稳定性和团队协作。文章将通过具体案例分析,阐述主动式运维的实践路径,并讨论其对企业运维文化的深远影响。
|
5天前
|
Cloud Native 安全 API
云原生架构下的微服务治理策略与实践####
—透过云原生的棱镜,探索微服务架构下的挑战与应对之道 本文旨在探讨云原生环境下,微服务架构所面临的关键挑战及有效的治理策略。随着云计算技术的深入发展,越来越多的企业选择采用云原生架构来构建和部署其应用程序,以期获得更高的灵活性、可扩展性和效率。然而,微服务架构的复杂性也带来了服务发现、负载均衡、故障恢复等一系列治理难题。本文将深入分析这些问题,并提出一套基于云原生技术栈的微服务治理框架,包括服务网格的应用、API网关的集成、以及动态配置管理等关键方面,旨在为企业实现高效、稳定的微服务架构提供参考路径。 ####
26 5
|
7天前
|
Kubernetes 负载均衡 Cloud Native
云原生架构下的微服务治理策略
随着云原生技术的不断成熟,微服务架构已成为现代应用开发的主流选择。本文探讨了在云原生环境下实施微服务治理的策略和方法,重点分析了服务发现、负载均衡、故障恢复和配置管理等关键技术点,以及如何利用Kubernetes等容器编排工具来优化微服务的部署和管理。文章旨在为开发者提供一套实用的微服务治理框架,帮助其在复杂的云环境中构建高效、可靠的分布式系统。
21 5
|
7天前
|
负载均衡 监控 Cloud Native
云原生架构下的微服务治理策略与实践####
在数字化转型浪潮中,企业纷纷拥抱云计算,而云原生架构作为其核心技术支撑,正引领着一场深刻的技术变革。本文聚焦于云原生环境下微服务架构的治理策略与实践,探讨如何通过精细化的服务管理、动态的流量调度、高效的故障恢复机制以及持续的监控优化,构建弹性、可靠且易于维护的分布式系统。我们将深入剖析微服务治理的核心要素,结合具体案例,揭示其在提升系统稳定性、扩展性和敏捷性方面的关键作用,为读者提供一套切实可行的云原生微服务治理指南。 ####
|
23天前
|
监控 Cloud Native Java
云原生架构下微服务治理策略与实践####
【10月更文挑战第20天】 本文深入探讨了云原生环境下微服务架构的治理策略,通过分析当前技术趋势与挑战,提出了一系列高效、可扩展的微服务治理最佳实践方案。不同于传统摘要概述内容要点,本部分直接聚焦于治理核心——如何在动态多变的分布式系统中实现服务的自动发现、配置管理、流量控制及故障恢复,旨在为开发者提供一套系统性的方法论,助力企业在云端构建更加健壮、灵活的应用程序。 ####
73 10
|
19天前
|
监控 安全 Cloud Native
云原生安全:Istio在微服务架构中的安全策略与实践
【10月更文挑战第26天】随着云计算的发展,云原生架构成为企业数字化转型的关键。微服务作为其核心组件,虽具备灵活性和可扩展性,但也带来安全挑战。Istio作为开源服务网格,通过双向TLS加密、细粒度访问控制和强大的审计监控功能,有效保障微服务间的通信安全,成为云原生安全的重要工具。
39 2
|
19天前
|
弹性计算 监控 Cloud Native
云原生架构下的性能优化实践与策略####
在数字化转型加速的今天,云原生技术以其弹性、敏捷和高效的特点成为企业IT架构转型的首选。本文深入探讨了云原生架构的核心理念,通过具体案例分析,揭示了性能优化的关键路径与策略,为开发者和企业提供了可操作的实践指南。 ####
|
30天前
|
负载均衡 监控 Cloud Native
云原生架构下的微服务治理策略与实践####
在数字化转型加速的今天,云原生技术以其高效、灵活、可扩展的特性成为企业IT架构转型的首选。本文深入探讨了云原生环境下微服务治理的策略与实践路径,旨在为读者提供一个系统性的微服务治理框架,涵盖从服务设计、部署、监控到运维的全生命周期管理,助力企业在云端构建更加稳定、高效的业务系统。 ####
|
6月前
|
存储 弹性计算 监控
【阿里云云原生专栏】成本优化策略:在阿里云云原生平台上实现资源高效利用
【5月更文挑战第29天】本文探讨了在阿里云云原生平台上实现资源高效利用和成本优化的策略。通过资源监控与评估,利用CloudMonitor和Prometheus等工具分析CPU、内存等使用情况,识别浪费。实施弹性伸缩策略,利用自动伸缩规则根据业务负载动态调整资源。借助容器化管理和Kubernetes编排提高资源利用率,优化存储选择如OSS、NAS,以及网络配置如VPC和CDN。示例展示了如何使用Kubernetes的HorizontalPodAutoscaler进行弹性伸缩,降低成本。
241 4

热门文章

最新文章