Stateful Serverless 背后的 Flink StateFun 内部机制实现【译】

本篇是 Flink StateFun 的第二篇文章,文中的内容是来自 Stateful Functions Internals: Behind the scenes of Stateful Serverless 的翻译,这篇文章从上层把 Flink StateFun 的内核做了一个比较深入的介绍,个人认为它是一篇很不错的、用来了解 StateFun 内部机制的文章。

阅读更多

Flink StateFun 2.0 浅谈

Stateful Function(简称 StateFun)从 2019 正式对外宣布之后,今年 4 月份已经发了 2.0 版(并且是作为 Apache Flink 项目中的一部分发布),7 月份也发布了 2.1.0 版。在 2.0 的架构中 Function 已经从 JVM 中解耦出来,只需要通过 HTTP/gRPC 来调用即可,新的架构可以充分利用 FAAS 的能力。本篇文章就来简单看下 StateFun 的架构及应用示例,后面还会有陆续有两篇文章来深入剖析一些其内部实现。

阅读更多

Kubenetes 之新手入门篇

近几年来,随着以 Docker 为代表的容器技术的出现,终结了之前 DevOps 中交付和部署环节因环境、配置及程序本身的不同而造成的动辄几种甚至几十种部署配置的困境,将它们统一在容器镜像上。但 Docker 更适用于管理单个容器,一旦开始使用越来越多的容器封装和运行应用程序,必将会导致其管理和编排变得越来越困难。最终,用户不得不对容器实施分组,以便跨所有容器提供网络、安全、监控等服务。于是,以 Kubernetes 为代表的容器编排系统应运而生。本文就是对 Kubernetes 做一个简单的总结,主要从 Kubernetes 架构、组件和核心概念来简单讲述,是一篇关于 Kubernetes 的入门文章。

阅读更多

浅谈 CPU 分支预测技术

最近在看 SQL 优化之 Code Generation 相关的内容,我们知道 Code Generation 是 SQL 优化的大杀器之一,不管是在 Apache Spark 还是 Apache Flink 中都有比较深入的应用(特别是在 Spark 中),Code Generation 最开始是在数据库中应用的,Spark 将其引入到 Spark SQL 的中优化,后来的 Flink 也借鉴了这一思想。Code Generation 是要解决什么问题呢?相信大部分人应该有所了解,简单来说就是减少虚函数调用、尽可能利用 CPU 分支预测的能力(会在 Code Generation 部分详细介绍,这里只需要了解这一背景即可),那么什么是 CPU 分支预测(Wikipedia: CPU Branch Predictor)呢?为什么虚函数调用会极大消耗 CPU 性能呢?这就是本文将要给大家介绍的内容。

阅读更多

Flink 基于 MailBox 实现的 StreamTask 线程模型

本篇文章是 Flink 系列 的第八篇,在介绍 TaskManager 第二部分之前,先来给介绍一下目前 StreamTask 中基于 MailBox 实现的线程模型,这个模型从 1.9 开始实现,在目前发布的 1.10 版本中,基本上已经改造完成,具体 issue 见 FLINK-12477: Change threading-model in StreamTask to a mailbox-based approach,其设计文档见 Change threading-model in StreamTask to a mailbox-based approach,去年,vinoyang 也写了一篇关于它的介绍,见 重磅!Flink 将重构其核心线程模型。因为 Flink 1.10 已经发布,本篇关于 MailBox 实现的介绍会基于 1.10 最新的代码来讲述(系列的其他篇,没有说明的话,默认还是以 1.9 的代码为例),这个功能在 1.9 中还并没有完全完成,所以本文以 1.10 代码为例讲述。

阅读更多

Flink TaskManager 详解(一)

本篇文章是 Flink 系列 的第七篇,这篇文章主要会讲述 Flink 中的 TaskManager 的一些内容,TaskManager 是 Flink 的 worker 节点,它负责 Flink 中本机 slot 资源的管理以及具体 task 的执行。TaskManager 上的基本资源单位是 slot,一个作业的 task 最终会部署在一个 TM 的 slot 上运行,TM 会负责维护本地的 slot 资源列表,并来与 Flink Master 和 JobManager 通信,预计将会通过两篇左右的文章来向大家揭秘 TaskManager 内部的实现原理。另外,本篇将采用先提出问题,然后再根据源码实现去解答这些问题的形式叙述,如果大家有其他建议,欢迎(博客/公众号)留言反馈。

阅读更多

Flink JobManager 详解

本篇文章是 Flink 系列 的第六篇,紧接着上篇文章,本篇主要讲述 Flink Master 中另一个组件 —— JobManager(在源码中对应的实现类是 JobMaster)。每个作业在启动后,Dispatcher 都会为这个作业创建一个 JobManager 对象,用来做这个作业相关的协调工作,比如:调度这个作业的 task、触发 Checkpoint 以及作业的容错恢复等。另外,本篇文章也将会看下一个作业在生成 ExecutionGraph 之后是如何在集群中调度起来的。

阅读更多

Flink Master 详解

本篇文章是 Flink 系列 的第五篇,从这篇开始会向大家介绍一下 Flink Runtime 中涉及到的分布式调度相关的内容。Flink 本身也是 Master/Slave 架构(当前的架构是在 FLIP-6 - Flink Deployment and Process Model - Standalone, Yarn, Mesos, Kubernetes, etc 中实现的),这个 Master 节点就类似于 Storm 中 Nimbus 节点,它负责整个集群的一些协调工作,Flink 中 Master 节点主要包含三大组件:Flink Resource Manager、Flink Dispatcher 以及为每个运行的 Job 创建一个 JobManager 服务,本篇文章主要给大家介绍一下 Flink 中 Master 节点相关内容。

阅读更多

Flink 如何生成 ExecutionGraph

本篇文章是 Flink 系列 的第四篇,紧接着前面两篇文章,在前两篇文章中介绍的 StreamGraph 和 JobGraph 都是在 client 端生成的,本文将会讲述 JobGraph 是如何转换成 ExecutionGraph 的。当 JobGraph 从 client 端提交到 JobManager 端后,JobManager 会根据 JobGraph 生成对应的 ExecutionGraph,ExecutionGraph 是 Flink 作业调度时使用到的核心数据结构,它包含每一个并行的 task、每一个 intermediate stream 以及它们之间的关系,本篇将会详细分析一下 JobGraph 转换为 ExecutionGraph 的流程。

阅读更多

Flink Streaming 作业如何转化为 JobGraph

本篇文章是 Flink 系列 的第三篇,紧接着上一篇文章,本文主要讲述 StreamGraph 是如何转换成 JobGraph 的,在前面的文章中,我们知道 StreamGraph 是根据用户作业的处理逻生成初始的逻辑计划,它并没有做任何的优化,而 JobGraph 将会在原来的基础上做相应的优化(主要是算子的 Chain 操作,Chain 在一起的算子将会在同一个 task 上运行,会极大减少 shuffle 的开销)。刚开始接触的同学可能会有一个疑问,为什么要有 StreamGraph 和 JobGraph 两层的 Graph,这里最主要的原因是为兼容 batch process,Streaming process 最初产生的是 StreamGraph,而 batch process 产生的则是 OptimizedPlan,但是它们最后都会转换为 JobGraph,本文主要是以 Streaming 作业的 StreamGraph 转换为 JobGraph 的处理流程来介绍。

阅读更多

Flink DataStream API 概述及作业如何转换为 StreamGraph

本篇文章是 Flink 系列 的第二篇,将会给大家讲述一个 Flink 作业(DataStream 高阶 API 为例的作业)是如何转换为 StreamGraph 的, StreamGraph 可以认为是一个还未经过优化处理的逻辑计划,它完全是在 Client 端生成的。StreamGraph 然后再经过优化转换为 JobGraph,Client 端向 JobManager 提交的作业就是以 JobGraph 的形式提交的,也就是说对于 JobManager 来说,它从客户端接收的作业实际上就是一个 JobGraph,然后它再对 JobGraph 做相应处理,生成具体的物理执行计划进行调度。

阅读更多

Apache Flink 初探

本篇文章是 Flink 系列 的第一篇,最近计划花个一到两个月的时间以最新的 Flink-1.9 代码为例把 Flink 的主要内容梳理一遍,这个系列文章的主要内容见 Flink 源码分析,这个 issue 拖了好几个月,现在终于开动了,不容易。梳理的过程也是个人强化学习的过程,博客中有问题的地方也欢迎各位指正(邮件联系 or disqus 评论都行,我这边都会及时回复)。

阅读更多

Paper 阅读: Distributed Snapshots: Determining Global States of Distributed Systems

今天对分布式系统领域的一篇经典论文 —— Chandy-Lamport 算法做了一下总结,这篇论文对于分布式快照算法产生了非常巨大的影响,比如:Apache Flink、Apache Spark 的 Structured Streaming、Ray 等分布式计算引擎都是使用的这个算法做快照。这篇论文的其中一位作者 —— Lamport,他也是 Paxos 算法的提出者,2013 年图领奖得主(图领奖是计算机领域的诺贝尔奖,目前只有一位华裔 —— 姚期智院士获得过这个殊荣,没错,就是清华交叉学院姚班的姚院士)。这篇论文发表于 1985 年,算法的由来可以参考下面的小段子:

阅读更多

Paper 阅读: Lightweight Asynchronous Snapshots for Distributed Dataflow

本篇文章是对 Lightweight Asynchronous Snapshots for Distributed Dataflow 的一个总结,从文章题目也可以看出文章的主题 —— 分布式 dataflow 的轻量级异步 snapshot 算法,它是 Flink 团队在 2015 年发表的论文,主要讲述了对于 Streaming System 如何做 snapshot 的,它选取的是 Chandy-Lamport 算法(论文见 Distributed Snapshots: Determining Global States of Distributed Systems),关于这个算法后面会单独一篇文章来总结。在 Lightweight Asynchronous Snapshots for Distributed Dataflow 这篇论文中,作者更多向我们表达的是 Chandy-Lamport 算法如何在 Flink 中落地的以及如何解决分布式 dataflow 做 snapshot 时遇到的痛点。

阅读更多

Paper 阅读: Real-Time Machine Learning: The Missing Pieces

这周抽空看了关于 ray 的一篇论文,论文是 2017 年发表的(见:Real-Time Machine Learning: The Missing Pieces,他们比较新的论文是 18 年发表的,见:Ray: A Distributed Framework for Emerging AI Applications),虽然论文描述的架构与现在 ray 真正的构架实现已经有了较大的不同,主要也是 ray 这两年发展比较快,架构做了很多的优化,不过本篇论文依然值得仔细阅读学习 一下的,这篇论文也展示了 ray 最初设计实现的出发点。

阅读更多

Apache Calcite 优化器详解(二)

紧接上篇文章Apache Calcite 处理流程详解(一),这里是 Calcite 系列文章的第二篇,后面还会有文章讲述 Calcite 的实践(包括:如何开发用于 SQL 优化的 Rule)。本篇文章主要介绍 Apache Calcite 优化器部分的内容,会先简单介绍一下 RBO 和 CBO 模型,之后详细讲述 Calcite 关于这两个优化器的实现 —— HepPlanner 和 VolcanoPlanner,文章内容都是个人的一些理解,由于也是刚接触这块,理解有偏差的地方,欢迎指正。

阅读更多

Apache Calcite 处理流程详解(一)

关于 Apache Calcite 的简单介绍可以参考 Apache Calcite:Hadoop 中新型大数据查询引擎 这篇文章,Calcite 一开始设计的目标就是 one size fits all,它希望能为不同计算存储引擎提供统一的 SQL 查询引擎,当然 Calcite 并不仅仅是一个简单的 SQL 查询引擎,在论文 Apache Calcite: A Foundational Framework for Optimized Query Processing Over Heterogeneous Data Sources 的摘要(摘要见下面)部分,关于 Calcite 的核心点有简单的介绍,Calcite 的架构有三个特点:flexible, embeddable, and extensible,就是灵活性、组件可插拔、可扩展,它的 SQL Parser 层、Optimizer 层等都可以单独使用,这也是 Calcite 受总多开源框架欢迎的原因之一。

阅读更多

BookKeeper 原理浅谈

接着之前的一篇文章 BookKeeper 集群搭建及使用,本文是 BookKeeper 系列的第二篇,短期来看应该也是最后一篇,本篇文章主要聚焦于 BookKeeper 内核的实现机制上,会从 BookKeeper 的基本概念、架构、读写一致性实现、读写分离实现、容错机制等方面来讲述,因为我并没有看过 BookKeeper 的源码,所以这里的讲述主要还是从原理、方案实现上来介绍,具体如何从解决方案落地到具体的代码实现,有兴趣的可以去看下 BookKeeper 的源码实现。

阅读更多

如何高效学习

在这个知识爆炸、科技日新月异的时代,技术的变化远比我们想象的要快很多,这就对工程师的要求就提高了很多,特别是对于那些在技术上有所追求的工程师而言。对于一些互联网大厂,学习能力也成了面试中重点考察的内容。如何快速学习、掌握一门新的技术,如何提高自己的学习效率,对于有一定工作经验的人来说,可能每个人都有一个自己的学习方法论,但是我们也需要去学习借鉴别人(特别是那些有一定技术影响力的技术大咖)的经验,来不断更新和完善自己的方法轮。今天这篇《高效学习》,就是与大家一起探讨技术学习的方法论,本文的内容主要来自耗子叔的《左耳听风 —— 高效学习篇》,中间会穿插个人的一些经验,算是对这个系列的一个总结。如果想看原文内容,欢迎订阅耗子叔的这个专栏,这个专栏质量还是非常高的,耗子叔推荐了很多优秀的学习资源(通过文章末尾处的二维码链接购买)。

阅读更多

Kafka Exactly-Once 之事务性实现

这篇文章是 Kafka Exactly-Once 实现系列的第二篇,主要讲述 Kafka 事务性的实现,这部分的实现要比幂等性的实现复杂一些,幂等性实现是事务性实现的基础,幂等性提供了单会话单 Partition Exactly-Once 语义的实现,正是因为 Idempotent Producer 不提供跨多个 Partition 和跨会话场景下的保证,因此,我们是需要一种更强的事务保证,能够原子处理多个 Partition 的写入操作,数据要么全部写入成功,要么全部失败,不期望出现中间状态。这就是 Kafka Transactions 希望解决的问题,简单来说就是能够实现 atomic writes across partitions,本文以 Apache Kafka 2.0.0 代码实现为例,深入分析一下 Kafka 是如何实现这一机制的。

阅读更多