关于apache:博文推荐|深入解析-Apache-Pulsar-中的事务

31次阅读

共计 5751 个字符,预计需要花费 15 分钟才能阅读完成。

对于 Apache Pulsar

Apache Pulsar 是 Apache 软件基金会顶级我的项目,是下一代云原生分布式音讯流平台,集音讯、存储、轻量化函数式计算为一体,采纳计算与存储拆散架构设计,反对多租户、长久化存储、多机房跨区域数据复制,具备强一致性、高吞吐、低延时及高可扩展性等流数据存储个性。

GitHub 地址:http://github.com/apache/pulsar/

原文转载于 StreamNative,原作者李鹏辉,地址:https://streamnative.io/en/bl…。本文译者是资飞。

本系列上一篇文章《基于 Pulsar 事务实现的 Exactly-Once(准确一次)语义》介绍了在 Apache Pulsar 中,能够通过启用 Transaction API 保障准确一次语义。本文将具体介绍多种消息传递语义,包含:

  • 通过幂等 producer 反对单个 topic 准确一次语义
  • 事务 API
  • Pulsar 与 Flink 集成时端对端仅且只解决一次语义

本文将深刻解析 Apache Pulsar 中的事务,帮忙读者相熟 Pulsar 事务 API 的次要概念,以便后续应用。

为什么须要事务?

事务加强了消息传递语义和流处理过程中解决保障(例如:应用 Pulsar Functions 或与其余流解决引擎集成)。流解决通常体现为“生产 - 解决 - 生产”,在一个数据流中生产和生产(例如:Pulsar Topic)。

随着流解决的衰亡,对具备更强解决保障的流解决利用的需要也在一直增长。例如,金融机构应用流解决引擎来解决用户的借贷业务。这种场景要求每条音讯都只解决一次且无异样。

换句话说,如果流解决利用生产 A 音讯 并将生成的后果当作音讯 B(B = f(A)),那么准确一次解决保障意味着,只有在胜利生成音讯 B 时,A 才会被标记为已生产,反之亦然。

在 Pulsar 2.8.0 之前,应用 Apache Pulsar 构建流解决利用时,实现准确一次解决保障的操作都不简略。将 Pulsar 与流解决引擎(如 Flink)集成可能能够实现准确一次保障。例如,你能够应用 Flink 准确一次读取从 Pulsar topic 中的音讯,但不能准确一次将后果写入到 Pulsar topic。

当为 Pulsar producer 和 consumer 配置至多传递一次语义时,流解决利用无奈在以下场景中实现准确一次解决语义:

  • 反复写入:因为外部重试逻辑,producer 可能会屡次写入同一条音讯。幂等 producer 通过音讯去重来解决这个问题。
  • 应用程序解体:流解决应用程序可能在任何时候解体。如果应用程序在写入后果音讯 B 之后,但未将源音讯 A 设为已生产(即 ack)时解体,应用程序在重启后会重新处理源音讯 A,导致音讯 B 反复写入到输入 topic,违反了准确一次解决的保障。
  • 僵尸应用程序:在分布式环境中,流解决利用可能会从网络中分区(如网络长期不可用)。通常,同一流解决应用程序的多个新实例会主动启动,以替换“失落”的实例。在这种状况下,同一解决应用程序的多个实例可能在并行运行,这些实例会解决雷同的输出 topic,并将后果写入雷同的输入 topic,导致输入反复的音讯,违反准确一次解决语义。

Pulsar 在 2.8.0 版本中引入了新事务 API,旨在解决在上述场景 2、3 中不能实现准确一次解决语义的问题。

事务语义

事务 API 使流解决应用程序可能在一个原子操作中生产、解决和生产音讯。这意味着,在同一事务中的一批音讯能够从许多 topic 分区接管、生产和确认。解决同一事务的所有操作为一个整体,要么全副胜利,要么全副失败。

那么事务 API 如何解决上述三个问题呢?

跨多 topic 的原子写入与确认

首先,事务 API 反对将多个 Pulsar topic 作为单个整体进行原子写入和原子确认。在一个事务中生产或生产的所有音讯一起被胜利写入或确认,或者没有音讯被胜利写入或确认。例如,处理过程中的谬误可能导致事务停止,在这种状况下,任何 consumer 都不会生产到该事务生成的任何音讯。这对“生产 - 解决 - 生产”原子操作意味着什么?

假如应用程序生产来自 topic T0 的音讯 A,并在对音讯 A(B=f(A))利用一些转换逻辑后生成后果音讯 B 到 topic T1,那么仅当音讯 A 和音讯 B 被认为胜利地一起生产和公布,或者基本不被生产也不被公布(即什么都不做)时,此时生产 - 解决 - 生产整个操作才是原子的。只有当音讯 A 被胜利确认时,咱们才认为是在 topic T0 中生产了此音讯。

事务 API 确保音讯 A 的确认和音讯 B 的写入以原子操作产生,此时才认为“生产 - 解决 - 生产”整个操作为一个原子操作。

通过条件确认隔离僵尸实例

咱们通过条件确认来解决僵尸实例的问题。条件确认指当两个事务试图确认同一音讯时,Pulsar 保障只有一个事务能够确认胜利,另一个事务的确认会被停止。

读事务音讯

读取由事务写入的音讯会有怎么的保障?

只有在事务已提交时,Pulsar broker 才会向 consumer 散发事务音讯。换句话说,如果事务仍在进行中,则 broker 不会散发其中的音讯;也不会传递处于停止状态的事务音讯。

然而,Pulsar 并不保障在一个提交的事务中生产的音讯会同时被生产。有以下几个起因:但 Pulsar 不保障同时生产在同一个提交事务中生产的音讯,起因如下:

  1. 参加提交事务的 topic 分区数量泛滥,consumer 不肯定能生产到所有分区上的音讯,因而无奈读取该事务中生成的所有音讯。
  2. Consumer 的承受队列大小或缓冲区大小可能不同,因而只能接管肯定数量(可能是任意值)的音讯。

事务 API

事务个性次要是服务器端协定级个性。目前事务 API 只反对 Java 客户端(将来将会反对更多语言的客户端)。用 Java 编写,应用 Pulsar 事务 API 的“生产 - 解决 - 生产”应用程序示例如下:

让咱们按步骤剖析这个例子。

事务的实现

本节简要概述事务 API 引入的新组件和新申请流程。你能够浏览相干文档,或回看 Pulsar 北美峰会上的相干视频理解更多对于事务的详细信息。

本节只介绍与事务相干的次要概念,为用户调试或调优事务,提供参考。

组件

事务协调器和事务日志

事务协调器(Transaction Coordinator,TC)保护与事务交互的 topic 和订阅。提交事务时,事务协调器与 topic owner broker 交互以实现事务。

事务协调器(TC)是一个在 Pulsar broker 中运行的模块,全程保护事务,并阻止事务进入谬误状态。事务协调器也处理事务超时,确保事务在超时后停止。

所有事务元数据都保留在事务日志中,而事务日志保留在 Pulsar topic 中。事务协调器解体后,仍能够从事务日志中复原事务的元数据。

每个事务协调器都有事务日志 topic 的分区子集,也就是说,(事务协调器所在的)broker 是(topic)分区的 owner。

每个事务都有惟一的事务 id(TxnID),长度为 128 位。最高的 16 位用于示意事务日志所在的 topic 分区,其余位为依据 TC(此事务日志所在的 topic 分区的 owner)生成的枯燥递增数值。

值得注意的是,事务日志 topic 只存储事务的状态,不存储事务中的音讯。音讯存储在 topic 分区中。事务能够处于多种状态,如“Open”、“Prepare commit”和“committed”。事务日志中存储事务的状态信息和相干的元数据。

事务缓冲区

事务中的音讯(原存储在 topic 分区中)存储在对应的 topic 分区所在的 broker 事务缓冲区中。在提交事务前,事务缓冲区中的音讯对 consumer 不可见。事务停止时,事务缓冲区中的音讯将被抛弃。

Pending ack 状态

在提交事务前,事务中的音讯确认处在 pending ack 状态。如果音讯处于 pending ack 状态,则在事务停止时,音讯未从 pending ack 状态中移除,其余事务无奈确认该音讯。(音讯不能被其余事务确认直到此音讯移除 pending ack 状态。)

pending ack 状态保留在 pending ack 日志中。pending ack 日志存储在游标日志中。重启后 broker 能够从 pending ack 日志还原事务状态,保障 ack 不会失落。

数据流

从下层 API 可看出,数据流能够分为多个步骤:

  • 开启事务;
  • 公布事务音讯;
  • 确认事务音讯;
  • 实现事务。

开启事务

在事务开始时,Pulsar 客户端向定位事务协调器申请新的事务 ID。收到申请后,事务协调器为事务调配事务 ID。而后,主动生成该事务的日志,并记录其 id 和状态(OPEN,如步骤 1a 所示),保障事务状态长久化(不用放心事务协调器解体)。记录事务状态后,TC 将事务 ID 返回给 Pulsar 客户端。

公布事务音讯

在 Pulsar 客户端向新的 topic 分区发送音讯之前,客户端申请 TC 将此 topic 分区增加到事务中。TC 将分区的更改记录并长久存储在其事务日志中(如 2.1a 所示),确保 TC 晓得事务正在解决的所有分区。因而,在 end-partition 时,TC 能够提交或停止此 transaction 在所有分区上的变更。

Pulsar 客户端开始向分区发送音讯,此发送流程与失常的音讯发送流程完全相同。惟一的区别是事务生成的批音讯蕴含事务 id。接管该批音讯的 broker 查看该批音讯是否属于某个事务。如果不属于某个事务,那么 broker 会失常解决写操作;否则,broker 将该批音讯写入分区的事务缓冲区。

携带事务 Ack 音讯

Pulsar 客户端第一次订阅被确认为事务的一部分时向 TC 发送申请。在步骤 2.3a 中,TC 记录对事务的新订阅,确保 TC 晓得事务正在解决的所有订阅,因而 TC 能够在 EndTxn 阶段提交或停止对每个订阅的更改。

Pulsar 客户端开始 ack 订阅上的音讯,此事务确认流程与失常确认流程雷同,但事务确认申请中蕴含事务 id。接管 ack 申请的 broker 查看此 ack 是否属于某个事务,如果属于某个事务,则 broker 将音讯标记为:PENDING_ACK 状态,即在提交或停止该 ack 前,其余 consumer 不能 ack 或 nack 此音讯,从而确保当两个事务在 ack 同一条音讯时,只有一个事务能够 ack 胜利,另一个则将被停止。

Pulsar 客户端尝试确认音讯时,如果在单个确认和累积确认中都检测到抵触,则会停止整个事务。

实现事务

在事务完结时,应用程序将决定提交或停止事务。如果在确认音讯时检测到抵触,也能够停止事务。

当事务实现时,Pulsar 客户端能够向 TC 申请完结事务,并用一个字段标识事务是提交还是停止。

TC 将提交或停止音讯写入其事务日志(如 3.1a 所示),并向该事务中波及的所有分区发送提交或停止事务申请。如 3.2 所示。

当接管到申请的所有分区都胜利提交或停止事务后,TC 将提交或停止的音讯写入其事务日志。如图中 3.3 所示。

事务性能如何

本文曾经解释了事务的语义及工作原理,接下来咱们来看看事务的性能。

事务 producer 性能

事务仅导致中等水平的写放大。额定写入呈现的次要起因如下:

  • 对于每个事务,producer 都会收到额定的申请,以便向事务协调器注册 topic 分区。
  • 当事务实现时,向参加该事务的所有分区写入事务标记。
  • TC 将事务状态变更写入事务日志。所有增加到事务的 topic 分区的状态(xxx)都会被 / 更新 / 记录(下来)。(“筹备提交”和“已提交”状态)。

开销与作为事务局部写入的音讯数无关。因而,进步吞吐量的要害是每个事务蕴含大量的音讯。缩小音讯数量或缩短事务提交工夫都会升高吞吐量。

减少事务持续时间的结果是减少了端到端提早。回忆一下,consumer 并不会读取到未提交的事务音讯。因而,提交距离越长,consumer 期待的工夫就越长(不得不期待),从而减少了端到端提早。

事务 consumer 的性能

事务 consumer 比 producer 简略得多。所有的(事务)逻辑都由 Pulsar broker 服务器端实现,broker 仅散发已实现的事务音讯。

扩大浏览

本文简要介绍了 Apache Pulsar 事务的相干信息。你能够浏览以下材料,深刻理解 Pulsar 事务:

  • 设计文档:介绍公共接口、数据流和组件的官网文档,文档中还蕴含如何实现事务组件、如何处理事务申请、如何革除事务数据等。
  • Pulsar 客户端 Javadocs[3] : 介绍如何应用新 API。
  • 基于 Pulsar 事务实现 Exactly-Once 语义:本系列博客的第一篇。

我的共事郭斯杰和 Addison Higham 在 6 月 16 日至 17 日举办的 Pulsar Summit 北美峰会 2021 上分享了“Exactly-Once 如此简略:Apache Pulsar 中的事务音讯”。观看演讲视频,理解 Pulsar 事务的更多细节。

论断

本系列的第一篇博客文章《借助 Pulsar 事务机制,实现准确一次语义如此简略》介绍了 Apache Pulsar 的事务 API 如何启用准确一次语义。在本文中,咱们探讨了 Apache Pulsar 中事务 API 的要害设计指标、事务 API 的语义,以及 API 理论如何工作。

如果咱们把流解决看作一个读 - 写处理器,那么这篇博文将重点放在读和写门路上,而解决自身则是一个黑匣子。然而,在理论解决阶段会产生很多事件,导致仅应用事务 API 无奈保障准确一次解决。例如,如果解决逻辑批改了内部存储系统,那么这里介绍的事务 API 不足以保障准确一次解决。

Pulsar 和 Flink 集成通过事务 API 为各种流解决应用程序提供端到端的准确一次解决,甚至解决期间更新那些额定状态存储。

在接下来的几周里,咱们将分享本系列的第三篇文章,具体介绍 Pulsar 和 Flink 集成如何基于新的 Pulsar 事务提供端到端的准确一次解决语义,以及如何应用 Pulsar 和 Flink 轻松编写流应用程序。

相干浏览

  • 技术探索:Apache Pulsar 的事务型事件流
  • Pulsar 2.7.0 新增个性概览:事务反对、Topic 级别策略配置等

译者简介

资飞,资深架构师,Apache Pulsar Contributor,目前在某初创公司负责数据平台、交易平台建设,集体在金融证券畛域已有 9 年的工作教训,专一证券业务以及分布式计算方向,青睐读书、烹饪、游览,关注分布式、高并发、内存交易相干的技术。

点击链接,获取 Apache Pulsar 硬核干货材料!

正文完
 0