抖音技术能力大揭密!钜惠大礼、深度体验,尽在火山引擎增长沙龙,就等你来! 立即报名>> 了解详情
写点什么

全球 6 大数据中心,日均 10 亿日志场景下的高可用实践

2018 年 9 月 26 日

开篇语

近几年互联网服务安全事故的频发,使得越来越多的企业及开发者意识到数据备份、灾备等重要性,高可用性、高容灾性及高可扩展性的系统和架构建设工作也被更多地置于重心。

在这个过程中,基于公有云提供的基础设施实现高可用已成为多数技术团队的选择。

而面对跨区域 + 高可用需求时,许多开发者却犯了难,一方面业务场景的不同对架构设计提出了不尽相同的需求,基本上没有可完全复制的架构模版;另一方面是纳入考虑的因素在不断增多,数据延迟、成本开销、物理隔离、快速的恢复能力……如何能在加法的基础上做好减法,对技术团队创新能力提出了更高要求。

对此,InfoQ 专访了 FreeWheel 架构师张磊及 FreeWheel 首席工程师姜冰,探讨在服务全球 6 个数据中心,日均产生近 10 亿广告投放展示日志的场景下,做好跨区域高可用的实践之道。

跨区域、高可用性实践背景

数据处理平台提出的多维挑战

作为美国 Comcast 旗下领先的视频广告管理和投放平台,FreeWheel 的数据来自于全球 6 大数据中心(美国东西海岸各两个、欧洲两个),每天产生 10 亿左右的广告投放展示日志,新增超过 3TB 的数据,并且有至少 18 个月的数据可以随时满足查询寻求。

在数据应用对实时性和可靠性要求逐渐增加的情况下, FreeWheel 根据其自身数据特点和应用需求,采用了一套以 Kafka,Hadoop 和 HBase 为核心的 Lambda 处理架构。

其中,各个数据中心的广告服务器实时地将广告数据传输到本地 Kafka 集群。中心化的 Kafka MirrorMaker 将多数据中心的数据聚集到一个全局的 Kafka 集群。流式处理框架会从全局 Kafka 集群消费数据,处理之后一方面写回 Kafka(为下游的各类实时应用服务);一方面写入 HBase,并由 Hadoop 离线作业将 HBase 的内容聚合转换成 Parquet 文件写入 HDFS。构建于 Presto 之上的 OLAP 服务会同时查询 HBase 和 HDFS,对外提供数据的实时或批量查询(整体架构见下图)。

FreeWheel 数据处理系统架构图

FreeWheel 部署的这一套数据处理系统,很好地实现了预期的设计目标。但过往几年里,随着数据量的不断增长和业务变化的需求,这种模式面临了如下挑战:

  1. 可扩展性:越来越多的数据产品接入到新的数据平台,对数据处理和查询服务的扩展性提出了严苛的要求。而在自建的数据中心,受限于规划和整体容量,很难根据需求灵活地扩展。 同时,在“超级碗”这样大型赛事的直播带来流量瞬时波动的场景下,传统的数据中心也很难满足对容量的弹性需求。

  2. 高可用性:虽然像 Hadoop 这样的大数据基础设施本身可以保证一定程度的高可用性,但在遇到数据中心整体性故障时,依然会对服务造成影响。

  3. 开发和测试效率:大数据平台开发和测试中,基于真实环境的集成测试和性能测试可以覆盖单元测试和回归测试的盲区,这需要经常启停一些基础组件甚至整套端到端服务。但在自有数据中心里,受到资源限制,很难做到及时满足需求,因而也降低了开发和测试的效率。

理论上,上述挑战中的一部分可通过在另一个自建数据中心里再部署一套数据处理系统解决或缓解,但考虑到规划、扩容所需时长以及问题根治性等因素,在 2016 年底,FreeWheel 决定与 AWS 合作,将数据平台和数据处理系统部署到云端。

选型过程并不复杂,FreeWheel 主要从成熟程度、数据监管、可用区(AZ)数以及原生服务的数量与广度等方面考量,最终选择了 AWS 作为云服务商。

基于 AWS 原生服务的使用权衡

整体上,FreeWheel 在 AWS 上也部署了一套 Kafka MirrorMaker,同步所有数据中心的数据,再将数据处理平台基本原样搬到了 AWS 上。

但如何权衡是直接使用像 Kinesis、DynamoDB 这样的 AWS 原生服务,还是自己维护 Kafka、HBase 等基础设施? FreeWheel 也有一些思考。

张磊对此总结了两点。一是从平台需求出发。AWS 许多原生服务在某种程度上的确能带来开发和维护成本的降低,但对于基础数据平台这类数据量极其庞大并且对稳定性要求很高的业务, AWS 的原生服务能不能满足需求,能满足需求的情况下成本是不是可控,这些都会是最终影响选型的因素。二是需要考虑开发者自身对技术的把控。AWS 的原生服务很多时候对使用者来说还是黑盒。当大家需要花大量时间去了解这些服务的内部运作原理,限制和故障处理时,不一定能降低时间和运维成本。

涉及到具体权衡与改造,姜冰也举例讲解了何时该选择自身维护:

以 AWS 原生服务 Amazon EMR 和 Amazon Kinesis 为例,映射到 FreeWheel 的数据处理系统中相应的是 Hadoop Cluster 和 Kafka。基于 FreeWheel 以 7*24 小时流计算为主的业务类型,如果直接使用 EMR 及 Kinesis,将面临如下问题:

  • 原生服务开放程度较弱,因而开发者缺乏更多的机会维护和管理自身集群。例如从对外兼容性上看,Kafka 下游接了多样的开源解决方案,与 Spark、Flink 等有天然集成,但 Kinesis 是闭源的托管服务,下游集成由 AWS 主导,日志记录的更新和变化将受制于 AWS 内部研发;

  • EMR 适合批处理的工作模式,在全天候不间断的运行状态下,基于 AWS 基础计算和存储资源自建的 Hadoop 集群能够提供更好的可用性,从而更好地应对流处理场景。

在上述场景下,FreeWheel 并没有主动选择 EMR 或 Kinesis 原生服务,而是从成本、性能、开放程度、规模化和容错管理等维度与自身维护做了对比实践。但张磊也提到,在一般的使用场景下,对于 AWS 的原生服务,比如 RDS,Athena 等,FreeWheel 会鼓励并尽可能地使用, 这样才能更有效地满足高可用需求,并降低总体开发维护成本。

截至目前,经过测试和调整,FreeWheel 已逐步把面向客户的的所有产品都迁移到 AWS 环境中,目前自有数据中心里只有极少数对内的服务在运行。而最终它们也都会迁移到 AWS 环境中。

高可用实践需求及实现方案解析

高可用性设计目标

一个完整的全系统高可用性设计通常会涉及五大层面:基础设施、服务器、数据、应用程序、系统服务。

在基础设施层,FreeWheel 更多的是将 AWS 视为一项服务。虽然 AWS 会充分保证其基础设施的稳定性,FreeWheel 还是会在所有的服务都可能出问题这一假设下指导设计。服务器层也是如此。

数据层,如果该数据存在于 FreeWheel 自身系统,其通常会借助于像 Kafka、HBase 的天然多副本能力,即设置多个副本提供数据容灾。

应用程序层,FreeWheel 一般会将它做到无状态,从而更容易实现快速恢复和高可用,无论是水平扩展还是垂直扩展都更方便。

服务层,FreeWheel 采用的是 Failover(故障转移)机制。即应用服务器设置多台,彼此之间通过心跳联系。数据库、缓存、应用服务器等任何位置出现瓶颈就只需增加处理能力。目前,对于服务器的对等可替换性,主要有三种类型:Active-Active(双主)、Active-Standby(主备)以及单 Active。

  • 在双主模式下,FreeWheel 通常会通过先绑定 Amazon ELB,再注册到 Amazon Route 53 的方式,从而实现自动对应用无感知访问。

  • 对于主备模式,FreeWheel 通常会将相应的信息注册到 ZooKeeper,由 ZooKeeper 实现 Failover 的分布式协调服务,从而实现 Master 的选举和对外服务发现。

  • 对于单主模式,一般是一些离线任务,FreeWheel 会将其绑定在 ASG(Auto Scaling Group)中,出现问题时可以自动扩展重试。

高可用的整体实现方案

无论是跨 Region(区域)还是跨 AZ(可用区),数据交换都将产生一定的成本开销。面对着庞大数据量和跨区域 / 可用区间的数据延迟,在 AWS 多可用区实践过程中,FreeWheel 针对数据平台对于高可用的需求及 AWS 自身高可用实践经验,采用了多种定制方式——主要对 Hadoop-HBase、Kafka、Zookeeper 及数据处理部分实现了不同的高可用解决方案。

1. Hadoop-HBase多可用区

在设计之初,FreeWheel 就试图平衡了成本、性能和可用性之间的关系。但是类似数据库系统中的 CAP 理论,这三者很难同时得到满足。例如,AWS 上很多及其类型和存储类型都不尽相同。为了提升 HBase 性能需要采用 instance store 这类本地 SSD 存储方式,而相应的弊端也随之产生:一旦挂载这个 instance store 这个实例出现异常,相应的存储就会丢失。尤其是当其真实宿主机发生大面积故障时,可能导致数据的彻底丢失。

因此,FreeWheel 也需要对 HBase 在多个可用区上实现高可用。

对于存储模块,FreeWheel 选择两个可用区来部署,通过 HDFS Storage Policy 接口,实现数据块副本数在主可用区和次可用区的分布。 对于无状态的数据应用优先部署在与 Hadoop/HBase 主可用区同侧,并支持在次可用区快速部署。应用和数据优先同侧的策略,可以有效降低数据应用的因为跨可用区带来的数据延迟,并降低可用区之间网络传输的成本开销。借助 AWS 提供不同存储介质的 IOPS 和持久化特点,实现针对不同业务的工作负载灵活选择存储节点配置,并实现业务之间的物理隔离(原理如下图)。

其中,隔离思路主要是基于不同的工作负载选用不用的 EC2 实例或 EBS 实例。这样也可根据自身的业务特点,在 AWS 中选择不同的硬件、实例类型或 EBS 类型来满足需求。此外,FreeWheel 也可以在 AWS Hadoop 上实现一组机器的上线及下线,而且只把具有某一类标签的机器上、下线,而不影响到其他数据。

2. Kafka多可用区

Kafka Topic 内每个 Partition 有多个副本,多可用区部署,需保证在不同可用区的副本个数的划分。姜冰提到,在正常情况下每个 Partition 里可设置多个副本,如果要保证高可用,意味着需要将多个副本同时被部署到同一可用区上,但同时,这样做的弊端是无法保证可用区级别高可用,如果一个可用区宕机将导致整个 Partition 不可用。

于是,考虑到跨可用区带来的数据延迟以及成本开销,FreeWheel 针对数据应用和规模实现了不同的策略。

一种策略是,对于用于数据处理流程的 Kafka Topic,在次可用区仅部署 Partition 副本中的 Follower。应用程序和 Kafka 主可用区同侧,读写数据的流量全部在同一可用区完成,这样在主从可用之间,仅有 Leader 和 Follower 之间的网络传输开销。在主可用区发生故障时,从可用区的 Follower 切换成 Leader 对外提供服务(原理如下图)。

在这种情况下,Kafka 消费者只会在同一可用区消费,从而避免跨可用区间因网络传输带来的成本消耗,同一可用区间的延迟性也大大降低。

而对于以在线服务为主的数据,为了提供更强的高可用和更快速的恢复能力,Kafka 采用 3 可用区对等部署的方案,无差别的对外提供服务:每一个 Partition 的 Leader 和 Follower 以公平的策略随机分配到不同的可用区,在 AWS 出现可用区级别的故障时,Kafka 借助 Leader 和 Follower 之间的切换,保证服务的高可用(原理如下图)。

放在 FreeWheel 的具体业务场景中,为保证广告主预算与广告竞价间反馈回路的可用性高且延时性低,避免出现广告超量投放或投放价格与预算偏差等问题,FreeWheel 即需采用上述第二类这种解决方案。

3. Zookeeper多可用区部署方案

Zookeeper 集群是由 1 个 leader 和若干个 follower 组成,这些节点被部署到 3 个 AWS 可用区。应用通过名字注册服务将主工作服务(Active)注册到 Zookeeper。在可用区发生故障时,应用 Active/Standby 角色根据 Zookeeper 名字服务状态变化进行切换,并注册最新的 Active 服务到 Route53(原理如下图)。

4. 数据处理高可用部署方案

目前 FreeWheel DIP(Data Ingestion Pipeline)架构由两部分组成,一是流处理工作类型,二是上下游以小时为级别的批处理工作类型。

流处理消费一次来源于 Kafka,同时会和 HBase 交互,所以就流处理来说,如果能解决数据和状态高可用,其本身是属于一条无状态的数据处理流水线。反观,这也是为什么 FreeWheel 会花更多功夫在 Kafka、Hadoop-Hbase 和 Zookeeper 高可用部署上的原因,从而进一步确保流式数据处理状态和高可用。

流式处理主要通过 Hadoop YARN 部署,采用 ASG 做扩展 / 收缩,以及采用 ASG 绑定同一 YARN 队列的方式来保证高可用性。

对于批处理工作类型的解决方案,FreeWheel 也有比较好的 Failover 方案应对异常状况下的自我修复。总的来说,利用分布式的天然架构,FreeWheel 可以通过监控措施很快地对其进行恢复。

高可用实践之切换部署

因为通过对有状态数据(诸如 Kafka、HBase、Zookeeper)实现多可用区,从底层向上的各个业务可形成自我恢复的能力,即使在发生故障时,也已能在极端的情况下为用户无缝提供完整服务。

当跨可用区级别切换时,FreeWheel 更多贯彻的是 DevOps 理念,即不用专职的运维人员,通过监控和脚本自动化的工具和方式保证服务高可用。目前在 FreeWheel 内部受重视的一种模式是监控和报警的代码化,即通过相应的框架实现监控和报警,用代码做管理,而非以往那种在站点上做简单配置的方式。

对于监控和报警,FreeWheel 用到的主要工具包括 Datadog 及开源工具如 TerraForm(类似于 AWS CloudFormation)和 SaltStack 等。

Datadog 的工作方式是在每一台需要监控的服务器上运行它的 Agent。FreeWheel 主要用 Datadog 实现 EC2 级别监控,这样可以基于机器类型、用途等,分门别类对其服务进行监控,一是实现系统级别(如 CPU、内存、磁盘、网络 I/O)的相关监控,二是实现基于 应用级别的监控。

另外,TerraForm 会应对启动资源、扩展 / 回收和权限配置之类的场景,从而实现 AWS 资源配置。SaltStack 实现配置的幂等性管理,并针对机器 tag 进行分布式调用和部署检查。

当可用区级别需切换时,目标是希望能做到让用户无感知。但目前如果需从主区域切换至备用区域情况下,FreeWheel 当前的设计方案是允许有一定(分钟级别)的宕机时间。因为在一般情况下,一个区域 3 个或 3 个以上的可用区(FreeWheel 只会使用有至少 3 个可用区的区域)已经足够保证高可用性。当整个区域出现整体性故障时,允许有一定的宕机时间是综合成本和需求的整体考虑。

高可用实践收效及未来规划  

张磊在采访中提到,伴随着高可用实践,FreeWheel 也获得了业务的高弹性。对于“超级碗”及世界杯这类大型体育赛事开始时,整个架构会有更好的扩展能力应对突发流量,帮助其在 AWS 上实现高度的动态扩展性。

未来,FreeWheel 一方面会尝试将一部分系统走向容器化,比如 Data Ingestion Pipeline。当然,对于 HBase、Hadoop 如何更好地结合 K8S 或利用 Amazon EKS 等工具,FreeWheel 还需要下一阶段的调研及实验。

另一方面,针对更大范围的高可用、数据安全等问题,FreeWheel 还将持续探索怎样在平衡性能和成本的条件下多个区域提供服务和快速的灾难修复的能力。

采访嘉宾

张磊,FreeWheel 架构师,现负责公司数据平台和数据产品的整体技术把控。

姜冰,FreeWheel 首席工程师,现全面负责大数据平台的架构和研发工作。

2018 年 9 月 26 日 18:255992
用户头像

发布了 39 篇内容, 共 22.8 次阅读, 收获喜欢 130 次。

关注

评论 1 条评论

发布
用户头像
ELK体系多AZ建设非常好的文章!
2019 年 11 月 21 日 10:10
回复
没有更多了
发现更多内容

网络攻防学习笔记 Day124

穿过生命散发芬芳

9月日更 互联网安全

未来10年,5个C/C++吃香的细分领域技术

奔着腾讯去

云原生 网络安全 音视频 DPDK 虚拟化技术

Go 专栏|变量和常量的声明与赋值

AlwaysBeta

go golang golang新手 Go 语言 Go 语言从入门到实践

Go 专栏|接口 interface

AlwaysBeta

go golang golang新手 Go 语言 Go 语言从入门到实践

Go 专栏|复合数据类型:字典 map 和 结构体 struct

AlwaysBeta

go golang golang新手 Go 语言 Go 语言从入门到实践

Linux之lastlog命令

入门小站

Linux

【HTML5游戏】从敲打空格键开始

devpoint

HTML5游戏 9月日更

Java + opencv 实现图片修复(图片去水印)

张音乐

Java OpenCV 音视频 9月日更 图片去水印

(深入篇)漫游语音识别技术—带你走进语音识别技术的世界

声网Agora

深度学习 音视频 语音识别

C 语言中的 malloc、free、realloc、calloc 函数详解

村雨遥

c 9 月日更

线程同步类CyclicBarrier在性能测试集合点应用

FunTester

多线程 性能测试 线程安全 测试框架 FunTester

Linux内核四大核心框架

hanaper

Go 专栏|说说方法

AlwaysBeta

go golang golang新手 Go 语言 Go 语言从入门到实践

LeetCode刷题278-简单-第一个错误版本

ベ布小禅

9月日更

HTTP系列之:HTTP中的cookies

程序那些事

Java 网络协议 HTTP cookies

Go 专栏|基础数据类型:整数、浮点数、复数、布尔值和字符串

AlwaysBeta

go golang golang新手 Go 语言 Go 语言从入门到实践

Go 专栏|复合数据类型:数组和切片 slice

AlwaysBeta

go golang golang新手 Go 语言 Go 语言从入门到实践

在线JSON转JAVA工具

入门小站

工具

Go 专栏|函数那些事

AlwaysBeta

go golang golang新手 Go 语言 Go 语言从入门到实践

多线程知识体系01-线程池源码阅读讲解-Executor

小马哥

多线程 高并发 源码阅读 源码剖析 日更

Electron团队为什么要干掉remote模块

刘晓伦

Electron Node

Java中的变量与常量

IT蜗壳-Tango

9月日更

ShardingSphere 语句解析生成初探

源码 ShardingSphere

Go 专栏|流程控制,一网打尽

AlwaysBeta

go golang golang新手 Go 语言 Go 语言从入门到实践

【报名】飞桨中国行丨企业零门槛AI创新应用-智能制造专场

百度大脑

人工智能

从一个并发异常问题引起的想法

卢卡多多

并发编程 9 月日更

模块(二)如何设计架构

我是一只小小鸟

【Flutter 专题】58 图解 Flutter 嵌入原生 AndroidView 小尝试

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 9 月日更

链路压测中各接口性能统计

FunTester

性能测试 测试框架 测试开发 FunTester 链路测试

Go 专栏|错误处理:defer,panic 和 recover

AlwaysBeta

go golang golang新手 Go 语言 Go 语言从入门到实践

【Vue2.x 源码学习】第四十三篇 - 组件部分 - 组件相关流程总结

Brave

源码 vue2 9 月日更

Study Go: From Zero to Hero

Study Go: From Zero to Hero

全球6大数据中心,日均10亿日志场景下的高可用实践-InfoQ