传统开发的缺点,是对于浏览器的页面,全部都是全局刷新的体验。如果我们只是想取得或是更新页面中的部分信息那么就必须要应用到局部刷新的技术。局部刷新也是有效提升用户体验的一种非常重要的方式。Ajax技术是基于js语言的扩展,能够通过将请求发送给后台,并从后台取得相关数据,然后将数据在页面做局部刷新的重要技术。本教程会通过对ajax的传统使用方式,结合json操作的方式,结合跨域等高级技术的方式,对ajax做一个全面的讲解。什么是Ajax?AJAX = Asynchronous JavaScript and XML(异步的 JavaScript 和XML)。AJAX 是一种在无需重新加载整个网页的情...... Last article READ

Flink可靠性的基石-checkpoint机制详细解析

Flink

在 Flink 中需要端到端精准一次处理的位置有三个:

Flink 端到端精准一次处理

Source 端:数据从上一阶段进入到 Flink 时,需要保证消息精准一次消费。

Flink 内部端:这个我们已经了解,利用 Checkpoint 机制,把状态存盘,发生故障的时候可以恢复,保证内部的状态一致性。不了解的小伙伴可以看下我之前的文章:

Flink可靠性的基石-checkpoint机制详细解析

Sink 端:将处理完的数据发送到下一阶段时,需要保证数据能够准确无误发送到下一阶段。

在 Flink 1.4 版本之前,精准一次处理只限于 Flink 应用内,也就是所有的 Operator 完全由 Flink 状态保存并管理的才能实现精确一次处理。但 Flink 处理完数据后大多需要将结果发送到外部系统,比如 Sink 到 Kafka 中,这个过程中 Flink 并不保证精准一次处理。

在 Flink 1.4 版本正式引入了一个里程碑式的功能:两阶段提交 Sink,即 TwoPhaseCommitSinkFunction 函数。该 SinkFunction 提取并封装了两阶段提交协议中的公共逻辑,自此 Flink 搭配特定 Source 和 Sink(如  Kafka 0.11 版)实现精确一次处理语义(英文简称:EOS,即 Exactly-Once Semantics)。

Flink端到端精准一次处理语义(EOS)

注:以下内容适用于 Flink 1.4 及之后版本

对于 Source 端:Source 端的精准一次处理比较简单,毕竟数据是落到 Flink 中,所以 Flink 只需要保存消费数据的偏移量即可, 如消费 Kafka 中的数据,Flink 将 Kafka Consumer 作为 Source,可以将偏移量保存下来,如果后续任务出现了故障,恢复的时候可以由连接器重置偏移量,重新消费数据,保证一致性。

对于 Sink 端:Sink 端是最复杂的,因为数据是落地到其他系统上的,数据一旦离开 Flink 之后,Flink 就监控不到这些数据了,所以精准一次处理语义必须也要应用于 Flink 写入数据的外部系统,故这些外部系统必须提供一种手段允许提交或回滚这些写入操作,同时还要保证与 Flink Checkpoint 能够协调使用(Kafka 0.11 版本已经实现精确一次处理语义)。

我们以 Flink 与 Kafka 组合为例,Flink 从 Kafka 中读数据,处理完的数据在写入 Kafka 中。

为什么以Kafka为例,第一个原因是目前大多数的 Flink 系统读写数据都是与 Kafka 系统进行的。第二个原因,也是最重要的原因 Kafka 0.11 版本正式发布了对于事务的支持,这是与Kafka交互的Flink应用要实现端到端精准一次语义的必要条件。

当然,Flink 支持这种精准一次处理语义并不只是限于与 Kafka 的结合,可以使用任何 Source/Sink,只要它们提供了必要的协调机制。

Flink 与 Kafka 组合

Flink 应用示例

如上图所示,Flink 中包含以下组件:

一个 Source,从 Kafka 中读取数据(即 KafkaConsumer)

一个时间窗口化的聚会操作(Window)

一个 Sink,将结果写入到 Kafka(即 KafkaProducer)

若要 Sink 支持精准一次处理语义(EOS),它必须以事务的方式写数据到 Kafka,这样当提交事务时两次 Checkpoint 间的所有写入操作当作为一个事务被提交。这确保了出现故障或崩溃时这些写入操作能够被回滚。

当然了,在一个分布式且含有多个并发执行 Sink 的应用中,仅仅执行单次提交或回滚是不够的,因为所有组件都必须对这些提交或回滚达成共识,这样才能保证得到一个一致性的结果。Flink 使用两阶段提交协议以及预提交(Pre-commit)阶段来解决这个问题。

不知道各位小伙伴是否碰到过这样的情况:一个 .c 文件 include 另一个 .h 头文件,使用 Makefile 来构建(编译)应用程序。第一次编译、执行,很正常!但是此时,如果修改了 .h 头文件,再次编译时,就出现问题了:预期的执行流程是:make 发现 .h 头文件的修改时间更新,于是重新编译包含这个头文件的所有 .c 文件。可实际的结果却是:make 并没有识别出 .h 头文件的修改。这是怎么回事呢?让我们一一道来。简单的代码示例一个头文件:hello.h#ifndef _HELLO_#define _HELLO_#define  NUM    1#e......Next article READ