在 Amazon EMR 上构建实时数据湖

news2024/9/27 17:36:22

前言

当公司业务发展遇到瓶颈时,业务分析师以及决策者们总会希望通过交叉分析大量的业务数据和用户行为数据,以解答“为什么利润会下滑?”“为什么库存周转变慢了?”等问题,最终整点“干货”出来从而促进业务发展。

亚马逊云科技开发者社区为开发者们提供全球的开发技术资源。这里有技术文档、开发案例、技术专栏、培训视频、活动与竞赛等。帮助中国开发者对接世界最前沿技术,观点,和项目,并将中国优秀开发者或技术推荐给全球云社区。如果你还没有关注/收藏,看到这里请一定不要匆匆划过,点这里让它成为你的技术宝库!

 

数据库往往不擅长大量数据分析型的工作,所以出现了数据仓库。但数据仓库往往要求较高配置的底层基础设施,成本较高。企业为了控制成本,一般只会把建好模的、含金量较高的数据放在其中。但是,生产经营的很多数据企业难以短期判断有没有价值,丢弃了怕失去机会,保存在数仓里又会造成巨大成本,放在冷存储里,又不容易进行数据价值探索。

这个时候,数据湖应运而生。一方面它底层基于 Amazon Simple Storage Service (S3) 这样的对象存储,存储成本低;另外它与一系列数据处理工具打通,能够快速进行数据探索和数据挖掘,可以实现高效的”沙中淘金”。

传统数据湖虽然存储成本底,但是实效性也较低。传统的数据湖方案,常常基于 Apache Spark 进行T+1离线任务。公司的数据团队一般会定时在凌晨启动 Spark 进行 ETL 数据建模,这样业务在上班的时候就可以用截止到当天0点的数据。但是随着商业模式的演变,企业需要通过实时推荐、实时对账、实时预警等方式以占据竞争优势,而这些手段对数据的实时性都要求极高。笔者曾经听闻一则消息,某电商的运营人员,因为把小数点打错造成价格低于实际价格10倍,引起客户疯狂下单。第二天,公司分析师根据姗姗来迟的销量报告进行分析,花费数个小时才发现了这个问题。但这个时候造成的资产和信用的损失已经难以挽回。以笔者来看,如果采用实时数据技术,对实时数据流式应用机器学习或规则引擎技术,实时监控数据异常,该损失是很容易避免的,

本文将介绍一种实时数据湖方案,即能帮助企业低成本地使用海量数据,又能更快速地响应业务需求,同时借助亚马逊云科技的托管服务,能够快速实施和轻松运维。

方案架构

整个架构为了保证数据的实效性,接入层使用 Apache Kafka 接入业务数据库的 binlog,而像用户行为这类数据,可以直接在埋点服务端调用 Kafka 的 producer api 将数据注入 Kafka。

在数据处理部分,我们使用 Apache Flink + Apache Hudi 进行增量消费,再使用 Apache Spark + Apache Hudi 的方式,实现增量ETL。整个架构能将数据延迟控制到秒级

借助亚马逊云科技托管的 Amazon Elastic MapReduce (EMR) 集群,你可以开箱即用 Flink, Spark 等服务。另外我们将使用 Amazon Managed Streaming for Apache Kafka (MSK) 托管 Kafka 消息队列,它能够让 Kafka 开箱即用,并且根据数据量动态扩缩容。

整个架构如下图:

image.png

关键服务介绍

整个架构中,我们使用了 Amazon EMR, Amazon MSK, Amazon S3, Apache Airflow,Apache Hudi 等服务或开源产品。下面笔者为大家简单进行介绍并说明使用它们为什么能让我们更轻松的搭建起整个实时数据湖

Amazon S3

Amazon S3 是专为从任意位置存储和检索任意数量的数据而构建的对象存储。Amazon S3 可以为不同用户、不同场景提供存储服务,比如数据湖、网站、移动应用、一般数据的备份恢复以及大数据分析等等。这是一种简单的存储服务,以极低的成本提供具备行业优势的耐久性、可用性、性能、安全性和几乎无限的可扩展性。使用 Amazon S3,您可以轻松构建使用原生云存储的应用程序。Amazon S3 具有高度可扩展性且按量计费,您可以从较小用量起步,之后根据需要扩展存储。

Amazon EMR

image.png

Amazon EMR 是行业先进的云计算大数据平台,适用于使用多种开源框架(例如 Apache Spark、Apache Hive、Presto)进行数据处理、交互分析和机器学习的场景。通过 Amazon EMR,您可以专注于数据转换和分析,而不必耗费时间精力用于管理计算能力或开源应用程序,此外还能节省资金成本。Amazon EMR采用存储和计算分离的架构,数据存储在 Amazon S3 上,计算资源来自 Amazon Elastic Compute Cloud (EC2) 实例。集群创建之后,MapReduce 通过 HDFS 代理调用 Amazon S3 接口,从 S3上读取和写入数据。Amazon EMR 为集群中的服务器定义了三种角色。

  1. 主节点——管理集群:协调将 MapReduce 可执行文件和原始数据子集分配到核心实例组和任务实例组。此外,它还会跟踪每个任务的执行状态,监控实例组的运行状况。一个集群中只有一个主节点。这与 Hadoop 主节点映射。
  2. 核心节点——使用 Hadoop 分布式文件系统(HDFS)运行任务和存储数据。这与 Hadoop 从属节点映射。
  3. 任务节点(可选)——运行任务:这与 Hadoop 从属节点映射。

Amazon MSK

Amazon MSK 是亚马逊云科技托管的高可用、强安全的 Kafka 服务,是数据分析领域负责消息传递的基础,也因此在流式数据入湖部分举足轻重。

Apache Airflow

Apache Airflow 是一项由 Airbnb 在 2014 年 推出的开源项目,其目的是为管理日益复杂的数据管理、脚本和分析工具,提供一个构建批处理工作流的方案。从功能来看,这是一种可扩展的分布式工作流调度系统,允许将工作流建模为有向无环图(DAGs),通过这种方式简化数据管道中各个处理步骤的创建、编排和监控。

Apache Hudi

Apache Hudi 是一个帮助企业构建流式数据湖的平台, Hudi 的含义是 Hadoop Upserts and Incrementals, 它的主要目的是高效减少摄取过程中的数据延迟, 由 Uber 开发并开源。它是一个表结构,提供了适用于Flink, Spark 的库,非常易于和现有大数据平台集成。

基础设施

该构建方案中使用到的基础设施除 Apache Airflow 外,均采用亚马逊云科技中国(宁夏)区域中的托管服务。Apache Airflow 采用 Docker 安装的方式,与其他组件在同一个 VPC 中。

构建方案

数据摄入

为了减少数据的延迟,我们在数据摄入过程中就采用流式数据。对于企业经营过程中的业务数据,一般存放在 MySQL 一类的关系型数据库,我们可以通过将 binlog接入 Kafka 完成,这个过程可以通过 Maxwell 一类的 binlog采集工具,也可以直接通过 Flink CDC。而对于用户行为数据的采集,各种埋点方案都可以直接把这些行为数据打入 Kafka。

使用 Apache Flink + Apache Hudi 构建 ODS 层表

数据接入 Kafka 以后,我们可以通过 Apache Flink + Apache Hudi 构建 ods 表。你可能会问这种方式构建的 ods 表和传统方式又和不同?

由于 Hudi 针对分布式数据存储提供了 插入更新(upsert)和增量消费两种原语,所以 Hudi 构建 raw table 天然能够同步原始数据的变更。

下面我将使用 Amazon EMR 6.4 版本来演示这个过程。启动 EMR 集群非常简单,我在这里不再赘述,您可以参考亚马逊云科技官方文档。

  1. 我们登陆 Amazon EMR 主节点,下载 hudi-flink-bundle 到 /usr/lib/flink/lib/ 目录中,即可使用 Hudi(你可以从 Central Repository: org/apache/hudi 下载合适你 Flink 版本的依赖包)
  2. 启动一个 Flink session
checkpoints=s3://xxxxxxxx/flink/checkpoints/

flink-yarn-session -jm 1024 -tm 4096 -s 2 \
 -D state.backend=rocksdb \
-D state.checkpoint-storage=filesystem \
-D state.checkpoints.dir=${checkpoints} \
-D execution.checkpointing.interval=60000 \
-D state.checkpoints.num-retained=5 \
-D execution.checkpointing.mode=EXACTLY_ONCE \
-D execution.checkpointing.externalized-checkpoint-retention=RETAIN_ON_CANCELLATION \
 -D state.backend.incremental=true \
-D execution.checkpointing.max-concurrent-checkpoints=1 \
-D rest.flamegraph.enabled=true \
-d \
-t /etc/hive/conf/hive-site.xml
  1. 启动 Flink SQL。其中 application id 是 Flink session 的 application id
/usr/lib/flink/bin/sql-client.sh -s {application id}
  1. 在启动好的 Flink SQL 客户端的中,创建一个 Kafka 流表。这里举个订单的例子
CREATE TABLE kafka_order (
  order_id BIGINT,
  user_mail STRING,
  status STRING, 
  good_count BIGINT,
  city STRING,
  amount DECIMAL(10, 2),
  create_time STRING,
  update_time STRING
) WITH (
 'connector' = 'kafka',
 'topic' = 'order_table',
 'properties.bootstrap.servers' = 'xxxxxxx.cn-northwest-1.amazonaws.com.cn:9092',
 'properties.group.id' = 'testGroup1',
 'format' = 'maxwell-json'
);

注意,上面代码 connector 设置为 Kafka,所以你需要下载 Flink Kafka connector 到 /usr/lib/flink/lib/ 目录中

  1. 使用 Hudi connector 创建一张Hudi 表。
CREATE TABLE flink_hudi_order_ods(
order_id BIGINT,
user_mail STRING,
status STRING, 
good_count BIGINT,
city STRING,
amount DECIMAL(10, 2),
create_time STRING,
update_time STRING,
ts TIMESTAMP(3),
logday VARCHAR(255),
hh VARCHAR(255)
)PARTITIONED BY (`logday`,`hh`)
WITH (
'connector' = 'hudi',
'path' = 's3://xxxxx/flink/flink_hudi_order_ods/',
'table.type' = 'COPY_ON_WRITE',
'write.precombine.field' = 'ts',
'write.operation' = 'upsert',
'hoodie.datasource.write.recordkey.field' = 'order_id',
'hive_sync.enable' = 'true',
'hive_sync.table' = 'flink_hudi_order_ods',
'hive_sync.mode' = 'HMS',
'hive_sync.use_jdbc' = 'false',
'hive_sync.username' = 'hadoop',
'hive_sync.partition_fields' = 'logday,hh',
'hive_sync.partition_extractor_class' = 'org.apache.hudi.hive.MultiPartKeysValueExtractor'
);
  1. 将流式数据插入刚才创建的 Hudi 表
insert into flink_hudi_order_ods select * ,
CURRENT_TIMESTAMP as ts,
DATE_FORMAT(CURRENT_TIMESTAMP, 'yyyy-MM-dd') as logday, 
DATE_FORMAT(CURRENT_TIMESTAMP, 'hh') as hh 
from kafka_order;
  1. 验证。一两分钟后,你应该可以通过 hive 或 glue catalog 查看到 flink_hudi_order 表,你可使用 hIve 或 Amazon Athena 查询这张表的数据。同时你也可以验证一下数据更新,在原始数据的 mysql 中更新某条记录,十多秒后再尝试在 hive 查询数据湖中的 flink_hudi_order_ods 表,应该发现刚才的更新已经同步到了数据湖中。

使用 Apache Spark + Apache Hudi 进行增量数据 ETL

接下来我们使用演示一下如何通过 Apache Spark + Apache Hudi 进行增量数据的 ETL

  1. 首先,你需要根据你的 Spark 版本下在 Amazon EMR master 节点下载hudi-spark-bundle 包

  2. 在编写 ETL 任务时,你需要把输出格式改为 hudi

df.write
  .format("hudi")
  .options(getQuickstartWriteConfigs)
  .option(PRECOMBINE_FIELD.key(), "logday")
  .option(RECORDKEY_FIELD.key(), "logday")
  .option(PARTITIONPATH_FIELD.key(), "logday")
  .option(OPERATION.key(), "upsert")
  .option("hoodie.table.name", targetTbName)
  .option("hoodie.datasource.hive_sync.enable", "true")
  .option("hoodie.datasource.hive_sync.database", "default")
  .option("hoodie.datasource.hive_sync.table", targetTbName)
  .option("hoodie.datasource.hive_sync.mode", "HMS")
  .option("hoodie.datasource.hive_sync.use_jdbc", "false")
  .option("hoodie.datasource.hive_sync.username", "hadoop")
  .option("hoodie.datasource.hive_sync.partition_fields", "logday")
  .option(
    "hoodie.datasource.hive_sync.partition_extractor_class",    "org.apache.hudi.hive.MultiPartKeysValueExtractor"  )
  .mode(SaveMode.Append)
  .save(basePath)
  1. 由于我们要通过 Airflow 调度任务,所以在你的 Airflow DAG 文件应该如下方式启动你的任务
spark-submit \
    --deploy-mode cluster \
    --master yarn \
    --class com.xxxx.xxxx.Demo \
    --jars {app_dir}/hudi-spark3.1.2-bundle_2.12-0.10.1.jar,{app_dir}/spark-avro_2.12-3.1.2.jar \
    --conf 'spark.serializer=org.apache.spark.serializer.KryoSerializer' \
    --conf 'spark.dynamicAllocation.enabled=false' \
    {app_dir}/spark-scala-examples-1.0-SNAPSHOT.jar
  1. 你也可以直接使用 spark-shell 直接查询 Hudi 表,如下演示如何将 Hudi 和 spark-shell 集成
spark-shell --jars ./hudi-spark3.1.2-bundle_2.12-0.10.1.jar,spark-avro_2.12-3.1.2.jar --conf 'spark.serializer=org.apache.spark.serializer.KryoSerializer' --conf 'spark.dynamicAllocation.enabled=false'

部署 Apache Airflow 并对 Spark 任务进行任务调度

在跟 Amazon EMR 同样的VPC中启动一台 Amazon EC2,操作系统可以选择 Amazon Linux 或者 CentOS。然后根据以下步骤安装 Apache Arflow。

  1. 安装 docker

  2. 安装 docker compose

  3. 使用 git clone GitHub - tuanavu/airflow-tutorial: Apache Airflow tutorial

  4. cd 到airflow-tutorial目录

  5. 运行docker-compose up -d 命令

执行完第五步的命令,Apache Airflow 相关软件将被下载和安装,安装完成之后,我们可以通过编写 DAG 来对 Spark 进行任务调度。

如何调度 Amazon EMR 上的 Spark 任务呢?我们建议使用 Airflow ssh hook,这种方式配置简单,并且容许你的 Airflow 单独部署。我们需要保证 Airflow 集群能够访问你的 Amazon EMR 集群,所以如果你的 Airflow 是单独部署,没有部署在 Amazon EMR 集群中,你需要保证二者的网络互通,另外 Airflow 可以通过 ssh 访问你的 Amazon EMR master 节点。具体配置方式是在 Airflow 配置 ssh 的默认信息的地方,配置好 Amazon EMR master 节点的信息,用户账号,以及 Amazon EMR master 节点 ssh 私钥地址。这里有个需要注意的问题,由于我们使用的是 docker 启动 Airflow,所以您的 ssh 私钥要保证 docker 内部可访问。

总结

本文在 Amazon EMR 集群上,演示了如何通过使用Flink, Spark 等服务与Hudi 集成,配合 Airflow, Amazon MSK 等服务实现了一个流式数据湖,从而有效的减少了数据从产生到消费的数据延迟。

借助 Amazon EMR 和 Amazon MSK, 消除了 Flink /Spark/Kafka 等基础服务运营开销,让这些服务开箱即用,从而使我们只要关心数据湖的构建以及湖上的数据处理。

本篇作者

image.png

许庭新

西云数据解决方案架构师,10+年产品研发和解决方案咨询经验,在电商,互联网金融,智能汽车领域有丰富的实战经验,擅长利用云计算、大数据,AI等技术挖掘用户底层需求,实现精准运营。

image.png

蔡如海

西云数据解决方案架构师,10+年开发和架构经验,曾就职于知名外企,在媒体、金融等业务领域有丰富的工作经验,擅长云计算、机器学习等技术,并且有丰富的项目管理经验。

文章来源:https://dev.amazoncloud.cn/column/article/6309c8990c9a20404da7914f?sc_medium=regulartraffic&sc_campaign=crossplatform&sc_channel=CSDN 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/809175.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

一、Postfix[安装与配置、smtp认证、Python发送邮件以及防垃圾邮件方法、使用腾讯云邮件服务]

Debian 11 一、安装 apt install postfix 二、配置 1.dns配置 解释:搭建真实的邮件服务器需要在DNS提供商那里配置下面的dns 配置A记录mail.www.com-1.x.x.x配置MX记录www.com-mail.www.com 解释:按照上面的配置通常邮件格式就是adminwww.com其通过…

2023 年还推荐报计算机专业吗?

计算机科学是一个很好的专业,因为它由各种课程组成,为学生在成熟和新兴专业就业做好准备。以下是一些通常属于计算机科学专业的课程: 基本编程介绍了用于构建和维护数字架构和基础设施的编程语言和标准。 微积分为制定高级计算和设计概念提供…

使用vim-cmd工具给ESXi虚机定期打快照

VMware虚拟化 - 建设篇 第四章 使用vim-cmd工具给ESXi虚机定期打快照 VMware虚拟化 - 建设篇系列文章回顾使用vim-cmd工具给ESXi虚机定期打快照前言前提条件ESXi新增执行快照备份的sh脚本ESXi添加crond任务并使其生效ESXi指定部分虚拟机不执行定期快照(附加)虚拟机自定义属性…

【数据分享】1999—2021年地级市学校数、教师数和学生数(Shp/Excel格式)

在之前的文章中,我们分享过基于2000-2022年《中国城市统计年鉴》整理的1999-2021年地级市的人口相关数据、各类用地面积数据、污染物排放和环境治理相关数据、房地产投资情况和商品房销售面积、社会消费品零售总额和年末金融机构存贷款余额、地方一般公共预算收支状…

(树) 剑指 Offer 26. 树的子结构 ——【Leetcode每日一题】

❓剑指 Offer 26. 树的子结构 难度:中等 输入两棵二叉树 A 和 B,判断 B 是不是 A 的子结构。(约定空树不是任意一个树的子结构) B 是 A 的子结构, 即 A 中有出现和B相同的结构和节点值。 例如: 给定的树 A: 3/ \4 5/ \1 2给定的树 B&…

【Linux】用户相关内容

如果命令ll 出现以上信息,UID为具体的数字,代表之前UID为502的用户被删除了。 更改目录或文件所属用户和所属组 在Linux中,创建一个文件时,该文件的拥有者都是创建该文件的用户。 更改所属用户 chown 用户名 文件名/目录名 更…

【环境配置】Windows下WSL将ubuntu挪位置-系统盘清理

问题–垃圾太多,系统盘空间占用太大 最近 C 盘空间暴涨,用工具 WinDirStat-强烈推荐的工具 查看发现 WSL 子系统占用了6个多 G 的空间,遂想办法挪个位置; 【关键字】将 Windows 里的子系统挪到非系统盘 D 盘; 解决 打…

认清现实重新理解游戏的本质

认清现实重新理解游戏的本质 OVERVIEW 认清现实重新理解游戏的本质现实两条小路的启发四个动机1.当前的学习任务或工作任务太艰巨2.完美主义3.对未来太过于自信/无知4.大脑小看未来的收益 四个方法1.让未来的收益足够巨大2.让未来的收益感觉就在眼前3.玩游戏有恶劣的结果4.玩游…

转行车载做开发,首先得掌握好Android Framework~

前言 在当今社会,科技的快速发展推动了各行各业的变革。移动设备作为人们生活、工作、学习的重要工具,其市场份额逐年攀升。Android作为全球最受欢迎的移动操作系统之一,为开发者提供了广阔的发展空间。但是现在Android发展比较尴尬&#xf…

【Python基础】- 自定义函数和匿名函数(文末送书3本)

🤵‍♂️ 个人主页:艾派森的个人主页 ✍🏻作者简介:Python学习者 🐋 希望大家多多支持,我们一起进步!😄 如果文章对你有帮助的话, 欢迎评论 💬点赞&#x1f4…

Nginx下载、安装与使用

Nginx下载 简介: Nginx是一个高性能的HTTP和反向代理web服务器,同时也提供了IMAP/POP3/SMTP服务(邮件服务)。 官网下载地址: https://nginx.org/en/download.html 国内镜像地址: https://mirrors.huawe…

认识数组指针

文章目录 数组指针的定义数组指针的应用 数组指针的定义 类比 整形数组——存放整形的数组 指针数组——存放指针的数组 整形指针——存放整形地址的指针 数组指针——存放数组地址的指针 深度理解 在之前我们知道:数组名表示首元素地址,但是有&#xf…

iostat工具使用

文章目录 iostat命令简介iostat命令参数 iostat输出信息CPU利用率输出信息磁盘利用率输出信息更详细的磁盘利用率输出信息 iostat命令使用示例iostat -kdx 1 iostat数据来源相关参考 iostat命令简介 iostat工具可用于CPU使用统计信息和设备的输入输出统计信息。iostat能支持显…

操作系统专栏1-内存管理from 小林coding

操作系统专栏1-内存管理 虚拟地址内存管理方案分段分页页表单级页表多级页表TLB 段页式内存管理Linux内存管理 malloc工作方式操作系统内存回收回收的内存种类 预读失败和缓存污染问题预读机制预读机制失效解决方案缓存污染 内核对虚拟内存的表示内核对内核空间的表示直接映射区…

一个字符驱动示例 -- 微秒级别周期 反转GPIO

仅作为自我记录的一个demo 本次GPIO以微妙级别频率的反转实验有以下几个启示: 一开始在应用层做延时,来实现2微妙周期,占空比50%的GPIO反转,发现波形的频率一直上不去,只能在25hz徘徊,后来索性去掉延时&am…

96. Python基础教程:多个异常的处理方法(2个except语句)

【目录】 文章目录 96. Python基础教程:多个异常的处理方法(2个except语句)1. 2个except语句练习-分苹果2. except (异常类型1,异常类型2) as 别名 【正文】 96. Python基础教程:多个异常的处理方法(2个except语句) 1. 2个except语句练习-分苹果 任务目标写一个模拟幼儿园老师…

TCP网络通信编程之netstat

【netstat指令】 【说明】 (1)Listening 表示某个端口在监听 (2)如果有一个外部程序(客户端)连接到该端口,就会显示一条连接信息 (3)指令netstat -anb 可以参看是那个…

分库分表之基于Shardingjdbc+docker+mysql主从架构实现读写分离(二)

说明:如果实现了docker部署mysql并完成主从复制的话再继续,本篇文章主要说明springboot配置实现Shardingjdbc进行读写分离操作。 如果没实现docker部署mysql实现主从架构的话点击我 Shardingjdbc配置介绍(版本:5.3.2)…

04-树6 Complete Binary Search Tree(C++)

思路 先排序&#xff08;冒泡排序&#xff09; 用数组建一棵空树&#xff08;用数组&#xff0c;填好左右儿子&#xff09; 中序遍历填数&#xff08; Tree::travIn() &#xff09; 顺序输出即为层次遍历&#xff08; Tree::travLevel() &#xff09; code # include <…