24、实时Hadoop应用的Lambda架构详解

实时Hadoop应用的Lambda架构详解

实时Hadoop应用的Lambda架构详解

1. 速度层概述

在数据处理中,批处理层的延迟使得查询难以获取最新或接近实时的数据。速度层的目的就是无延迟地提供这些数据。从功能上看,速度层与批处理层相似,都基于主数据生成视图,但二者存在明显差异:
- 批处理层使用所有数据计算视图,而速度层仅处理批处理层尚未处理的新数据或近期数据。
- 批处理层通过重新计算(或重建)来更新视图,速度层则对视图进行增量处理,仅处理自上次增量处理后执行的增量(或新)事务。

速度层视图的更新方式有同步和异步之分:
- 同步更新 :将对主数据的任何更新直接应用于速度层视图。由于集群处理更新或其他数据密集型操作的容量固定,在高峰使用时可能会因请求过多而超载,影响性能和功能。
- 异步更新 :将更新请求放入队列,实际更新在稍后进行。其延迟取决于更新量、所需处理资源、对近实时数据的功能需求等因素,但能有效处理更多请求,不受高峰使用峰值的影响。

异步更新具有诸多优势,如处理队列中的多条消息、提高吞吐量、通过缓冲额外请求来处理不同负载等。而同步更新缺乏控制更新量的机制,容易导致数据库系统超载崩溃,或出现请求丢弃、超时等错误。选择同步还是异步更新,可根据应用程序的处理类型决定:
- 同步更新适用于需要与用户界面协调、保证请求完成的事务系统。
- 异步更新更适合注重复杂计算和聚合而非交互式用户输入的分析应用程序。

2. 速度层实现所需特性

实现速度层时,需要支持以下特性:
- 随机读写
- 支持包括日期/时间在内的广泛数据类型
- 能够执行定期或临时更新
- 以可接受的性能支持连接和任何增量更新任务(更新、插入)
- 支持索引并提供SQL查询接口,以提高性能和易用性
- 能够轻松与Hadoop生态系统交互
- 提供可扩展性和容错能力
- 具备内存处理能力以提高性能

3. 技术选型

经过评估,考虑了Spark SQL和VoltDB。但由于VoltDB无法从Hive(或HDFS)读取数据,所以被排除。而Spark SQL虽有一定优势,但也存在不足:
- 不提供事务支持。
- Spark SQL DataFrames不支持索引,而索引有助于随机读写性能。
- 本身不包含存储,需要使用外部数据存储。

4. 速度层构建示例

以构建跟踪信息系统的速度层为例,步骤如下:
1. 确定未处理记录 :通过查询 BatchProcHist 表中批次视图的最新记录,获取最新构建的日期/时间,从而确定未处理的记录。由于Hive不支持将查询结果赋值给变量,将第一个批次视图的最新记录写入表 MaxTable

Create table MaxTable as select ViewName, max(CreatedAt) as MaxDate from BatchProcHist group by ViewName having ViewName = 'ProfLFiveView';
  1. 考虑速度层已处理记录 :检查速度层自批次视图构建以来是否处理了主数据集中的新记录,仅考虑未处理的记录来更新视图(这里是注册为表的Spark数据框)。将第一个速度层视图的最新记录写入 MaxTable
Insert into MaxTable select ViewName, max(CreatedAt) from BatchProcHist group by ViewName having ViewName = 'ProfLFiveView_S';
  1. 确定最新记录并处理 :找出最新记录,以此为基础处理第一个速度层视图的记录:
Create table MaxTbl1 as select max(MaxDate) as MaxDate from MaxTable;
  1. 创建速度层视图 :从主数据集中获取未处理的记录,创建速度层视图,并添加时间戳,同时向审计历史表写入记录:
Create table Profitemp1_S as Select a.ProfLastYear, a.AsOf, a.Corporation from CorpProfitDetails a, MaxTbl1 b where a.AsOf > b.MaxDate;
Create table ProfLFiveView_S as select Corporation, sum(ProfLastYear) as ProfLastFive from Profitemp1 group by Corporation;
INSERT INTO TABLE BatchProcHist VALUES ('ProfLFiveView_S', from_unixtime(unix_timestamp()));

此时可删除临时表 MaxTable Profitemp1_S MaxTbl1 。创建 ProfLFiveView_S 视图时未使用 having sum(ProfLastYear) > 0 条件,因为该总和仅针对过去五年盈利的公司的新记录。要获取最新总和,将其与批处理层的总和相加即可。

5. 速度层视图更新策略

假设速度层视图每周构建一次,当需要更新速度层视图以适应新数据并移除已包含在批次层视图中的数据时,有两种方法:
- 重建视图 :仅考虑未处理的记录重建速度层视图,如同首次构建时一样。
- 增量更新 :第一轮处理后不删除临时表 Profitemp1_S ,删除已过期(已包含在重建的批次视图中)的记录,添加新记录,然后进行聚合操作并重建速度层视图 ProfLFiveView_S

选择哪种方法可根据速度层视图的大小决定:
- 如果视图不大且能快速重建,选择重建选项。
- 如果视图庞大,重建需要大量处理和时间,则启用事务支持,直接添加新记录并从临时表 Profitemp1 中移除已处理(由批处理层处理)的记录。

6. 另一个批次视图的速度层构建

以计算过去五年平均客户支持人员等于或超过1000人的公司的批次视图 AveCS1000View 为例,构建其速度层视图的步骤如下:
1. 获取最新处理时间

Create table MaxTable as select ViewName, max(CreatedAt) from BatchProcHist group by ViewName having ViewName = 'AveCS1000View';
Insert into MaxTable select ViewName, max(CreatedAt) from BatchProcHist group by ViewName having ViewName = 'AveCS1000View _S';
  1. 确定最新记录并处理
Create table MaxTbl1 as select max(MaxDate) as MaxDate from MaxTable;
  1. 创建速度层视图
Create table CustSuptemp1_S as Select a.CustSuppStrength, a.AsOf, a.Corporation from CorpCustSupDetails a, MaxTbl1 b where a.AsOf > b.MaxDate;
Create table CustSuptemp2_S as select Corporation, sum(CustSuppStrength) as TotalCustSup, count(CustSuppStrength) as CountCustSup from CustSuptemp1_S group by Corporation;
Create table AveCS1000View_S as select a.Corporation, (a.TotalCustSup + b.TotalCustSup) as TotalCustSup, (a.CountCustSup + b.CountCustSup) as CountCustSup, ((a.TotalCustSup + b.TotalCustSup) / (a.CountCustSup + b.CountCustSup)) as AveLastFive from CustSuptemp2_S a, AveCS1000View b where a.Corporation = b.Corporation and (AveLastFive >= 1000);
INSERT INTO TABLE BatchProcHist VALUES ('AveCS1000View_S', from_unixtime(unix_timestamp()));

由于该视图计算平均值,需要使用额外的临时表来添加和计数未处理记录以及相应批次视图中的 CustSuppStrength 数量。

7. Spark接口与速度层实现

Spark使用数据框和RDD(弹性分布式数据集)作为内存结构,可用于查询和提高性能,还允许使用 SQLContext 对Hive数据库执行查询。使用Spark实现速度层的步骤如下:
1. 构建HiveContext

val sqlContext = new org.apache.spark.sql.hive.HiveContext(sc)
val sqlContext.sql("Create table MaxTable as select ViewName, max(CreatedAt) from BatchProcHist group by ViewName having ViewName = 'AveCS1000View'")
val sqlContext.sql("Insert into MaxTable select ViewName, max(CreatedAt) from BatchProcHist group by ViewName having ViewName = 'AveCS1000View _S'")
  1. 创建速度层视图
val resultsDF = sqlContext.sql("select a.Corporation, (a.TotalCustSup + b.TotalCustSup) as TotalCustSup, (a.CountCustSup + b.CountCustSup) as CountCustSup, ((a.TotalCustSup + b.TotalCustSup) / (a.CountCustSup + b.CountCustSup)) as AveLastFive from CustSuptemp2_S a, AveCS1000View b where a.Corporation = b.Corporation and (AveLastFive >= 1000)")
val resultsDF.registerTempTable("AveCS1000View _S")
val results = sqlContext.sql("SELECT Corporation FROM AveCS1000View _S")
8. Hive与Spark SQL集成注意事项

由于Hive依赖众多,默认的Spark程序集不包含Hive。可使用 -Phive -Phive-thriftserver 标志来构建包含Hive的新程序集jar包,并确保该jar包存在于所有数据节点上。同时,将 hive-site.xml 文件复制到 $HADOOP_HOME/conf 目录。如果使用YARN集群,datanucleus jars应位于 lib_managed/jars 目录, hive-site.xml 应位于 $HADOOP_HOME/conf 目录,可通过 spark-submit 命令的 --jars --file 选项添加。

9. Lambda架构的优缺点
优点
  • 数据不可变性 :强调数据不可变,输入数据保持不变,处理和转换后的数据单独写入,可随时访问原始输入数据,避免因人为错误或硬件故障导致的数据损坏,增强架构的弹性。
  • 模块化处理 :数据在一系列模块化阶段进行转换,有助于独立调试每个阶段,使工作流程更易于管理。
  • 数据重处理 :可轻松重新处理数据。当应用程序代码发生变化时,可使用新代码重新处理输入数据。批处理层每次处理新数据时都会重建,默认支持数据重处理。
  • 灵活存储 :可以将主数据集进行规范化存储,同时根据需要对实时和批处理视图进行非规范化处理,有助于提高NoSQL数据的查询性能,还能对每个数据层进行微调。
  • 可靠分析源 :主数据集作为不可变数据存储,可作为可靠的分析源,包含所有应用程序数据的完整记录,便于分析数据子集或查找模式。
  • 支持近实时数据查询 :便于在查询中使用近实时数据。
缺点
  • 实时处理假设不准确 :认为实时处理比批处理准确性低、功能弱且不必要地复杂,这并不一定正确。许多领先的流处理系统(如Storm、Spark、Amazon Kinesis)能提供与批处理系统一样强大的语义保证。
  • 未打破CAP定理 :声称“打破CAP定理”并不成立。Lambda本质上是一种异步处理架构,计算结果与传入数据并非立即一致。
  • 代码维护复杂 :需要在两个独立的分布式系统(批处理层和速度层)中维护代码,且代码需根据运行的框架进行专门设计,导致实现Lambda架构的系统操作复杂性高。

综上所述,Lambda架构在实时Hadoop应用中有其独特的优势,但也存在一些问题,在实际应用中需要根据具体需求进行权衡和选择。

实时Hadoop应用的Lambda架构详解(续)

10. 速度层与批处理层的关系及处理流程

速度层的处理依赖于批处理层,至少需要移除已由批处理层处理的速度层记录,也可以选择重建或添加新记录到速度层视图。下面通过一个mermaid流程图来展示速度层与批处理层的整体处理流程:

graph LR
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A(数据流入):::process --> B(批处理层处理):::process
    A --> C(速度层处理):::process
    B --> D(生成批处理视图):::process
    C --> E(生成速度层视图):::process
    D --> F(更新审计表 BatchProcHist):::process
    E --> F
    F --> G(确定未处理记录):::process
    G --> C
    B --> H(定期重建批处理视图):::process
    H --> I(移除速度层中已处理记录):::process
    I --> C

从流程图可以看出,数据流入系统后,同时进入批处理层和速度层进行处理。批处理层和速度层分别生成各自的视图,并将处理信息记录到审计表 BatchProcHist 中。通过审计表确定未处理的记录,继续在速度层进行处理。批处理层会定期重建视图,重建后需要移除速度层中已处理的记录。

11. 不同更新策略的对比分析

为了更清晰地对比速度层视图更新的两种策略(重建视图和增量更新),下面通过一个表格进行分析:
| 更新策略 | 优点 | 缺点 | 适用场景 |
| — | — | — | — |
| 重建视图 | 逻辑简单,易于实现;能确保视图数据的准确性 | 当视图数据量较大时,重建时间长,资源消耗大 | 速度层视图数据量较小,且能快速重建的情况 |
| 增量更新 | 减少重建时间和资源消耗;能及时反映数据变化 | 需要维护临时表,增加了数据管理的复杂度;可能存在数据不一致的风险 | 速度层视图数据量庞大,重建成本高的情况 |

12. 技术选型决策树

在选择速度层的技术时,需要综合考虑各种因素。下面是一个mermaid决策树,帮助我们做出决策:

graph TD
    classDef decision fill:#FFF6CC,stroke:#FFBC52,stroke-width:2px;
    classDef process fill:#E5F6FF,stroke:#73A6FF,stroke-width:2px;

    A{是否需要从 Hive 或 HDFS 读取数据?}:::decision -->|是| B{是否需要事务支持?}:::decision
    A -->|否| C(VoltDB):::process
    B -->|是| D{是否对随机读写性能要求高?}:::decision
    B -->|否| E{是否需要内置存储?}:::decision
    D -->|是| F(其他支持事务和索引的技术):::process
    D -->|否| G(考虑外部存储结合 Spark SQL):::process
    E -->|是| F
    E -->|否| H(Spark SQL):::process

通过这个决策树,我们可以根据具体需求选择合适的技术。如果需要从Hive或HDFS读取数据,并且需要事务支持和高随机读写性能,可能需要选择其他支持事务和索引的技术;如果对事务支持和随机读写性能要求不高,且不需要内置存储,Spark SQL是一个不错的选择。

13. 实际应用中的注意事项

在实际应用Lambda架构时,除了前面提到的Hive与Spark SQL集成注意事项外,还需要注意以下几点:
- 资源管理 :由于速度层需要处理实时数据,对资源的要求较高。需要合理分配集群资源,避免因资源不足导致系统性能下降。可以通过监控系统实时监测资源使用情况,根据负载情况动态调整资源分配。
- 数据一致性 :虽然速度层和批处理层的视图最终会趋于一致,但在处理过程中可能会存在数据不一致的情况。需要建立数据一致性检查机制,定期检查速度层和批处理层的视图数据,发现不一致时及时进行处理。
- 错误处理 :在数据处理过程中,可能会出现各种错误,如网络故障、数据格式错误等。需要建立完善的错误处理机制,对不同类型的错误进行分类处理,确保系统的稳定性和可靠性。

14. 总结与展望

Lambda架构为实时Hadoop应用提供了一种有效的解决方案,通过批处理层和速度层的结合,能够在保证数据处理准确性的同时,实现近实时的数据查询。虽然Lambda架构存在一些缺点,如代码维护复杂、未打破CAP定理等,但在实际应用中可以通过合理的设计和优化来减轻这些问题的影响。

未来,随着技术的不断发展,Lambda架构可能会与其他架构(如Kappa架构)进行融合,以更好地满足不同场景的需求。同时,对于实时数据处理的性能和准确性要求也会越来越高,需要不断探索和创新,提高Lambda架构的应用效果。

在实际应用中,我们需要根据具体的业务需求和数据特点,综合考虑各种因素,选择合适的架构和技术,以实现高效、稳定的实时数据处理。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值