背景

一面数据创立于 2014 年,是一家领先的数据智能解决方案提供商,通过解读来自电商平台和社交媒体渠道的海量数据,提供实时、全面的数据洞察。长期服务全球快消巨头(宝洁、联合利华、玛氏等),获得行业广泛认可。公司与阿里、京东、字节合作共建多个项目,旗下知乎数据专栏“数据冰山”拥有超30万粉丝。一面所属艾盛集团(Ascential)在伦敦证券交易所上市,在 120 多个国家为客户提供本地化专业服务。

公司在 2016 年线下机房部署了 CDH 集群,到 2021 年已存储和处理 PB 级的数据。公司自创立以来一直保持每年翻一番的高增长,而比业务量增长更快的是 Hadoop 集群的数据量。

在这几年间,按 1 到 2 年规划的硬件,往往因数据增长超出预期而在半年后不得不再次扩容。每次扩容周期可达到一个月,除了花费大量精力跟进行政和技术流程,业务端也不得不安排较多人日控制数据量。

为了降低运维难度,发展可持续扩张的大数据处理方案,我们从 2021 年 10 月份开始探索取代现有Hadoop 集群的方案。当时提出了这些需求:

  • 上云,弹性伸缩、灵活运维
  • 存储计算分离
  • 尽量使用开源组件,避免云厂商绑定
  • 尽量降低业务迁移工作量

最终选择的方案是使用阿里云 EMR + JuiceFS + 阿里云 OSS 来搭建存算分离的大数据平台,将云下数据中心的业务逐步迁移上云。截至目前(2022 年 7 月)整体迁移进度约 40%,计划在 2022 年内完成全部业务的搬迁,届时云上 EMR 的数据量预计会超过单副本 1 PB.

技术选型

首先是决定使用哪家云厂商。由于业务需求,AWS、Azure 和阿里云都有在用,综合考虑后认为阿里云最适合,有这些因素:

  • 物理距离:阿里云在我们线下机房同城有可用区,网络专线的延迟小,成本低
  • 开源组件齐全:阿里云 EMR 上包含的开源组件很多很全,除了我们重度使用的 Hive、Impala、Spark、Hue,也能方便集成 Presto、Hudi、Iceberg 等。我们在调研时发现只有阿里云 EMR 自带了 Impala,AWS 和 Azure 要么版本低,要么要自己安装部署。

阿里云的 EMR 本身也有使用 JindoFS 的存算分离方案,但基于以下考虑,我们最终选择了JuiceFS:

  1. JuiceFS 使用 Redis 和对象存储为底层存储,客户端完全是无状态的,可以在不同环境访问同一个文件系统,提高了方案的灵活性。而 JindoFS 元数据存储在 EMR 集群的本地硬盘,不便于维护、升级和迁移。
  2. JuiceFS 的存储方案丰富,而且支持不同方案的在线迁移,提高了方案的可移植性。JindoFS 块数据只支持 OSS.
  3. JuiceFS 以开源社区为基础,支持所有公有云环境,方便后期扩展到多云架构。

关于 JuiceFS

直接截取官方文档的介绍:

JuiceFS 是一款面向云原生设计的高性能共享文件系统,在 Apache 2.0 开源协议下发布。提供完备的 POSIX 兼容性,可将几乎所有对象存储接入本地作为海量本地磁盘使用,亦可同时在跨平台、跨地区的不同主机上挂载读写。

JuiceFS 采用「数据」与「元数据」分离存储的架构,从而实现文件系统的分布式设计。使用 JuiceFS 存储数据,数据本身会被持久化在对象存储(例如,Amazon S3),相对应的元数据可以按需持久化在 Redis、MySQL、TiKV、SQLite 等多种数据库中。

除了 POSIX 之外,JuiceFS 完整兼容 HDFS SDK,与对象存储结合使用可以完美替换 HDFS,实现存储和计算分离。

实施过程

我们在 2021 年 10 月开始探索 Hadoop 的上云方案;11 月做了大量调研和讨论,基本确定方案内容;12 月和 2022 年 1 月春节前做了 PoC 测试,在春节后 3 月份开始搭建正式环境并安排迁移。为了避免导致业务中断,整个迁移过程以相对较慢的节奏分阶段执行,截至目前(2022 年 7 月)进度约 40%,计划在 2022 年内完成整体的搬迁。 迁移完后,云上的 EMR 集群数据量预计会超过单副本 1 PB.

架构设计

做完技术选型之后,架构设计也能很快确定下来。考虑到除了 Hadoop 上云之外,仍然有大部分业务会继续保留在数据中心,所以整体实际上是个混合云的架构。

部署和配置

  • 关于IDC-阿里云专线:能提供专线服务的供应商很多,包括 IDC、阿里云、运营商等,选择的时候主要考虑线路质量、成本、施工周期等因素,最终我们选择了IDC的方案。IDC 跟阿里云有合作,很快就完成了专线的开通。这方面如果遇到问题,可以找 IDC 和阿里云的支持。除专线租用成本,阿里云也会收取下行(从阿里云到 IDC)方向传输费用。专线两端的内网 IP 完全互通,阿里云和 IDC 两侧都需要一些路由配置。
  • 关于EMR Core/Task 节点类型的选择:
  1. JuiceFS 可以使用本地硬盘做缓存,能进一步减少 OSS 带宽需求并提高 EMR 性能。更大的本地存储空间,可以提供更高的缓存命中率。
  2. 阿里云本地 SSD 实例是较高性价比的 SSD 存储方案(相对于云盘),用作缓存正合适。
  3. JuiceFS 社区版未支持分布式缓存,意味着每一个节点都需要一个缓存池,所以应该选用尽量大的节点。

基于以上考虑和配置对比,我们决定选用 ecs.i2.16xlarge,每个节点64 vCore、512GiB Memory、1.8T*8 SSD。

  • 关于 EMR 版本:

    软件方面,主要包括确定组件版本、开启集群、修改配置。我们机房使用的是 CDH 5.14,其中 Hadoop 版本是 2.6,阿里云上最接近的版本是 EMR 3.38. 但调研时发现该版本的 Impala 和 Ranger 不兼容(实际上我们机房使用的是 Sentry 做权限管理,但 EMR 上没有),最终经过评估对比,决定直接使用 EMR 5 的最新版,几乎所有组件的大版本都做了升级(包含 Hadoop 3、Spark 3 和 Impala 3.4)。此外,使用外部 MySQL 作为 Hive Metastore、Hue、Ranger 的数据库。

  • 关于 JuiceFS 配置:

    基本参考JuiceFS官方文档《在 Hadoop 中通过 Java 客户端访问 JuiceFS》即可完成配置。另外我们也配置了这些参数:

  • 缓存相关:其中最重要的是 juicefs.cache-dir 缓存目录。这个参数支持通配符,对多个硬盘的实例环境很友好,如设置为/mnt/disk*/juicefs-cache(需要手动创建目录,或在EMR节点初始脚本中创建),即用全部本地 SSD 作为缓存。另外也要关注 juicefs.cache-sizejuicefs.free-space 两个参数。

  • juicefs.push-gateway:设置一个 Prometheus Push Gateway,用于采集 JuiceFS Java 客户端的指标。

  • juicefs.usersjuicefs.groups:分别设置为 JuiceFS 中的一个文件(如jfs://emr/etc/usersjfs://emr/etc/groups),解决多个节点 uid 和 gid 可能不统一的问题。

  • 关于 Kafka Connect 使用 JuiceFS:

经过一些测试,确认 JuiceFS 可以完美应用于 Kafka Connect 的 HDFS Sink 插件(我们把配置方式也补充到了官方文档)。相比使用 HDFS Sink 写入HDFS,写入 JuiceFS 需要增加或修改以下配置项:

  • 将 JuiceFS Java SDK 的 JAR 包发布到 Kafka Connect 每一个节点的 HDFS Sink 插件目录。Confluent 平台的插件路径是:/usr/share/java/confluentinc-kafka-connect-hdfs/lib
  • 编写包含 JuiceFS 配置的 core-site.xml,发布到 Kafka Connect 每一个节点的任意目录。包括这些必须配置的项目:
fs.jfs.impl = io.juicefs.JuiceFileSystem

fs.AbstractFileSystem.jfs.impl = io.juicefs.JuiceFS

juicefs.meta = redis://:password@my.redis.com:6379/1

请参见 JuiceFS Java SDK 的配置文档。

  • Kafka Connector 任务设置:
hadoop.conf.dir=<core-site.xml所在目录>

store.url=jfs://<JuiceFS文件系统名称>/<路径>

PoC

PoC 的目的是快速验证方案的可行性,有几个具体目标:

  • 验证 EMR + JuiceFS + OSS 整体方案的可行性
  • 检查 Hive、Impala、Spark、Ranger 等组件版本的兼容性
  • 评估对比性能表现,用了 TPC-DS 的测试用例和部分内部真实业务场景,没有非常精确的对比,但能满足业务需求
  • 评估生产环境所需的节点实例类型和数量(算成本)
  • 探索数据同步方案
  • 探索验证集群与自研 ETL 平台、Kafka Connect 等的集成方案

期间做了大量测试、文档调研、内外部(阿里云 + JuiceFS 团队)讨论、源码理解、工具适配等工作,最终决定继续推进。

数据同步

要迁移的数据包括两部分:Hive Metastore 元数据以及 HDFS 上的文件。由于不能中断业务,采用存量同步 + 增量同步(双写)的方式进行迁移;数据同步完后需要进行一致性校验。

存量同步

对于存量文件同步,可以使用 JuiceFS 提供的功能完整的数据同步工具 sync 子命令 来实现高效迁移。JuiceFS sync 命令支持单节点和多机并发同步,实际使用时发现单节点开多线程即可打满专线带宽,CPU 和内存占用低,性能表现非常不错。

Hive Metastore 的数据同步则相对麻烦些:

  • 两个 Hive 版本不一致,Metastore 的表结构有差异,因此无法直接使用 MySQL 的导出导入功能
  • 迁移后需要修改库、表、分区存储路径(即 dbs 表的 DB_LOCATION_URIsds 表的 LOCATION

因此我们开发了一套脚本工具,支持表和分区粒度的数据同步,使用起来很方便。

增量同步

增量数据主要来自两个场景:Kafka Connect HDFS Sink 和 ETL 程序,我们采用了双写机制。

Kafka Connect 的 Sink 任务都复制一份即可,配置方式上文有介绍。ETL 任务统一在内部自研的低代码平台上开发,底层使用 Airflow 进行调度。通常只需要把相关的 DAG 复制一份,修改集群地址即可。实际迁移过程中,这一步遇到的问题最多,花了大量时间来解决。主要原因是 Spark、Impala、Hive 组件版本的差异导致任务出错或数据不一致,需要修改业务代码。这些问题在 PoC 和早期的迁移中没有覆盖到,算是个教训。

数据校验

数据同步完后需要进行一致性校验,分三层:

  • 文件一致。在存量同步阶段做校验,通常的方式是用 checksum. 最初的 JuiceFS sync 命令不支持 checksum 机制,我们建议和讨论后,JuiceFS 团队很快就加上了该功能(issuepull request)。除了 checksum,也可考虑使用文件属性对比的方式:确保两个文件系统里所有文件的数量、修改时间、属性一致。比 checksum 的可靠性稍弱,但更轻量快捷。
  • 元数据一致。有两种思路:对比 Metastore 数据库的数据,或对比 Hive 的 DDL 命令的结果。
  • 计算结果一致。即使用 Hive/Impala/Spark 跑一些查询,对比两边的结果是否一致。一些可以参考的查询:表/分区的行数、基于某个字段的排序结果、数值字段的最大/最小/平均值、业务中经常使用的统计聚合等。

数据校验的功能也封装到了脚本里,方便快速发现数据问题。

后续计划

大致有几个方向:

  • 继续完成剩余业务的上云迁移
  • 探索 JuiceFS + OSS 的冷热分级存储策略。JuiceFS 的文件在 OSS 上完全被打散,无法基于文件级别做分级。目前的思路是将冷数据从 JuiceFS 迁移到 OSS 上,设置为归档存储,修改 Hive 表或分区的 LOCATION,不影响使用。
  • 目前 JuiceFS 使用 Redis 作为元数据引擎,假如将来数据量增加,使用 Redis 有压力的话可能考虑切换为 TiKV 或其他引擎。
  • 探索 EMR 的弹性计算实例,争取能在满足业务 SLA 的前提下降低使用成本

一手实战经验

在整个实施过程中陆陆续续踩了一些坑,积累了一些经验,分享给大家做参考。

阿里云 EMR 和组件相关

兼容性

  • EMR 5 的 Hive 和 Spark 版本不兼容,无法使用 Hive on Spark,可以把默认的引擎改成 Hive on Tez.
  • Impala 的 stats 数据从旧版同步到新版后,可能因为 IMPALA-10230 导致表无法查询。解决方案是在同步元数据时,将 num_nulls=-1 的改成 num_nulls=0. 可能需要用到 CatalogObjects.thrift 文件
  • 原集群有少量 Textfile 格式的文件用了 snappy 压缩,新版 Impala 无法读取,报错 Snappy: RawUncompress failed,可能是 IMPALA-10005 导致的。规避方案是不要对 Textfile 文件使用 snappy 压缩。
  • Impala 3.4 相比 2.11 的 CONCAT_WS 函数行为有差异,老版本 CONCAT_WS('_', 'abc', NULL) 会返回 NULL,而新版本返回 'abc'.
  • Impala 3.4 对 SQL 中的保留关键字引用更严格,必须加上``. 其实一个好习惯是业务代码不要使用保留关键字。
  • PoC 或前期测试的覆盖度尽可能完整,用真实的业务代码去跑。我们在 PoC 和早期迁移的业务中用到的组件特性比较少,基本都是最常用、保持兼容的功能,因此比较顺利。但在第二批迁移过程中就暴露出了很多问题,虽然最终都有解决,但花了很多额外的时间去做诊断和定位,打乱了节奏。

性能

  • EMR 5 的 Impala 3.4 打了 IMPALA-10695 这个补丁,支持对 oss://jfs://(本意是支持 JindoFS,但 JuiceFS 也默认使用 jfs 这个 scheme)设置独立的 IO 线程数。在 EMR 控制台上增加或修改 Impala 的配置项 num_oss_io_threads.
  • 阿里云 OSS 有账号级别的带宽限制,默认 10Gbps,随着业务规模上升容易成为瓶颈。可以与阿里云沟通调整。

运维

  • EMR 可以关联一个 Gateway 集群,通常用来部署业务程序。如果要在 Gateway 上用 client 模式提交 Spark 任务,需要先将 Gateway 机器的 IP 加到 EMR 节点的 hosts 文件。默认可以使用 cluster 模式。
  • EMR 5 会开启一个 Spark ThriftServer,在 Hue 上可以直接写 Spark SQL,用起来很方便。但默认配置有个坑,会写大量日志(路径大概是 /mnt/disk1/log/spark/spark-hadoop-org.apache.spark.sql.hive.thriftserver.HiveThriftServer2-1-emr-header-1.cluster-xxxxxx.out),导致硬盘写满。解决方案有两个:配置 log rotate 或把 spark.driver.extraJavaOptions 配置清空(阿里云技术支持的建议)。

JuiceFS 相关

  • JuiceFS 需要每个节点上具有相同的 UID 和 GID,否则很容易出现权限问题。有两种实现方式:修改操作系统的用户(比较适合新机器,没有历史包袱),或者在 JuiceFS 上维护一个用户映射表。我们之前也分享过一篇 JuiceFS + HDFS 权限问题定位,有详细讨论。通常需要维护映射的用户有 impala, hive, hadoop 等。如果使用 Confluent Platform 搭建 Kafka Connect,也需要配置 cp-kafka-connect 用户。
  • 使用默认的 JuiceFS IO 配置时,相同的写查询,Hive on Tez 和 Spark 都比 Impala 快很多(但在机房里 Impala 更快)。最终发现将 juicefs.memory-size 从默认的 300 (MiB) 改成 1024 之后 Impala 的写入性能有成倍的提升。
  • 在做 JuiceFS 的问题诊断和分析时,客户端日志很有用,需要注意 POSIX 和 Java SDK 的日志是不一样的,详见 JuiceFS 故障诊断和分析 | JuiceFS Document Center
  • 注意监控 Redis 的空间用量,Redis 如果满了,整个 JuiceFS 集群无法写入。
  • 使用 JuiceFS sync 把机房数据往云上同步时,选择在有 SSD 的机器上跑,获得更好的性能。

如有帮助的话欢迎关注我们项目 Juicedata/JuiceFS 哟! (0ᴗ0✿)

一面数据: Hadoop 迁移云上架构设计与实践的更多相关文章

  1. 基于 Angularjs&Node.js 云编辑器架构设计及开发实践

    基于 Angularjs&Node.js 云编辑器架构设计及开发实践 一.产品背景 二.总体架构 1. 前端架构 a.前端层次 b.核心基础模块设计 c.业务模块设计 2. Node.js端设 ...

  2. 【原创】基于Docker的CaaS容器云平台架构设计及市场分析

    基于Docker的CaaS容器云平台架构设计及市场分析 ---转载请注明出处,多谢!--- 1 项目背景---概述: “在移动互联网时代,企业需要寻找新的软件交付流程和IT架构,从而实现架构平台化,交 ...

  3. 云ATM架构设计

    云ATM架构设计 启动程序(Start.java) public class Start { public static void main(String[] args) { MainView vie ...

  4. 2本Hadoop技术内幕电子书百度网盘下载:深入理解MapReduce架构设计与实现原理、深入解析Hadoop Common和HDFS架构设计与实现原理

    这是我收集的两本关于Hadoop的书,高清PDF版,在此和大家分享: 1.<Hadoop技术内幕:深入理解MapReduce架构设计与实现原理>董西成 著  机械工业出版社2013年5月出 ...

  5. FPGA加速:面向数据中心和云服务的探索和实践

    欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦~ 本文由columneditor 发表于云+社区专栏 作者介绍:章恒--腾讯云FPGA专家,目前在腾讯架构平台部负责FPGA云的研发工作,探索 ...

  6. Slickflow.NET 开源工作流引擎基础介绍(六)--模块化架构设计和实践

    前言:在集成Slickflow.NET 引擎组件过程中,引擎组件需要将用户,角色等资源数据读取进来,供引擎内部调用:而企业客户都是有自己的组织架构模型,在引入模块化架构设计后,引擎组件的集成性更加友好 ...

  7. Atitit.数据库表的物理存储结构原理与架构设计与实践

    Atitit.数据库表的物理存储结构原理与架构设计与实践 1. Oracle和DB2数据库的存储模型如图: 1 1.1. 2. 表数据在块中的存储以及RowId信息3 2. 数据表的物理存储结构 自然 ...

  8. 基于Hadoop的大数据平台实施记——整体架构设计[转]

    http://blog.csdn.net/jacktan/article/details/9200979 大数据的热度在持续的升温,继云计算之后大数据成为又一大众所追捧的新星.我们暂不去讨论大数据到底 ...

  9. 基于Hadoop的大数据平台实施记——整体架构设计

    大数据的热度在持续的升温,继云计算之后大数据成为又一大众所追捧的新星.我们暂不去讨论大数据到底是否适用于您的组织,至少在互联网上已经被吹嘘成无所不能的超级战舰.好像一夜之间我们就从互联网时代跳跃进了大 ...

随机推荐

  1. 『现学现忘』Git基础 — 24、Git中查看历史版本记录

    目录 1.查看详细的历史版本记录 2.简化显示历史版本记录 3.历史版本记录常用操作 (1)指定查看最近几次提交的内容 (2)以简单图形的方式查看分支版本历史 (3)翻页与退出 4.查看分支相关的版本 ...

  2. OAuth2授权服务器Id Server一键生成配置原理

    OAuth2客户端的配置参数非常多,虽然Id Server通过控制台可视化解决了创建OAuth2客户端的问题.但是如何进一步降低OAuth2的使用难度,把创建的OAuth2客户端转化为配置成为了刚需, ...

  3. 用Docker打包Python运行环境

    虽然Docker作为部署环境打包镜像的工具,和我的科研并没有直接的关系.但我觉得在项目中运用Docker来打包环境依赖也可以大大提高工作效率,于是准备专门学习一下Docker. 1. Docker基础 ...

  4. Java异常处理最佳实践

    总结一些Java异常的处理原则 Java异常处理最佳实践 不要忘记关闭资源 在finally里关闭资源 public void readFile() { FileInputStream fileInp ...

  5. 665. Non-decreasing Array - LeetCode

    Question 665. Non-decreasing Array Solution 题目大意: 思路:当前判断2的时候可以将当前元素2变为4,也可以将上一个元素4变为2,再判断两变化后是否满足要求 ...

  6. Android.mk编译App源码

    在Andriod源码环境编译APP主要考虑如何引入第三方jar包和arr包的问题,初次尝试,步步是坑,这里给出一个模板: LOCAL_PATH := $(call my-dir) include $( ...

  7. Kafka消息的压缩机制

    最近在做 AWS cost saving 的事情,对于 Kafka 消息集群,计划通过压缩消息来减少消息存储所占空间,从而达到减少 cost 的目的.本文将结合源码从 Kafka 支持的消息压缩类型. ...

  8. 前端5jQuery

    内容概要 jQuery简介 查找标签 jQuery操作标签 jQuery事件操作 jQuery动画效果(了解) 前端第三方框架(基础) 内容详情 jQuery简介

  9. JavaScript Object学习笔记一

    Object.assign(target, source1, source2, ...)//用于对象的复制合并(同名属性后覆盖前)或拷贝(拷贝自身可枚举属性,不拷贝继承属性或不可枚举属性),将sour ...

  10. 使用kubeseal加密和管理k8s集群的secret

    使用kubeseal加密和管理k8s集群的secret 在k8s的管理过程中,像secret这种资源并不好维护,kubeseal提供了一种相对简单的方式来对原始secret资源进行加密,并通过控制器进 ...