您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
论SparkStreaming的数据可靠性和一致性
 
作者 叶琪  来源:程序员杂志  火龙果软件  发布于 2015-6-26
   次浏览      
 

摘要:眼下大数据领域最热门的词汇之一便是流计算了,而其中最耀眼的无疑是来自Spark社区的SparkStreaming项目。 对于流计算而言,最核心的特点毫无疑问就是它对低时的需求,但这也带来了相关的数据可靠性问题。

2Driver HA

由于流计算系统是长期运行、且不断有数据流入,因此其Spark守护进程(Driver)的可靠性至关重要,它决定了Streaming程序能否一直正确地运行下去。

Driver实现HA的解决方案就是将元数据持久化,以便重启后的状态恢复。如图一所示,Driver持久化的元数据包括:

Block元数据(图1中的绿色箭头):Receiver从网络上接收到的数据,组装成Block后产生的Block元数据;

Checkpoint数据(图1中的橙色箭头):包括配置项、DStream操作、未完成的Batch状态、和生成的RDD数据等;

Driver失败重启后:

恢复计算(图2中的橙色箭头):使用Checkpoint数据重启driver,重新构造上下文并重启接收器。

恢复元数据块(图2中的绿色箭头):恢复Block元数据。

恢复未完成的作业(图2中的红色箭头):使用恢复出来的元数据,再次产生RDD和对应的job,然后提交到Spark集群执行。

通过如上的数据备份和恢复机制,Driver实现了故障后重启、依然能恢复Streaming任务而不丢失数据,因此提供了系统级的数据高可靠。

可靠的上下游IO系统

流计算主要通过网络socket通信来实现与外部IO系统的数据交互。由于网络通信的不可靠特点,发送端与接收端需要通过一定的协议来保证数据包的接收确认和失败重发机制。

不是所有的IO系统都支持重发,这至少需要实现数据流的持久化,同时还要实现高吞吐和低时延。在SparkStreaming官方支持的data source里面,能同时满足这些要求的只有Kafka,因此在最近的SparkStreaming release里面,也是把Kafka当成推荐的外部数据系统。

除了把Kafka当成输入数据源(inbound data source)之外,通常也将其作为输出数据源(outbound data source)。所有的实时系统都通过Kafka这个MQ来做数据的订阅和分发,从而实现流数据生产者和消费者的解耦。

一个典型的企业大数据中心数据流向视图如图3所示:

除了从源头保证数据可重发之外,Kafka更是流数据Exact Once语义的重要保障。Kafka提供了一套低级API,使得client可以访问topic数据流的同时也能访问其元数据。SparkStreaming每个接收的任务都可以从指定的Kafka topic、partition和offset去获取数据流,各个任务的数据边界很清晰,任务失败后可以重新去接收这部分数据而不会产生“重叠的”数据,因而保证了流数据“有且仅处理一次”。

可靠的接收器

在Spark 1.3版本之前,SparkStreaming是通过启动专用的Receiver任务来完成从Kafka集群的数据流拉取。

Receiver任务启动后,会使用Kafka的高级API来创建topicMessageStreams对象,并逐条读取数据流缓存,每个batchInerval时刻到来时由JobGenerator提交生成一个spark计算任务。

由于Receiver任务存在宕机风险,因此Spark提供了一个高级的可靠接收器-ReliableKafkaReceiver类型来实现可靠的数据收取,它利用了Spark 1.2提供的WAL(Write Ahead Log)功能,把接收到的每一批数据持久化到磁盘后,更新topic-partition的offset信息,再去接收下一批Kafka数据。万一Receiver失败,重启后还能从WAL里面恢复出已接收的数据,从而避免了Receiver节点宕机造成的数据丢失(以下代码删除了细枝末节的逻辑):

启用WAL后,虽然Receiver的数据可靠性风险降低了,但却由于磁盘持久化带来的开销,系统整体吞吐率会明显下降。因此,最新发布的Spark 1.3版本,SparkStreaming增加了使用Direct API的方式来实现Kafka数据源的访问。

引入了Direct API后,SparkStreaming不再启动常驻的Receiver接收任务,而是直接分配给每个Batch及RDD最新的topic partition offset。job启动运行后Executor使用Kafka的simple consumer API去获取那一段offset的数据。

这样做的好处不仅避免了Receiver宕机带来数据可靠性的风险,也由于避免使用ZooKeeper做offset跟踪,而实现了数据的精确一次性(以下代码删除了细枝末节的逻辑):

预写日志 Write Ahead Log

Spark 1.2开始提供预写日志能力,用于Receiver数据及Driver元数据的持久化和故障恢复。WAL之所以能提供持久化能力,是因为它利用了可靠的HDFS做数据存储。

SparkStreaming预写日志机制的核心API包括:

管理WAL文件的WriteAheadLogManager

读/写WAL的WriteAheadLogWriter和WriteAheadLogReader

基于WAL的RDD:WriteAheadLogBackedBlockRDD

基于WAL的Partition:WriteAheadLogBackedBlockRDDPartition

以上核心API在数据接收和恢复阶段的交互示意图如图4所示。

从WriteAheadLogWriter的源码里可以清楚看到,每次写入一块数据buffer到HDFS后都会调用flush方法去强制刷入磁盘,然后才去取下一块数据。因此receiver接收的数据是可以保证持久化到磁盘了,因而做到较好的数据可靠性。

结束语

得益于Kafka这类可靠的data source以及自身的checkpoint/WAL等机制,SparkStreaming的数据可靠性得到了很好的保证,数据能保证“至少一次”(at least once)被处理。但由于其outbound端的一致性实现还未完善,因此Exact once语义仍然不能端到端保证。SparkStreaming社区已经在跟进这个特性的实现(SPARK-4122),预计很快将合入trunk发布。

作者简介:叶琪,华为软件公司Universe产品部高级架构师,专注于大数据底层分布式存储和计算基础设施,是华为软件公司Hadoop发行版的主要架构师,目前兴趣点在流计算与Spark。

   
次浏览       
相关文章

基于EA的数据库建模
数据流建模(EA指南)
“数据湖”:概念、特征、架构与案例
在线商城数据库系统设计 思路+效果
 
相关文档

Greenplum数据库基础培训
MySQL5.1性能优化方案
某电商数据中台架构实践
MySQL高扩展架构设计
相关课程

数据治理、数据架构及数据标准
MongoDB实战课程
并发、大容量、高性能数据库设计与优化
PostgreSQL数据库实战培训
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

MySQL索引背后的数据结构
MySQL性能调优与架构设计
SQL Server数据库备份与恢复
让数据库飞起来 10大DB2优化
oracle的临时表空间写满磁盘
数据库的跨平台设计
更多...   


并发、大容量、高性能数据库
高级数据库架构设计师
Hadoop原理与实践
Oracle 数据仓库
数据仓库和数据挖掘
Oracle数据库开发与管理


GE 区块链技术与实现培训
航天科工某子公司 Nodejs高级应用开发
中盛益华 卓越管理者必须具备的五项能力
某信息技术公司 Python培训
某博彩IT系统厂商 易用性测试与评估
中国邮储银行 测试成熟度模型集成(TMMI)
中物院 产品经理与产品管理
更多...