亚马逊AWS官方博客

OPPO大数据平台在亚马逊云科技上的成本优化最佳实践

序言

OPPO 大数据基础平台架构的海外部分主要搭建在亚马逊云科技服务上,服务于公司二十多条业务线,每天对亿级用户产生的海量数据进行存储和业务价值的分析及挖掘。OPPO 以国际绿色包装“3R+1D” 为设计原则,在包装设计过程中,坚持推广和使用绿色包装的减量化(Reduce)、可回收(Reuse)、可循环(Recycle)、可降解(Degradable)。大数据SRE团队稳定支撑业务部门各类作业需求的同时,践行此OPPO可持续发展理念。在大数据,我们主动对基础架构进行持续优化,尤其是在Reduce(节省成本)这一项,取得了显著成绩:

  • 在核心数据任务准点率保持在100%的基础上每年节省数千万(人民币)
  • 敏捷成本管控,持续监控分析,按业务的明细报表次日达,及时发现、反馈问题、并协同业务方一起整改,让业务方没有后顾之忧

亚马逊云科技的服务和产品体系非常全面,计费规则比较精细,对于初学者而言,有一定的学习门槛。本文是我们对成本优化的阶段性工作总结,在此阶段我们得到了亚马逊云科技客户团队的大力协助和支持,我们希望这个阶段性总结能对大家有所启发,帮助大家更优的使用亚马逊云科技的服务,降低成本优化的入门门槛。

我们将阐述:

  1. DataOps 数据驱动,用大数据的方式运营大数据
  2. 多层优化实践:
    • 计算层(EMR/EC2)优化
    • 存储层(S3/EBS)优化
    • 网络层(DTO)优化
  3. 未来努力方向:从“数”到“智”(DataOps -> AIOps)

不过请读者注意以下两点:

  1. 图表和数据做了一定程度模糊处理,并不总是代表真实数据,仅做示意;
  2. 本文基于2022年的亚马逊云科技服务现状,未来可能会有所变化导致本文的建议不再适用,仅供参考。

1. DataOps 用大数据的方式运营大数据

大数据 SRE 团队利用Amazon EMR 为广告、搜索、推荐、应用市场等多条业务线(LOB)提供大数据处理和分析的能力,持续服务数亿全球用户。

我们不仅仅支撑大数据平台,同时也不断学习应用大数据技术,从而更好的服务业务:

  • 持续采集作业信息、亚马逊云科技 成本与用量报告(CUR),S3访问日志、各类指标等信息
  • 自动处理原始数据
    • 一方面,利用 EMR,Glue,Lambda 等工具可以进行深度定制转换
    • 另一方面,站在用户角度,自己搭的平台自己先用,持续优化用户体验
  • 借助 Amazon Athena 交互式查询服务,可以通过标准 SQL 快速探索数据,分析成本
  • Turn data into insights,综合运用 Athena 的联邦查询,可以在 Amazon QuickSight 以拖拉拽的方式跨多个数据源(S3/CloudWatch)定制报表
  • 持续监控分析:
    • 自动推送,按天报表,敏捷迭代,有问题,早发现,早反馈,早解决
    • 定期复盘, 关注一段时间内的趋势,洞察规律,提前管控,提供持续稳定且成本可控的服务

要想优化成本,必须先知道成本构成。大数据 SRE 团队在 QuickSight 定制了一系列账单分析报表,对大数据成本进行了不同层次的归类分析。

首先我们进行了诸如EMR/S3这种大类别的费用占比分析:

通过大类别的占比分析,可以确定我们的费用大头,以确定优化方向及优先性。注意上图中的EMR费用指的是EMR的托管服务费,真实的计算费用归类到了EC2-Instance中。

其次再深入到需要重点优化的某类服务的所有子类型的明细费用展示,如我们对S3桶的费用进行了整体分析:

以及对单个桶的费用明细分析:

通过各种层面的数据呈现后,我们就能通过各种产品和资源的费用占比和增长趋势确认优化的方向和先后顺序,以期尽快降低总体拥有成本。

2. 计算层(EMR/EC2)优化

EMR是我们大数据平台架构里的核心组件,通过EMR可以灵活组合各种算力,相对廉价的弹性算力-Spot机型,完美的契合了OPPO大数据业务里主力业务批计算的算力需求:弹性供给+低成本。

随着业务发展,集群迅速扩张,单个集群的规模越来越大,集群数量也不断增加。面对作业量(每天数万批处理)持续增加,如何做好资源协调,保障算力供应的同时尽可能降低成本是我们的一大挑战。

我们在社区的Yarn Router功能的基础上,自研了智能路由策略,用户提交的任务到router,router再根据资源预测信息分配到各个EMR集群,实现联邦调度,提升资源利用率。

这里简单介绍一下OPPO使用EMR集群的方式。由于业务7*24小时有作业需要运行,我们维护了几个大的EMR集群,通过设立规则对集群的实例组进行扩缩容以维护一个业务需要的合适的集群规模。

2.1       EMR集群费用构成

我们通过Amazon QuickSight分析其中一个主力集群的费用构成,如下图:

目前根据账单项目可以看到EMR费用由以下部分构成:

  • 实例费用(包括Spot、Savings Plan、On-Demand三种计费模式的EC2)
  • EMR管理费(在EMR集群里启动一台虚拟机需要单独支付的托管费用)
  • EBS卷(为EC2配置的块存储)
  • 区域内流量费(在亚马逊云科技单个区域内各可用区之间发生的网络传输费用)

三种计费模式对应实例的主要特点如下:

  • EC2-Instance-Spot:EMR竞价实例,费用最低,但是存在被强制回收和资源池不足而置备时间很长的现象;
  • EC2-Instance-Ondemand:EMR按需实例,费用最高,不会被强制回收,置备速度也较快;
  • EC2-Instance-SP:通过1年或3年期合约并承诺每小时使用量获得优惠的灵活计费模式。费用优惠幅度灵活切较大,不会被强制回收。

对此,我们可得出优化的方向:

  • 降低实例单价费用
    • 在不降低性能的前提下使用核时费便宜的机型
    • 尽可能多使用竞价机型
    • 购买Savings Plan合约
  • 减少EMR管理费
    • 使用大机型取代多台小机型,以减少最小的管理费用支出
    • 采用合理的扩缩容策略
  • 调整集群EBS卷
    • 减少集群中EBS配置不合理的实例
  • 减少流量费
    • 优化系统架构以避免跨可用区流量产生
  • 减少集群数/节点数
    • 删除小集群以减少集群的固定机器开支
    • 维持合理的Core节点数,避免浪费

2.2 降低实例单价费用

 

  • 搭配使用合适的机型

亚马逊云科技 EMR提供m,r,c,d,i,z等不同系列的机型且每个系列有不同的大小(例如m系列存在m5.2x,m5.4x不同的型号等)。我司离线任务偏向计算和内存,故考虑m,r,c系列,其他暂不考虑。其中c系列cpu:memory比 为1:2 (即1个vcore:2GB memory),m系列cpu:memory比 为1:4 ,r系列为1:8。根据我司在EMR上调试的经验,我司离线任务cpu:memory比设置为1:6较为合适。

以r5.12xlarge和m5.12xlarge为例(新加坡,注意价格会有波动):



r5.12xlarge的价格约为m5.12xlarge的1.3倍。假如一个spark/hive任务使用48个vcore,288GB memory,一台r5.12xlarge即可满足资源需求,但需要两台m5.12xlarge才能满足。两台m5.12xlarge的价格高出一台r5.12xlarge约53.33%。从成本来看,r机型很适合我们使用,但为避免因在同一个可用区内单机型的争抢无法及时拿到此机型,故同时搭配m机型使用,且r系列和m系列均搭配不同大小的型号使用。

  • 使用核时费便宜的机型

对于EMR和EC2的按需实例费用,可以见官方费用链接

其中,左侧为按需(On-Demand)时的机器实例费用,右侧为使用机器时所需额外支出的EMR机器管理费。

注意:EMR中实例均为EC2实例,EMR按需实例的费用为EC2实例单价(左侧)+EMR服务费(右侧)。

以下为是我司常用机型的费用对比(以新加坡区域为例):

机型 每小时费用/USD vcore数 内存 核时费
r5.xlarge 0.304 4 32GiB 0.07600
r5.2xlarge 0.608 8 64GiB 0.07600
r5.4xlarge 1.216 16 128GiB 0.07600
r5.8xlarge 2.432 32 256GiB 0.07600
r5.12xlarge 3.648 48 384GiB 0.07600
r5.16xlarge 4.864 64 512GiB 0.07600
r5.24xlarge 7.296 96 768GiB 0.07600
m5.xlarge 0.24 4 16GiB 0.06000
m5.2xlarge 0.48 8 32GiB 0.06000
m5.4xlarge 0.96 16 64GiB 0.06000
m5.8xlarge 1.92 32 128GiB 0.06000
m5.12xlarge 2.88 48 192GiB 0.06000
m5.16xlarge 3.84 64 256GiB 0.06000
m5.24xlarge 5.76 96 384GiB 0.06000
m4.xlarge 0.25 4 16GiB 0.06250
m4.2xlarge 0.5 8 32GiB 0.06250
m4.4xlarge 1 16 64GiB 0.06250
m4.10xlarge 2.5 40 160GiB 0.06250
m4.16xlarge 4 64 256GiB 0.06250
  • 使用竞价机型

EMR的 Spot 实例费用的价格单如链接

注意:价格会变动。

以m5系列机型进行分析,该系列机器的核时费如下:

实例类型 m5系列机型 每小时费用/USD vcore数 内存 核时费

按需

On-Demand

m5.xlarge 0.24 4 16GiB 0.06000
m5.2xlarge 0.48 8 32GiB 0.06000
m5.4xlarge 0.96 16 64GiB 0.06000
m5.8xlarge 1.92 32 128GiB 0.06000
m5.12xlarge 2.88 48 192GiB 0.06000
m5.16xlarge 3.84 64 256GiB 0.06000
m5.24xlarge 5.76 96 384GiB 0.06000

竞价

Spot

m5.xlarge 0.0654 4 16GiB 0.01635
m5.2xlarge 0.1318 8 32GiB 0.01648
m5.4xlarge 0.2827 16 64GiB 0.01767
m5.8xlarge 0.5469 32 128GiB 0.01709
m5.12xlarge 0.7872 48 192GiB 0.01640
m5.16xlarge 1.0464 64 256GiB 0.01635
m5.24xlarge 1.5696 96 384GiB 0.01635

可见

  • Spot 机型的核时费远远低于按需机型;
  • Spot 机型的中间机型(4x, 8x)的核时费比其他机型的都要贵,该机型非常受市场欢迎导致价格上涨。

根据上表,我们得出以下结论:

  • 尽可能使用 Spot 型实例;
  • 在动态扩缩容中配置优先使用大机型(16x,24x)。

但是,使用 Spot 实例存在几个问题:

  • Spot 实例会被亚马逊云科技强制回收。

Spot 实例是亚马逊云科技服务中的可用空闲计算容量。与按需实例的价格相比,这类实例可提供超低折扣。当供需发生变化,EC2 需要更多容量时,那么亚马逊云科技可能会回收 Spot 实例的资源,而运行在被强制回收的实例中的作业则会运行失败,从而造成作业重试而增加运行成本和作业延迟风险。

  • Spot 实例数量有限。

Spot机型价格优惠,但单个区域,单个可用区内Spot资源仍是有限的。当特定某种Spot实例没有资源时,该实例组会出现长时间处于请求资源状态而一直没有扩容成功,这样会导致作业没有足够资源运行。为了避免这种情况,我们设置了多组实例组以申请不同的Spot实例类型,这样就能保证大部分情况都会获得足够的Spot实例。而且我们还配置了按需机型,若大部分 Spot 实例组都没有成功获得,则会触发按需机型实例组的资源请求。

如前面架构图所示,为了保证在作业高峰期间能获取到所需的机型,我们还配置了多个可用区(可以简单理解为机房),以分散作业运行所在位置。亚马逊云科技在新加坡区域提供了3个可用区,不同的可用区 Spot 实例的数量相差较大,最好跟亚马逊云科技的支持专员进行事先沟通。较好的一个方案是在3个可用区都建立集群,然后进行任务路由,充分利用各区的的 Spot 实例。

  • 为按需机型购买Saving Plan

Savings Plan(SP)是在承诺量合约上得到的计费优惠,具体介绍参考文档

SP类似于最低消费,保证EC2实例等计算资源使用费用维持在一定水平以上并承诺一定期限购买就能享有一定折扣。此优惠强烈建议联系您的亚马逊云科技企业级支持客户技术经理来进行规划。目前我司的SP覆盖率已达到80%,这是为了避免如果我们后续减少按需实例类型时造成浪费而配置的比例。

2.3 减少EMR管理费

对于EMR服务费,可以见官方费用链接。我们通过合理设置机型,配置动态扩缩容等策略来优化管理费。

 

  • 使用大机型取代多台小机型

对于同一系列的实例来说,核时费是相同的,但是加上服务费后,综合核时费则会有明显差别。

以m5系列机型为例进行分析,该系列机器的综合核时费如下:

可见,加上管理费后,大机型的综合核时费实际上比其他机型的要低很多,所以我们应该尽可能的使用大机型。

  • 动态扩缩容

由于我们的作业会出现明显的高峰期和低谷期,两者运算资源使用量相差近40倍,为了减少低谷期的费用支出,我们只维持了少量按需机型以保证日常使用时的资源。

下图为我们其中一个Spark-Hive的EMR集群近2天的集群总节点数的示意:

对于扩缩容策略的配置,经过多次尝试后,我们的最佳实践是仅使用ContainerPending这项指标。下图为上图对应的EMR集群的控制台ContainerPending监控指标。

我们可以通过ContainerPending指标来判定区分业务高峰和次高峰。这样次高峰时扩容条件只会触发部分实例组扩容,避免一遇到需要资源不足就直接扩容所有实例组。

关于EMR自动扩缩容的策略,可以参照此网址

扩缩容策略存在3个注意点。

逻辑1:所有条件中只会触发其中一条

逻辑2:触发条件后,只有执行完了才会进行下一次判断

逻辑3:所有条件中优先触发保留节点数最大的规则

根据以上规则,我们重点优化了以前配置的缩容策略,因为缩容策略中总是只会按最小缩容实例数进行缩容,所以之前会出现业务高峰过后缩容很慢的情况。目前使得集群利用率从不到50%增加到65%以上。

2.4 减少集群数量

  • 删除小集群

在一开始创建集群时,为每一个服务都创建了单独的集群,这些集群有以下问题:

  • 集群利用率不高
    • 不同业务对集群的利用率不相同,存在业务集群使用率不高,甚至集群长时间闲置,造成资源浪费;
    • 高可用EMR集群中Master节点为3个,而这节点并不能作为运算资源,大多数情况下是闲置的。
  • 为了节省成本而创建了单Master集群
    • 单Master节点存在高风险,如果该节点进行维护或者重启,会导致整个集群服务不可用。

为了解决以上问题,我们做了以下两件事:

1,只提供三个大集群。我们将小集群和业务量小的集群都回收并且让业务仅使用指定的几个集群。因为EMR的自动扩缩容策略,能保证作业量激增的情况下能自动启动大量节点,以保证运算资源。

2,打上Core节点标签。我们还配置了Core节点标签,让Core节点只运行AppMaster(AM),这样就能保证作业运行高峰期间每一个作业都能成功启动AM,减少AppsPending的情况,提前向集群提出扩容要求,提前扩容,从而增加整体作业运行速度。而作业运行数的最大容量就是Core实例组中的总vCore数,我们可以根据作业峰值数来对Core节点数进行调整。

EMR集群在销毁后是无法恢复的。所以在销毁集群时,一定要倍加小心。为了避免对业务的作业产生影响,我们总结出以下流程:

  1. 编写脚本捕获与Master节点建立连接(ESTABLISHED)的IP。

其中需要监控的进程有:

  • NameNode
  • HiveMetaStore
  • HistoryServer
  • JobHistoryServer
  • HiveServer2
  1. 要求接入的IP所属业务修改配置,不再连接到要销毁的集群中;
  2. 分析hiveserver2日志,排查接入过来但没有成功连接的IP;
  3. 分析HiveMetaStore日志,排查接入过来但没有成功连接的IP;
  4. 分析Hdfs审计日志,排查具体访问了该集群hdfs系统的文件,再找到对应业务进行整改;
  5. 停止集群告警;
  6. 停止服务,如有业务反馈报错则重新开启服务;
  7. 修改安全组,不让任何机器访问该集群,如有业务反馈报错则重新开启服务;
  8. 在EMR控制台操作销毁集群。
  • 减少实时作业集群Core节点数

我们实时作业集群(运行flink任务)在一开始创建时,并没有预想到业务量的增长速度如此之快,所以当时选择的Core节点的内存和EBS卷都配置得过小并不适合运行实时任务,导致了这些节点的闲置。

但而随着业务量增加,集群负载变高,而销毁老集群再重新创建新集群的话对业务影响非常大,所以我们决定通过手动调整Core节点配置来减少Core节点数量。

1,增加任务吞吐。首先集群配置Core节点标签,让Core节点只运行AM。还通过优化作业配置,减少Job Manager的内存使用,从而减少对Core节点资源消耗,增加单实例其吞吐。

2,优化HDFS服务构成。同时由于Core实例组还承担了提供HDFS服务的角色,而Core实例的费用远比EBS卷的费用高,我们通过在现有节点上手动添加EBS卷,增加了HDFS的容量后,进一步降低了对Core实例的需求量。

通过以上措施,我们最终减少了76%的实时作业EMR集群的Core节点数量,而节点利用率如下:

  • HDFS使用率:84%
  • 内存使用率:75%
  • vCore使用率:24%

注:已检查过Core节点的负载,CPU的真实负载都低于10%。由于该集群使用的是内存容量调度,所以vCore使用率在部分场景下会超过100%,这是正常现象。

2.5 及时回收 EC2 实例

因历史业务变化的等原因,我们会定期检查账单内EC2实例存在的合理性,及时排查出无人使用的机器,并做安全下线处理。

目前下线实例的流程为:

1、停止实例上所有的服务;

2、通过修改机器的安全组,禁止所有业务访问该机器,如果出现业务发生报错的情况,则恢复该机器;

3、几天后再彻底下线实例。

3.存储层(S3/EBS)优化

我们在亚马逊云科技上有PB级数据湖(S3),存储上的成本大头主要是 S3 和 EBS。

3.1调整集群EBS卷

由于在配置EMR实例组的时候,每个实例都会根据配置来添加EBS卷。我们一开始认为EBS卷的费用并不高所以没有太多的关注,但是如果拉起大量小机型的时候,EBS卷的数量也会同时激增,从而导致费用激增。

为了避免再次发生这种现象,我们停止在较小实例上配置过大的EBS卷(例如m5.xlarge实例+3T SSD硬盘)。

此外,根据作业运行经验,由于过小的EBS卷可能导致任务失败,我们调整了集群中实例的EBS卷大小,将小于2T的实例组所配EBS全部改成2T,以提高作业运行速度从而减少运行成本。

3.2 S3桶费用构成

我们通过Amazon Quicksight分析S3合计费用构成,根据桶名进行分组,结果如下图。

可以观察到大数据业务的S3费用主要是来自4个桶,然后再分别对这些桶进行费用分析。

其中一个桶的费用构成如下:

目前根据账单项目可以看到EMR费用由以下部分构成

  • S3标准储存类费用(S3 Standard)
  • Get请求费
  • PUT/COPY/POST/LIST 请求费
  • 文件存储清单管理费(Inventory)
  • 存储类分析费用(Storage Analytics)

其中:

S3标准储存类费用:目前我们在S3中存储的都是S3标准类,所以只有这储存类的费用;

请求费用:对S3桶内对象进行操作时都会产生请求,会根据请求类型收费;

文件储存费和存储类分析:这两笔费用比较少,因为是根据文件数收费的,我司解决了小文件的问题后,这笔费用基本可以忽略不计。

注:关于S3桶费用明细参考官方文档

对此,我们可得出优化的方向:

  • 降低S3标准储存类储存费用
    • 配置数据生命周期
    • 将冷数据从标准存储转为更便宜的存储类型
    • 使用S3智能分层
  • 减少请求费用
    • 排查不合理的大表扫描作业

3.3 降低S3标准储存类储存费用

  • 配置生命周期
    • 内部管理平台

在大数据场景中,部分数据是仅保存几天或几个月。对于这部分数据,我们在内部的数据资产管理平台中创建了库表生命周期管理工具,能让业务方根据需求定期删除生命周期之外的数据,保持数据量的稳定,避免存储不需要的数据。

    • S3桶生命周期

对于非业务数据(例如EMR集群的日志和S3桶的各种审计日志),我们可以通过S3的控制台,配置各种数据清理规则,防止日积月累的无用数据产生成本。一个非常典型且重要的配置是清理未完成文件(如S3分段上传的文件块),仅此一项就节省数万美金/月。

    • S3桶对象存储清单

为了监控S3桶的存储量的变化,我们还开启了S3控制台中的库存配置,每天生成一张桶里的数据清单。这样就能在存储费用增加的时候,对数据变化进行详细排查。通过使用亚马逊云科技提供的Athena交互式查询工具,我们可以编写SQL,对文件名进行正则匹配,比较增长前和增长后数据量变化最大的路径,再联系对应业务方对该数据配置生命周期或者检查数据量是否增长异常。

    • 关闭版本控制

某次有业务或者运维不知为什么开启了S3桶的版本控制,这功能是S3桶为了避免误删数据而做的类似回收站的功能,被删除的文件会被标记成删除,这部分文件无法通过外部进行访问,仅能在S3桶控制台中进行查看。所以一开始我们内部库表管理平台并没发现数据量增加。但是通过费用账单发现费用在不停增长到原来的两倍。经过排查后才发现这是由于该桶被开启了版本控制,我们内部配置的生命周期并没删除S3桶中的数据,而只是在S3桶中标记成删除而已,这部分数据依旧会按普通数据进行收费。

最后我们通过关闭版本控制,并且在生命周期中配置删除带有删除标记的文件后,存储量才减少50%至原来的水平。但是关闭版本控制需要有对应的高可用和防误删机制。

    • 排查僵尸表

存在部分库表由于人事变动,交接遗留或者其他原因导致长时间没有进行维护或者使用,而这部分库表就作为僵尸表储存在S3桶中。

由于S3桶并没有给业务提供公开的文件最后访问时间的查询方法,所以只能自己进行分析。我们额外开启了S3桶的访问审计日志,将访问审计日志和文件审计日志一同进行分析,通过编写脚本和SQL就能创建一个记录S3桶文件的最后访问日期的库表,以此信息推动业务进行干预。

    • 任务失败的遗留文件

在Spark或者Hive执行任务时,中途报错或者终止SQL会导致中间数据遗留在S3桶中,这部分文件可以通过S3文件审计日志来进行排查,而删除方法可以通过S3中对应路径配置生命周期进行删除或者编写脚本,将文件生成日期大于指定天数的文件删除。需要注意的是,避免将正在执行的作业临时文件进行删除。

  • 将数据转冷存

实际上,我们目前储存的S3标准类是在整个S3储存类中储存费用最贵的,下表为从官网中整理出的费用清单(新加坡区域):

存储类 存储类(英文原文) 存储成本(GB*$/天)
S3 标准 S3   Standard 0.0250
不频繁访问层 Infrequent   Access 0.0138
GIR Glacier Instant Retrieval 0.0050
GFR Glacier Flexible Retrieval 0.0045
GDA Glacier Deep Archive 0.0020

其中GFR和GDA是储存费用虽然很低,但是需要将数据从冷存进行恢复后才能进行访问,如果要使用这两种储存类型,则需要修改引擎以匹配这些数据的恢复流程。

因此目前我司仅计划使用前三个存储类(S3标准,IA,GIR),因为这三类是不需要修改现有引擎,而且经过测试,使用Spark引擎对这三中存储类的数据查询(增,删,查)速度基本一致,使用的核时数和内存数也基本一致。此外,还测试过当一个库表文件中存在多个储存类时,也能正常进行查询。

注意:不频繁访问层的最低储存时间为30天,即使不满30天即删除,移动文件或再次修改储存类都会收取30天的储存费用,而GIR的最低储存时间为90天。所以使用这种储存类的数据需要提前与业务确认。

对于前三类存储类,有额外的费用需要进行比较

其中,生命周期转换请求:在S3控制台中通过配置生命周期,将文件修改成对应存储类时所需的费用。相对的,如果不通过生命周期,而是通过S3控制台直接修改储存类,则需要支付其他请求费用。

所以,S3储存的一天费用为:

S3储存的一天费用=S3储存量×储存成本+一天总PUT等请求数/1000×请求费用+一天总GET等请求数/1000×请求费用+一天总掃描数据量×读取成本

可以结合审计日志,通过正则匹配对应路径,算出一天各种请求的次数,然后根据请求总的扫描数据量(Bytes Sent)求出该库表在一天内的费用,再根据下表进行对比,观察是哪种储存类的费用最低

储存文件的大小 请求PUT等次数 请求GET等次数 扫描数据成本
GB 次数 次数 GB
分类 一天费用
S3 标准 =GB×0.025+次数/1000×0.005+次数/1000×0.0004+GB×0
不频繁访问层 =GB×0.0138+次数/1000×0.01+次数/1000×0.001+GB×0.01
GIR =GB×0.005+次数/1000×0.02+次数/1000×0.01+GB×0.03
  • 使用S3智能分层

S3智能分层就相当于使用S3的托管服务,自动将数据转移到对应的储存费用更低的储存类中。此方法节省人力成本,而且适用场景更广。目前主要是推动这个存储类给业务使用。关于Amazon S3 智能分层可参考官方文档

但是需要注意的是,S3智能分层中,文件只要被访问了,就会将文件的存储类改成S3标准层。因此,S3智能分层仅适用于文件长时间不访问的情况。

S3智能分层需要收取如下费用(新加坡区域):

存储级别(中文) 存储级别(英文) 存储成本(GB*$/天)
S3 标准 Frequent Access Tier 0.0250
不频繁访问 Infrequent Access Tier 0.0138
归档即时访问层 Archive Instant  Access Tier 0.0050
归档访问层(可选) Archive Access Tier 0.0045
深度存档访问层(可选) Deep Archive Access Tier 0.0020

其中可选的两个存储层的费用虽然很低,但是查询时间需要3小时至12小时,如果要使用这两种储存类型,则需要修改引擎的作业超时时间。

因此目前我司仅计划使用前三个存储类,因为这三类不需要修改现有引擎。

而如果使用S3智能分层,需要收取以下额外费用:

相对于普通的S3储存类,S3智能分层还额外收取了监控费。

所以,S3智能分层储存的一天费用为:

S3储存的一天费用=S3储存量×储存成本+一天总PUT等请求数/1000×请求费用+一天总GET等请求数/1000×请求费用+文件数/1000/月天数×监控费

而为了排查出哪些数据适合使用S3智能分层,则需要使用记录S3桶文件的最后访问日期的库表,当生成了这个库表后,就能进一步推动这个S3智能分层的使用。

目前我们已经完成技术验证,正在推动业务逐步应用。

  • 建议删除文件的时期

我们曾经发现过2月份存储费用激增10%的情况,当时对数据量进行排查后,发现数据量并没有增长10%。

在同亚马逊云科技技术支持讨论时,怀疑可能存在大量写入后又进行删除操作,导致了两天最终记录下的储存量没有太大变化。但是在后台指标中也并没有发现大量写入删除的情况。

最终了解到由于S3桶的存储费是按月度用量进行收费的。比如新加坡区域 10TB数据的标准存储1,2两个月都是收费$256。但因为2月(28天)与1月(31天)的天数相比少了10%,所以2月单日储存费用会比1月增加10%。

因此,在做年度的数据排查和删除时,建议考虑月份天数差异对单日费用的影响。

3.4 减少请求费用

  • 排查不合理的大表扫描作业

我们发现,其中有个桶的GET请求费用占总费用的比例非常高,有时请求费用甚至等于储存费用。对此我们进行了仔细排查。

我们先通过S3桶的访问审计日志排查出访问量最大的库表,然后再分析出其中一天每一分钟的请求次数,最终得到下图。可以清楚看出请求激增的时间段。

然后再根据这个时间范围,去后台系统查询在这个时间段耗费资源最严重的作业。最后,我们排查出2个作业,两个作业一共扫描了10万个以上分区。

我们联系负责这两个作业的业务后,业务反馈其中一个作业已经没有下游任务,并将作业停止了,而另一个作业我们通过优化SQL,将运行成本减少了98.51%,运行时间减少了81.78%。最终平均请求费用降为原本的37.5%,成效显著。

  • S3桶的SQL查询请求费用的分析

我们曾经粗略地分析了一下S3中以下2种情况下的请求的个数。

  1. 手动修改文件储存类的请求分析。

分析这个是为了对比生命周期和智能分层中的请求费用。我们首先手动修改一个文件的储存类从S3标准到不频繁访问层,再从S3桶的访问审计日志中统计到以下请求数据

key 请求 请求个数
part-00000 PUT 17
POST 2
HEAD 3
GET 4
part-00190 PUT 4
POST 2
HEAD 3
GET 4

其中PUT请求中所有objectsize之和与文件的大小一致,可以确认PUT请求个数为文件除以16M的向上取整的个数,而其他请求(POST、HEAD、GET)都一致。根据上面的分析,可以得到下面的公式:

优化后得

而通过生命周期转移的请求费是每 1000 个请求 0.01$,但我们还没有测试过除了生命周期请求费外,还有没有其他额外的请求,因此还没判断出哪个方法更节省成本。

  1. 查询请求分析。

对于一次简单的limit 1的SQL:select * from 表 where 表分区 limit 1;

会有以下请求:

请求总数 5
*无效请求数 3
**有效请求数 2
GET请求 1
HEAD请求 1

*无效访问数包括: 响应码404 和 _$folder$文件的请求

**有效访问数 = 请求总数 – 无效访问数

  • 【请求总数】中存在的无效请求
    • 响应码404:是对文件夹路径的请求,对于S3来说,由于S3是面向对象储存的,里面储存的文件都是仅包括键值对,并没有所谓的文件夹,因此扫描到该路径时会返回响应码404,errorcode 为 “NoSuchKey”。对此文件夹发起的请求次数通常为1~2次HEAD请求。
    • 对_$folder$文件的请求,至少HEAD请求1次,没有GET请求。
  • 每次访问一个数据文件时,都会先有一次HEAD请求,再来GET请求
  • 存在一个GET请求,bytessent 字段是有数据的,说明SQL中就扫描了S3桶中这部分数据。

之后通过分析扫描全表的请求,相关数据如下:

spark中的task数 1494
S3中的文件总数 1494
请求总数 3076
*无效访问数 14
**有效访问数 3062
GET请求 1547
HEAD请求 1515

*无效访问数包括 响应码404 和 _$folder$文件的请求

**有效访问数 = 请求总数 – 无效访问数

  • 分析每次bytessent字段,其中【bytessent】=【objectsize】的GET请求数等于文件数
  • 存在少量【bytessent】小于【objectsize】的请求,猜测是由于网络问题导致传输中断,然后再重新请求,或是在SQL引擎中启动额外的task来扫描同一个文件,最后其中一个扫描完成后自动终止另一个task的扫描请求

结论:

对于S3桶的库表数据,数据文件的多少会对进行一次扫描的请求次数造成直接影响,若要减少GET请求费用,可以通过解决小文件问题来解决问题。

另外,$folder$文件也会对请求造成影响,而且还会收取S3的文件管理费和监控费。

4. 网络层(DTO)优化

 4.1 跨区流量费

由于新加坡有3个可用区,部分服务跨可用区数据传输是需要收取额外的跨可用区流量费的,具体收费规则见官网链接

我司配置了不同的集群来执行不同类型的作业,其中实时作业集群的跨可用区流量费(InterAZ Transfer)相对于其他集群来说是比较高的。我们关注到这块费用后,推动相关团队对埋点数据上报位置进行了修改,最大可能的减少了数据传输后,跨区流量费减少了88.1%。

4.2 S3终端节点

默认情况下,应用程序和客户端对S3的访问是通过互联网进行。其中公有子网中的实例到 S3 的流量先走到互联网网关,然后才路由到服务。私有子网中的实例无法直接将流量发送到 S3,还要经过一层 NAT。

注意为所有VPC子网配置S3终端节点,确保网络路由内网并节省对应费用,尤其是新开区域,初始化网络的时候。

5.  总结

5.1 成效

通过上述方法进行优化后,两大成效:

  • 持续降本增效:用更少的钱,做了更多的事,在 30% 的业务增量下,仍然为公司一年节省约千万人民币级别的费用。
  • 持续促进创新: 通过数据驱动,主动支持,敏捷迭代,有力地支撑业务方持续挖掘和发挥数据价值,得到了业务方极大的认可,收获非常多业务方对 SRE团队的正向反馈。

其中各项的节省费用占比:

  • 优化 EMR/EC2 费用:约60%
  • 优化S3/EBS费用:约35%
  • 优化网络流量费用:5%

从历史数据统计,我们的主力EMR集群的 Spot 机型占比已经稳定保持在85%以上,根据亚马逊云科技支持团队的评估,已经属于业界算力成本优化的极致了。

大量使用 Spot 不仅仅是节省成本,同时充分利用 亚马逊云科技 云中未使用的 EC2 容量,大大提高云的整体利用率并减少未使用资源对可持续性的影响。

5.2 经验和教训

 服务稳定优先于成本优化

在对EMR扩缩容策略的不断验证的过程中,我们一度过于激进,对于调整方案的效果没有做详细推演,对亚马逊云科技产品特性的了解并不到位,导致出现了两次线上故障,且造成了费用的增加,幸好及时观察账单进行了快速的回滚。

成本优化会给SRE团队带来较多的成就感,有可能会导致对服务稳定性的忽略。SRE团队必须牢记自己的使命,所有的工作都必须建立在 Sustainability(可持续性)这个的基础上。业务持续稳定的运行是目标,Reduce成本优化只是手段,不能本末倒置。

要有追求极致的精神

可以看出,有些成本优化的措施比较容易想到,但由于亚马逊云科技越来越庞大的产品体系和真实的业务架构的复杂性,要取得更深入的优化效果,需要钻研较为深入才行。以S3桶请求费用的降低为例,我们一度陆续持续排查了大半年才把其中的细节调研清楚;在提升Spot机型利用率的方面,没有现成的完全适合我司独特的业务场景的经验借鉴,我们为了验证合适的扩缩容策略,选取合适的锚定指标,前后也是几个月的不断对比验证才得以成功。

6. 未来的努力方向

未来,我们将继续秉持 OPPO 可持续发展理念,扩大使用更绿色环保的算力(如 Graviton),持续打磨技术架构和数据流程。

6.1 持续演进基础架构

SRE 团队观察到业界已经开始逐步采纳基于 k8s 的作业调度,我们已经开始验证 EMR on EKS:

  • 一方面,提前做好技术储备,构建好相应的能力,一旦业务方有需要时,可以快速交付。
  • 另一方面,现在我们在 EMR on EC2上的成本优化可以算是做到了行业极致,后续希望借助 EKS 上的 EMR,利用更快的容器拉起速度,更短的节点准备时间等特性,进一步减少业务成本。

此外,我们计划全面应用S3智能存储/分层存储,持续优化存储成本。

6.2 持续优化数据流程

过去我们主要是通过分析过往作业数据,“洞察历史”(DataOps),后续我们希望进一步引入机器学习能力“智策未来”(AIOps):

  • 首先,借助 Amazon Forecast 等机器学习能力,快速导入 CUR 等数据集,提前预判,从容管控成本。
  • 其次,现在 EMR 上有很多作业都是用于机器学习的特征工程,生成的特征用于下游的训练任务,例如SageMaker。我们也将从机器学习的视角探索现在采集到的作业,CUR等信息,从更深层次的了解业务流程,进而更好的支撑业务需求。
  • 最后,SRE 团队逐步形成一定的机器学习能力,利用 AI 辅助运营,减少人工干预,从另一个角度提升可持续性。

7. 致谢

在这个成本优化的项目过程中,我们得到了亚马逊云科技客户团队的主动服务和大力支持,他们给了我们很多架构优化和成本优化的建议和选项,帮助我们OPPO SRE 团队有效的实现了成本优化的目标,在此予以特别的感谢。同时,成本优化项目也得到了OPPO内部团队领导和兄弟团队同事的大力支持,在此一并表达感谢。

8.作者介绍

Huan Yang

OPPO 大数据基础平台服务&SRE负责人,毕业于华中科技大学,曾供职于京东科技,有较为丰富的大数据任务开发和性能优化经验,同时对产品体验和成本优化有较多兴趣。

Weier Dai

OPPO 大数据基础平台SRE工程师,毕业于西安交通大学,专项负责OPPO大数据基础平台海外部分的成本优化工作。

Naihong Song

OPPO 大数据基础平台高级SRE工程师,负责OPPO大数据基础平台海外部分的稳定性和成本优化工作。

Bin Long

亚马逊云科技解决方案架构师,负责协助客户业务系统上云的解决方案架构设计和咨询,现致力于容器和机器学习相关领域的研究。

Neo Wang

Neo 是一位亚马逊云科技技术客户经理。他致力于让客户更好的了解,规划和使用 亚马逊云科技 服务以实现事业的成功。