事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity)。一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency)。事务必须是使数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是密切相关的。
隔离性(isolation)。一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。
持久性(durability)。持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
Spark Streaming中的事务
1. Exactly once容错
2. 数据输出不重复
从事务视角探索SparkStreaming架构机制
1、SparkStreaming是以批处理的方式处理数据,在SparkStreaming程序启动的时候,就会为程序分配好了相应的资源,且在程序执行的过程中SparkStreaming还可以动态的伸缩资源,所以一般情况下是不会出现问题。
2、SparkStreaming程序一般分成两块,一块是Driver,另一块是Executor。Receiver接收到数据后不断的将元数据信息发送给Driver,Driver接收到元数据信息后先进行CheckPoint处理。CheckPoint主要有Block MetaData、DStreamGraph、Job的状态信息 等(当然Configuration(含有Spark Conf、Spark Streaming等配置信息)在程序启动之后也会被checkpoint下来)。Receiver可以在多个Executor节点的上执行Job。
必须要有可靠的数据来源和可靠的Receiver、整个应用程序的MetaData必须进行CheckPoint、通过WAL来保证数据安全。
Spark1.3的时候为了避免WAL的性能损失和实现Exactly Once而提供了Kafka direct api,把Kafka作为文件存储系统,此时Kafka兼具有流的优势和文件系统的优势,至此,Spark Streaming+Kafka就构建了完美的流处理世界!数据不需要copy副本,不需要WAL性能损耗,不需要Receiver,而直接通过kafka direct api直接消费数据,所有的Executors通过kafka api直接消费数据,直接管理offset,所以也不会重复消费数据;事务一致性就实现了!
数据丢失及其具体的解决方法:
在Receiver收到数据且Job处于Driver的调度之中,但Executor开始计算数据的时候如果Driver突然崩溃,此时Executor会被Kill掉,那么Executor中的数据就会丢失,此时就必须通过例如WAL机制让所有的数据通过类似HDFS的方式进行安全性容错处理,从而解决Executor被Kill掉后导致数据丢失可以通过WAL机制恢复回来。
数据重复读取的情况:
在Receiver收到数据且保存到了hdfs时Receiver崩溃,此时持久化引擎没有来得及进行updateOffset,Receiver重新启动后就会从管理Kafka的ZooKeeper中再次读取元数据从而导致重复读取元数据;从SparkStreaming来看是成功的,但是Kafka认为是失败的(因为Receiver奔溃时没有及时更新offsets到ZooKeeper中)重新恢复时会重新消费一次,此时会导致数据重新消费的情况。
性能损失:
通过WAL方式会极大的损伤SparkStreaming中的Receiver接收数据的性能。
如果通过Kafka作为数据来源的话,Kafka中有数据,然后Receiver接受数据的时候又会有数据副本,这个时候其实是存储资源的浪费。(重复读取数据解决办法,读取数据时可以将元数据信息放入内存数据库中,再次计算时检查元数据是否被计算过)。
关于Spark Streaming数据输出多次重写及解决方案:
为什么会有这个问题,因为SparkStreaming在计算的时候基于SparkCore,SparkCore天生会做以下事情导致SparkStreaming的结果(部分)重复输出:
1. Task重试;
2. 慢任务推测;
3. Stage重复;
4. Job重试;
对应的解决方案:
1. 一个任务失败就是job 失败,设置spark.task.maxFailures次数为1;
2. 设置spark.speculation为关闭状态(因为慢任务推测其实非常消耗性能,所以关闭后可以显著的提高Spark Streaming处理性能)
3. Spark streaming on kafka的话,假如job失败后可以设置kafka的auto.offset.reset为largest的方式会自动恢复job的执行。
可以通过transform和foreachRDD基于业务逻辑代码进行逻辑控制来实现数据不重复消费和输出不重复!这两个方式类似于Spark Streaming的后门,可以做任意想象的控制操作!
资料来源于:
DT_大数据梦工厂(Spark发行版本定制)微信公众号:DT_Spark
新浪微博:http://www.weibo.com/ilovepains
如果您对大数据Spark感兴趣,可以免费听由王家林老师每天晚上20:00开设的Spark永久免费公开课,地址YY房间号:68917580