从一到无穷大 #23 《流计算系统图解》书评

在这里插入图片描述本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。

本作品 (李兆龙 博文, 由 李兆龙 创作),由 李兆龙 确认,转载请注明版权。

文章目录

  • 引言
  • 内容
  • 总结

引言

春节假期回到家里断然是不会有看纸质书的时间的。造化弄人,二月三号早上十一点的飞机延误到一点多,原本三小时不到的阅读时间延长为五个小时,也给了我看完这本书的机会。

第一次了解到这本书是Tison在朋友圈发了他写的书评[2],开头便是:

值得一读,尤其是对开始开发流计算任务或系统一到两年,初步实现过一些功能或作业,但是还没有对流式系统建立起系统认识的开发者。

Tison参与开源的起家项目就是Flink。而我对于流计算系统接触起源于时序数据库的流式计算(降采样),时序数据的以目前使用的场景来看,绝大多数还是把分钟/秒级别数据基于SQL规则降维度/不降维度(对应group by tag/*)到小时/天级别,这样的需求大多数决策者会在写入链路上加一个Flink/Spark,将数据本身处理后写入时序数据库,这也导致业务成本上相当一部分是在Flink/Spark上的。

我们可以看到TDengine的官网上将缓存、流计算,数据订阅以及时序数据库的功能闭环在TDengine内部,并将此作为卖点之一,核心是为了降低系统设计复杂度和运行成本,并标榜自己为时序大数据处理平台。

在这里插入图片描述
我对于流计算系统的浅薄了解便来自于这里。事实上TDengine包括我们的实现标榜为流计算系统并不完全正确,准确的说应该窗口仅为时间,无状态的,且非DAG的简化批处理系统,但是这样的场景对于目前绝大多数需求完全够用,因为目的是为了加速查询而不是给业务赋能。

我参与了腾讯新一代时序数据库从立项到上云的全过程,并实现了对于系统内部简化流计算能力的支持,所以非常符合“开始开发流计算任务或系统一到两年,初步实现过一些功能或作业”的人的,这也是读这本书的主要原因。

在开始书评之前,以TDengine这张图为背景,我以我浅薄的知识评价下在决策者的角度我会怎样使用时序数据库。

  1. 首先我认为时序数据库的流式计算能力是可以解决时序场景中的绝大多数分析需求的,所以我愿意尝试这里的能力。但是对于是否降本我持怀疑态度,因为系统内部执行流计算系统需要大量的内存,尤其是在流计算任务较多时(每个measurement一个,这个数字会极度膨胀),这个时候扩容成了唯一的方法,如果只按照读写的能力去申请资源,加上流计算的资源消耗存在内存风险。但也并不是没有显而易见的好处,即数据库自治,绝大多数情况只有数据库自己知道该如何较优构建降采样和流计算。
  2. kafka的钱是省不了的,这是系统的最后兜底,假如我是一个CEO不可能把我身家性命放在“时序大数据处理平台”的,而且业务数据还需要做更高级的分析需求(降维度,接入用户内部分析系统等),时序数据库的流计算短期能很难看到超越专业流计算系统的可能,所以接受到业务数据后架一个kafka是必要的。
  3. Cache功能完全可以集成到时序数据库内部,这里有两个场景,1. 系统需要快速将最新数据返回给应用程序 2. 相同sql数据缓存,实际查询只查询两次sql的时间差值内的数据,减少CPU/内存消耗;时序数据库集成这些功能是完全可行的,对于我们开发的多模数据库,可以在用户的资源内起一个SSD Redis db,存储大量数据在SSD中,在增加了存储利用率的同时减少了用户查询时延。

内容

若河床上没有岩石,溪流就不会有歌声

第一章阐述了应用程序,后台服务,批处理系统,流处理系统之间的区别,并讨论多阶段架构,为后续引出DAG做铺垫。

先解决问题,再编写代码

第二章引入收费站的例子,指出基于Web服务构建存在流量增加时请求延迟引发了系统迟滞,导致结果不准确的问题,因而引出使用流系统,并指出流系统的核心概念由事件,作业,源,算子和流构成,处理引擎由源执行器,算子执行器和作业启动器构成。

九个人不可能再一个月造出一个孩子

第三章介绍了并行化和数据分组,这可以解决分布式系统的一个根本挑战,即如何扩展系统以增加吞吐量,或者说如何在更短的时间处理更多的数据。并行化包含数据并行和任务并行,前者含义为将一个任务的不同子集交给不同的执行单元,后者含义为在不同的数据上运行相同的任务。章节的后续引入事件分发器,并提出分组概念,为了下游组件可以高效的并行处理上游事件,这和kafka中的partition概念基本一致。

糟糕的程序员担心代码,优秀的程序员担心数据结构和它们之间的关系

第四章引入欺诈检测的case,与之前不同,这时的流并不是一条直线,在数据源之后需要执行多种检测,这就引出了DAG,并解释了算子的扇入扇出,同时指出扇出时发出的事件可以只被推送到某些输出队列中,此外不同的输出队列中可能拥有不同的数据。

人们从来没有足够的时间去做正确的事情,但总有足够的时间去重做一遍

第五章介绍了送达语义,即至多一次(At-Most Once)、至少一次(At-Least Once)和恰好一次(Exactly Once),并指出Exactly Once需要重试和幂等来保证。在我们的时序系统中实现了kafka ingest,需要接受用户写入kafka的数据,并高效的写入引擎,这里开始我们使用autoCommit,这就是经典的至多一次,但是存在数据丢失风险,后来我们使用手动管理offset,保证在实际写入成功后再提交offset,但这依旧只能保证至少一次,真正的恰好一次是靠时序数据库本身的幂等保证的。

技术使人们能够控制除了技术以外的一切

第六章是对前五章的总结。

计算机能集中注意力的时间只和它的电源线一样长

第七章讨论了窗口计算和窗口水位;前者讨论了固定窗口,滑动窗口和会话窗口,并指出可以使用外部系统来完善窗口算子;其次提到乱序数据的到达需要设置窗口水位,一般情况下维持多个窗口开销较大,以目前的经验用户通常可以接受丢弃这部分数据。Tison提到The Dataflow Model 是 Google 流计算的经典论文,Dataflow 模型的开山之作,简单浏览了一下文章内容,窗口水位部分对应文章中:

  1. When in processing time they are materialized ?
  2. How earlier results relate to later refinements ?

这里我还想讨论下目前公有云监控的实时性问题,腾讯云上目前分钟监控在120s内,秒监控在12s以内,这个值是怎么得到的呢?时序数据本质上也可以看作一个有界的数据流,分钟级别监控可以认为是窗口为时间的数据,在这种情况下首先存在一个攒数据的过程,因为不确定数据实在一分钟的哪一秒到达,这就60s了,在加上上报存在失败,在最后1s失败时允许重试,最后就是时序数据库内写入的削峰,这些加起来产品给出了120s的保证。

一个SQL查询来到酒吧,走到两张桌子(table)前问道:我能加入(join)你们吗

第八章讨论JOIN。书中把join当作一种特殊的扇入方式,并提出流必须转化为表才可以执行join,同时讨论了双流join中首先基于窗口物化流,其次再join。这一节的内容在我们的流系统中无法使用,但是在流式查询引擎中还是有理论指导意义的,首先基于窗口截取,其次再合并返回。

永远不要相信一台你无法扔出窗口的计算机

第九章讨论了流系统中广泛支持的故障处理机制,即反压,一种与数据流向相反的压力。因为流是源源不断的,如果存在某个模块出现预期之外的情况,问题很快会传播到其他组件,导致系统崩溃,反压就是最后一道防线,
具体介绍了如何判断繁忙状态与如何执行反压,前者我认为与系统相关,后者的处理是通用的,1. 停止数据源 2. 停止上游组件 并需要考虑如何解除反压状态让系统恢复。

且反压需要区分事件,比如实例宕机或者消费能力不足,这两者靠自身都是无法恢复的,需要拉起实例和增加资源,书中还提到一种特殊的case,即持续触发反压,这会造成整个系统的抖动。

这一章对我来说最大的意义在于从理论上确定了在流系统上思考极端情况是有理论基础的,在我们的实现流计算过程中就遇到过类似的问题,比如WAL拉取导致计算节点CPU暴增处理包变慢,存储节点累计大包,出现大范围OOM;其次还有在均衡操作触发时存在消费老数据的情况,造成CPU激增,影响其他组件;这些其实都是没有考虑反压的情况。

对于如何判断繁忙状态与如何执行反压,前者可以通过统计CPU/内存来做,后者可以选择停止输入和丢弃,工程上不同的场景在监控上需要可以体现。

重启试试

第十章讨论了有状态计算,这同时是Flink的最大价值,即而在于实现了带状态的流计算。这一章主要阐述状态和检查点,即何时持久化状态,书中给出的方法是在数据流中加入检查点,这可以理解为屏障(barrier)。其实以目前我们在时序数据库中实现的流系统来看,最难的点其实在于调度,因为调度的复杂性,我们没有选择有状态的流计算,在出现故障时,选择重放几个窗口的事件,并限制CPU/内存使用。

成功不在于是否曾经摔倒,而在于能否重新站起来

第十一章终章是对七到十章节的总结和展望。

总结

现有的时序数据库只是实现了窗口仅为时间,无状态的,且非DAG的简化批处理系统,想以此替代流系统的全部份额基本不太现实,但是确实可以拿下其中部分收益,领域垂直公司需要故事去活下去,但是公有云需要关注业务上真正需要解决的问题,可见的未来我们的精力不会投入到完善时序的流计算系统中去。

参考:

  1. 大图书馆 #8 流式系统阅读指南
  2. 大图书馆 #9 《流计算系统图解》书评
  3. 支持消息队列和流式计算背后,TDengine 3.0 存储引擎的优化与升级
  4. DolphinDB教程:流数据时序引擎
  5. 一文学会如何使用 TDengine 3.0 中的流式计算
  6. 支持消息队列和流式计算背后,TDengine 3.0 存储引擎的优化与升级
  7. Naiad:A Timely Dataflow System
  8. 论文阅读-Naiad:A Timely Dataflow System
  9. The Dataflow Model: A Practical Approach to Balancing Correctness, Latency, and Cost in Massive-Scale, Unbounded, Out-of-Order Data Processing
  10. 大数据理论篇 - 通俗易懂,揭秘谷歌《The Dataflow Model》的核心思想(一)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2777443.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

微服务OAuth 2.1扩展额外信息到JWT并解析(Spring Security 6)

文章目录 一、简介二、重写UserDetailsService三、Controller解析JWT获取用户信息四、后记 一、简介 VersionJava17SpringCloud2023.0.0SpringBoot3.2.1Spring Authorization Server1.2.1Spring Security6.2.1mysql8.2.0 Spring Authorization Server 使用JWT时,前…

jmeter-问题二:JMeter进行文件上传时,常用的几种MIME类型

以下是一些常用的MIME类型及其对应的文件扩展名: 文本类型: text/plain: 通常用于纯文本文件,如 .txt 文件。 text/html: 用于HTML文档,即 .html 文件。 application/msword: Microsoft Word文档,即 .doc 和 .docx 文件。 图像…

SparkJDBC读写数据库实战

默认的操作 代码val df = spark.read.format("jdbc").option("url", "jdbc:postgresql://localhost:5432/testdb").option("user", "username").option("password", "password").option("driver&q…

《剑指 Offer》专项突破版 - 面试题 37 : 小行星碰撞(C++ 实现)

题目链接:LCR 037. 行星碰撞 - 力扣(LeetCode) 题目: 输入一个表示小行星的数组,数组中每个数字的绝对值表示小行星的大小,数字的正负号表示小行星运动的方向,正号表示向右飞行,负…

【SpringBoot】Redis集中管理Session和自定义用户参数解决登录状态及校验问题

🏡浩泽学编程:个人主页 🔥 推荐专栏:《深入浅出SpringBoot》《java对AI的调用开发》 《RabbitMQ》《Spring》《SpringMVC》 🛸学无止境,不骄不躁,知行合一 文章目录 前言一、分布…

自动化UI,API和DevOps测试架构设计与实现

自动化测试是软件开发过程中的重要环节,它可以提高测试效率、减少人工测试的工作量。本文将介绍自动化测试架构的设计原则和实现方法,以帮助读者理解如何构建一个可靠、可扩展和易于维护的自动化测试框架。 1. 什么是自动化测试? - 解释了…

【java】简单的Java语言控制台程序

一、用于文本文件处理的Java语言控制台程序示例 以下是一份简单的Java语言控制台程序示例,用于文本文件的处理。本例中我们将会创建一个程序,它会读取一个文本文件,显示其内容,并且对内容进行计数,然后将结果输出到控…

excel统计分析——多组数据的秩和检验

单因素资料不完全满足方差的基本假定时,可进行数据转换后再进行方差分析,但有时数据转换后仍不满足方差分析的基本假定,就只能进行秩和检验了。 多组数据秩和检验的主要方法为Kruskal-Wallis检验,也称为Kruskal-Wallis秩和方差分析…

1、学习 Eureka 注册中心

学习 Eureka 注册中心 一、创建 Eureka 微服务0、SpringBoot 和 SpringCloud 版本1、引入 Eureka 服务端依赖2、启动类加 EnableEurekaServer 注解3、配置 yaml 文件,把 Eureka 服务注册到 Eureka 注册中心4、访问 Eureka 服务端,查看注册中心的服务列表…

2024年N1叉车司机证模拟考试题库及N1叉车司机理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2024年N1叉车司机证模拟考试题库及N1叉车司机理论考试试题是由安全生产模拟考试一点通提供,N1叉车司机证模拟考试题库是根据N1叉车司机最新版教材,N1叉车司机大纲整理而成(含2024年…

前端JavaScript篇之call() 和 apply() 的区别?

目录 call() 和 apply() 的区别? call() 和 apply() 的区别? 在JavaScript中,call()和apply()都是用来改变函数中this指向的方法,它们的作用是一样的,只是传参的方式不同。 call()方法和apply()方法的第一个参数都是…

NOR Flash 存内计算芯片技术探幽

文章目录 NOR Flash 存内计算芯片技术探幽1. 核心技术与芯片架构的独特设计2. 强大性能与多样化应用场景3. 技术前景与面临挑战4. 模拟计算精度的突破5. 工具链完善与应用生态建设6. 跨层协同设计的推动7. 技术突破与挑战8. 工具链的完善与生态系统建设9. 跨层协同设计的加强10…

(全网最全)微型计算机原理与接口技术第六版课后习题答案-周荷琴,冯焕清-第10章模数(A/D)和数模(D/A)转换-中国科学技术大学出版社

含有“AI:”开头的题目的答案是问chat的,看个乐就行,不一定正确 大年初一,赶着把最后两篇文章发完,嘻嘻 1。包含A/D和D/A的实时控制系统主要由哪几部分组成?什么情况下要用多路 开关? 第二段文字是在旧版第四版答案…

idea自带database连接mysql失败问题

idea2023.1版连接mysql失败 DBMS: MySQL (ver. 5.7.13) Case sensitivity: plainexact, delimitedexact Driver: MySQL Connector Java (ver. mysql-connector-java-5.1.47 ( Revision: fe1903b1ecb4a96a917f7ed3190d80c049b1de29 ), JDBC4.0) [08S01]Communications link fai…

Stata实证命令代码汇总

Stata代码命令汇总 数据内容:包括数据导入和管理、数据的处理、描述性统计、相关性分析、实证模型、内生性解决、检验分析、结果导出 具体如下: 一、数据导入和管理:数据导入、数据导出 二、数据的处理:生成新变量、格式转换、…

安卓服务的常见问题,性能优化以及应用场景剖析

一、引言 在安卓开发中,服务(Service)扮演着至关重要的角色,它们在没有用户界面的情况下,为用户提供了长时间的后台任务执行能力。本文将探讨服务常见问题、优化策略、应用场景以及开发过程中应注意的事项。 二、应用场…

c#安全-nativeAOT

文章目录 前记AOT测试反序列化Emit 前记 JIT\AOT JIT编译器(Just-in-Time Complier),AOT编译器(Ahead-of-Time Complier)。 AOT测试 首先编译一段普通代码 using System; using System.Runtime.InteropServices; namespace co…

如何解决利用cron定时任务自动更新SSL证书后Nginx重启问题

利用cron定时任务自动更新SSL证书后,用浏览器访问网站,获取到的证书仍然是之前的。原因在于没有对Nginx进行重启。 据说certbot更新完成证书后会自动重启Nginx,但显然经我检测不是这回事儿。 所以我们需要创建一bash脚本,然后定时调用这个脚…

第十七篇【传奇开心果系列】Python的OpenCV库技术点案例示例:自适应阈值二值化处理图像提取文字

传奇开心果短博文系列 系列短博文目录Python的OpenCV库技术点案例示例系列短博文目录前言一、自适应阈值二值化处理图像提取文字轮廓的初步示例代码:二、扩展思路介绍三、调整自适应阈值二值化的参数示例代码四、对二值化图像进行形态学操作示例代码五、使用轮廓特征进行筛选示…

跟着cherno手搓游戏引擎【23】项目维护、2D引擎之前的一些准备

项目维护: 修改文件结构: 头文件自己改改就好了 创建2DRendererLayer: Sandbox2D.h: #pragma once #include "YOTO.h" class Sandbox2D :public YOTO::Layer {public:Sandbox2D();virtual ~Sandbox2D() default;virtual void O…