Spark Streaming的Exactly-One的事务处理

来源:互联网 发布:php开源文件管理系统 编辑:程序博客网 时间:2024/05/16 08:25

Spark Streaming事务处理彻底掌握至关重要

Spark Streaming的事务处理和关系型数据库的事务的概念有所不同,关系型数据库事务关注的是语句级别的一致性,例如银行转账。而Spark Streaming的事务关注的是某次job执行的一致性。也就是如何保证Job在处理数据的过程中做到如下两点:

  • 不丢失数据
  • 不重复处理数据

SparkStreaming程序执行架构大致如下:

SparkStream架构图

事务性处理:能够处理且只被处理一次能够输出且只输出一次

Exacily Once的事务处理:

  1. 数据零丢失:必须有可靠的数据来源和可靠的Receiver,且整个应用程序的metadata必须进行checkpoint,且通过WAL来保证数据安全;
  2. Spark Streaming 1.3的时候为了避免WAL的性能损失和实现Exacily Once而提供了Kafka Direct API。把Kafka作为文件存储系统!此时兼具有流的优势和文件系统的优势,至此,Spark Streaming+Kafka就构建了完美的流处理世界!!!所有的Executor通过Kafka API直接消费数据,直接管理Offset,所以也不会重复消费数据。事务实现啦!

数据丢失及其具体的解决方式:

  1. 在Receiver收到数据且通过Driver的调度Executor开始计算数据的时候如果Driver突然崩溃,则此时Executor会被Kill掉,那么Executor中的数据就会丢失,此时就必须通过例如WAL的方式让所有的数据都通过例如HDFS的方式首先进行安全性容错处理,此时如果Executor中的数据丢失的话就可以通过WAL恢复回来。

数据重复读取的情况:

在Receiver收到数据且保存到了HDFS等持久化引擎,但是没有来得及进行updateOffset,此时Receiver崩溃后重新启动就会通过管理 Kafka的Zookeeper中元数据再次重复读取数据,但是此时Spark Streaming认为是成功的,但是Kafka认为是失败的(因为没有更新Offset到Zookeeper中),此时就会导致数据重新消费的情况。

性能损失:

  1. 通过WAL方式会极大的损伤Spark Streaming中Receiver接受数据的性能
  2. 如果通过Kafka作为数据来源的话,Kafka中有数据,然后Receiver接收的时候又会有数据副本,这个时候其实是存储资源的浪费。

关于Spark Streaming数据输出多次重写及其解决方案:

  1. 为什么会有这个问题:因为Spark Streaming在计算的时候基于Spark Core,Spark Core天生会做以下事情导致Spark Streaming的结果(部分)重复。

    Task重试 慢任务推测 Stage重复 Job重试

  2. 具体解决方案:

  • 设置spark.task.maxFailures最大失败次数为1次
  • 设置spark.speculation为关闭状态(因为慢任务推测其实非常消耗性能,所以关闭后可以显著提高Spark Streaming处理性能)
  • Spark Streaming on Kafka的话:Job失败后可以设置auto.offset.reset为"largest"的方式

最后再次强调

可以通过Transform和foreachRDD基于业务逻辑代码进行逻辑控制来实现数据不重复消费和输出不重复!这两个方法类似于Spark Streaming的后门,可以做任意想象的控制操作!

0 0
原创粉丝点击