常见 MQ 的比较 - Kafka、RocketMQ、RabbitMQ的优劣势比较 GFS 论文学习和 HDFS 实现的比较 Docker技术入门与实战 - 使用 dockerfile定制镜像 I love log 读书笔记 flink 入门程序-wordcount flink 配置项介绍 在 Mac 上搭建 Flink 的开发环境 lambda 架构问题的阅读笔记 IDEA常用插件 Mybatis源码分析(1) - Mybatis关键类 Mybatis源码分析(1) - Mybatis包目录简介 tair 1:tair学习 dataflow论文阅读笔记 Polysh的安装使用 SnappyData排序函数比较 Squirrel-sql客户端连接SnappyData手册 在虚拟机里显示Hello World spark学习博客推荐 SnappyData学习博客和官网文章 Docker常用命令 MyBatis支持的OGNL语法 mysql性能优化 mysql性能优化-优化Sql语句 java各版本新特性 mac上命令行操作 explain输出格式 从文件中读取zk配置——ZooKeeper编程技能(1) git进阶经验-从项目中删除移除的目录 Mongodb 学习之shell命令操作(3) mysql命令 git进阶经验-从多模块项目中分理子模块 从零学hadoop-搭建基础(单点)的Hdfs环境 ZooKeeper集群操作脚本 Vue安装使用 2 初学JVM之问答式记住类加载机制 2 初学JVM之问答式记住虚拟机性能监控与故障处理工具 2 初学JVM之问答式记住垃圾收集器 log4j2 按天生成日志文件 1 初学JVM之问答式记住java自动内存管理 MapReduce学习心得之MapReduce初识 log4j2 日志发送到kafka配置实战 log4j2 日志配置实战 Mongodb 学习之shell命令操作(二) Mongodb 学习之linux版本安装(一) Dubbo的初级使用 ServiceLoader内部实现分析 ServiceLoader 初级应用 log4j日志发送邮件配置实战 红黑树笔记 IDEA首次使用之前的配置 java源码学习之Enum java源码学习之String 自定义Spring tag标签 编写一键发布脚本 记一次Spring Scheduler莫名不执行的一次堆栈分析 kafka的基本操作 nginx 5:Nginx内部变量 nginx 4:Nginx日志管理 提高hadoop配置效率的shell脚本 Hive编程指南之一 Hive的安装 Ambari服务器安装 Ambari服务器管理集群 HBase分布式安装 windows下Eclipse远程调试运行MR程序 基于MapReduce新的API的编程Demo-wordCount window下Eclipse远程只读HDFS上的文件 YARN上节点标签 编写第一个MapReduce的wordcount程序 NodeManager的重启 搭建JStorm集群 YARN上的web应用代理 YARN上的ResourceManager的高可用方案 配置vmware中的虚拟机使用宿主机的共享网络 YARN架构简述 HDFS 架构 Spring的统一异常处理机制 Tomcat 配置服务 HDFS的viewfs指南 HDFS的Federation之路 HDFS基于QJM的HA之路 nginx 3:Nginx反向代理 mybatis操作主体流程 1.正则表达式学习-基础篇 log4j日志配置详解 mysql的时间函数 nginx 2:Nginx模块配置理论及实战 HashMap相关解析和测试文章 工作一年后的面试 用私有构造器或枚举类型强化Singleton属性 java中比较重要的图 mybatis处理枚举类 mybatis集成进spring Spring比较重要的几个截图 21.hadoop-2.7.2官网文档翻译-使用NFS的HDFS高可用性 20.hadoop-2.7.2官网文档翻译-使用仲裁日志管理器的HDFS高可用性 markdown在jekyll中支持的一些操作 Spring项目中配置sl4j和log4j的日志配置 19.hadoop-2.7.2官网文档翻译-HDFS命令指南 Spring的profile机制介绍 mybatis-generator反向生成 18.hadoop-2.7.2官网文档翻译-HDFS用户指南 17.hadoop-2.7.2官网文档翻译-实现Hadoop中Dapper-like追踪 16.hadoop-2.7.2官网文档翻译-Hadoop的KMS(key 管理服务器)-文档集 15.hadoop-2.7.2官网文档翻译-Hadoop的http web认证 14.hadoop-2.7.2官网文档翻译-服务级别的授权指南 13.hadoop-2.7.2官网文档翻译-安全模式中的Hadoop 09.hadoop-2.7.2官网文档翻译-Hadoop命令行微型集群 12.hadoop-2.7.2官网文档翻译-机架感知 11.hadoop-2.7.2官网文档翻译-代理用户-超级用户对其他用户的代表 10.hadoop-2.7.2官网文档翻译-原生库指南 08.hadoop-2.7.2官网文档翻译-文件系统规范 07.hadoop-2.7.2官网文档翻译-Hadoop接口类别 (转)浅析 Decorator 模式,兼谈 CDI Decorator 注解 06.hadoop-2.7.2官网文档翻译-Hadoop的兼容性 05.hadoop-2.7.2官网文档翻译-文件系统命令 04.hadoop-2.7.2官网文档翻译-Hadoop命令指南 03.hadoop-2.7.2官网文档翻译-集群安装 02.hadoop-2.7.2官网文档翻译-单节点集群安装 01.hadoop-2.7.2官网文档翻译-概述 Http 协议相应状态码大全及常用状态码 IDEA快捷键 JDBC Type与Java Type redis 12:redis 操作集合 mybatis-generator错误集合 redis 11:redis 错误集合 nginx 1:nginx的安装 redis 10:redis cluster命令操作 redis 9:redis实例集群安装 java设计模式 hadoop集群学习笔记(1) Apache Shiro 简介 vim编辑神器的进阶命令 Eclipse配置 Eclipse快捷键 Linux 测试题 Linux脚本学习(1) Linux启动简要过程 Centos7上安装Mysql hadoop集群学习笔记(1) (转)分布式发布订阅消息系统 Kafka 架构设计 maven 命令 Kafka集群安装 Kafka初步使用 redis 8:redis server 和 scripting命令操作 redis 7:redis transaction 和 connection命令操作 redis 6:redis hash 命令操作 redis 5:redis sorted_set 命令操作 搭建本地Jekyll+Markdown+Github的开发环境 Spring源码阅读笔记(2) redis 4:redis set命令操作 Spring添加任务调度配置 redis 3:Redis list命令操作 redis 2:redis 一般命令操作 redis 1:redis单机安装笔记 redis 0:redis配置属性描述 Spring源码阅读笔记(1) spark 错误集锦 spark集群安装 Linux 基本命令操作 Hadoop错误信息处理 Hadoop代码拾忆 从零开始搭建spring-springmvc-mybatis-mysql和dubbo项目 java知识点札记 java排错 Google Java Style 中文版 git进阶经验 github使用经验 MongoDB用户角色授权与AUTH启用 MongoDB 命令 MongoDB 特定规范 Spring MVC实现跳转的几种方式 史上最全最强SpringMVC详细示例实战教程 Spring 零星笔记 js中(function(){…})()立即执行函数写法理解 如何解决跨域问题 创建ajax简单过程 前端定位 设置MYSQL允许通过IP访问 mybatis异常 :元素内容必须由格式正确的字符数据或标记组成 如何为 WordPress 绑定多个域名的方法s WordPress工作原理之程序文件执行顺序(传说中的架构源码分析) Spring源码导入Eclipse中 基于PHPnow搭建Eclipse开发环境 解决wordpress首页文章内容截断处理的几种方法 ZooKeeper理论知识 ZooKeeper集群安装配置 Git常用命令速查表 Linux 4:磁盘与文件系统管理 Linux 3:文件与目录管理 Linux 2:文件权限与目录配置 Markdown输入LaTeX数学公式
从零学hadoop-搭建基础(单点)的Hdfs环境 MapReduce学习心得之MapReduce初识 Ambari服务器安装 Ambari服务器管理集群 windows下Eclipse远程调试运行MR程序 基于MapReduce新的API的编程Demo-wordCount window下Eclipse远程只读HDFS上的文件 YARN上节点标签 编写第一个MapReduce的wordcount程序 NodeManager的重启 YARN上的web应用代理 YARN上的ResourceManager的高可用方案 YARN架构简述 HDFS 架构 HDFS的viewfs指南 HDFS的Federation之路 HDFS基于QJM的HA之路 21.hadoop-2.7.2官网文档翻译-使用NFS的HDFS高可用性 20.hadoop-2.7.2官网文档翻译-使用仲裁日志管理器的HDFS高可用性 19.hadoop-2.7.2官网文档翻译-HDFS命令指南 18.hadoop-2.7.2官网文档翻译-HDFS用户指南 17.hadoop-2.7.2官网文档翻译-实现Hadoop中Dapper-like追踪 16.hadoop-2.7.2官网文档翻译-Hadoop的KMS(key 管理服务器)-文档集 15.hadoop-2.7.2官网文档翻译-Hadoop的http web认证 14.hadoop-2.7.2官网文档翻译-服务级别的授权指南 13.hadoop-2.7.2官网文档翻译-安全模式中的Hadoop 09.hadoop-2.7.2官网文档翻译-Hadoop命令行微型集群 12.hadoop-2.7.2官网文档翻译-机架感知 11.hadoop-2.7.2官网文档翻译-代理用户-超级用户对其他用户的代表 10.hadoop-2.7.2官网文档翻译-原生库指南 08.hadoop-2.7.2官网文档翻译-文件系统规范 07.hadoop-2.7.2官网文档翻译-Hadoop接口类别 06.hadoop-2.7.2官网文档翻译-Hadoop的兼容性 05.hadoop-2.7.2官网文档翻译-文件系统命令 04.hadoop-2.7.2官网文档翻译-Hadoop命令指南 03.hadoop-2.7.2官网文档翻译-集群安装 02.hadoop-2.7.2官网文档翻译-单节点集群安装 01.hadoop-2.7.2官网文档翻译-概述 hadoop集群学习笔记(1) hadoop集群学习笔记(1) Hadoop错误信息处理 Hadoop代码拾忆

lambda 架构问题的阅读笔记

2019年06月25日
摘要:

原文:https://www.oreilly.com/ideas/questioning-the-lambda-architecture

Storm的作者Nathan Marz提出了 lambda 架构,该架构是在 MapReduce 上和 Storm 上构建流式处理的应用。lambda 架构是捕获不可变的数据序列并将其并行的发送给批处理系统和流式处理系统。但是你需要分别在批处理系统和流式处理系统中实现一次数据处理逻辑。而在查询的时候需要将两个系统计算的结果合并在一起,以完成查询返回给请求端。

对于两种处理系统,你可以灵活替换实现系统,比如使用 kafka+storm 实现流出处理,使用 hadoop 实现批式处理,输出结果通常在分开的两个数据库中,一个是为了流式而优化,另一个是为了批式更新而优化。

但是对于Jay Kreps【原文作者】因为一直在从事实时数据管道的建设,虽然其中有一些风格就是 lambda 架构,但是他更喜欢一个新的替换的方案。

Lambda 架构图

Lambda 架构

为什么会提出lambda 架构呢

因为那些试图构建流式处理系统的人并没有过多的考虑数据重计算的问题,最终造成系统没有便利的方法来处理数据重计算。

lambda 架构强调保持输入的原始数据不可变并且显示的将数据重新计算的问题给展现了出来。通过 lambda 架构可以比较好的解决了流式数据和历史数据的计算问题。

为什么数据会可能重新计算呢?

因为随着时间的推移,代码可能会改变。改变的原因可能是你想在输出结果中新加一个字段,或者是因为代码有 bug 需要修复。不管是什么原因,要使得历史数据得到新的预期结果,就需要将数据重新计算。

Jay Kreps对 lambda 架构的反驳

因为 lambda 架构提出其中一个观点认为流式系统是近似的,不准确的,准确度不如批式处理。 Jay Kreps对此观点不敢苟同,他认为现存的流式处理的框架不如 MapReduce成熟,但不代表流式系统不能如批式系统那样提供强大的语义保证。而且 lambda 架构提出的标题是”beats the CAP theorem”,即干掉 CAP 理论,但是实际上尽管在流处理上对延时和可用性间存在权衡,但因为这是一种异步处理架构。所以异步计算的结果也不能立即保持与输入的数据一致,因此 CAP 理论仍然没有被打破。

lambda 架构存在的问题是什么?

lambda 架构需要维护在两个复杂的分布式系统中输出相同结果的代码,就像看起来那么痛苦,而且Jay Kreps也不认为该问题是可以解决的。

因为 storm 和 Hadoop 分布式框架非常的复杂,因此不可避免的代码会针对其运行的框架进行设计。

为什么 Lambda 会这样令人兴奋呢?

Jay Kreps建议如果对延时性不敏感就仅使用如 MapReduce 这样的批处理系统。如果延迟敏感则使用流式处理框架,除非特别必须才同时使用这两种系统。

但是需求总是千奇百怪的,人们需要构建复杂的,低延时的处理系统,(而且在天朝 PM 都想要大而全的功能下,这样需求更盛)。

他们拥有的两件事情并不能解决他们的问题:一个可以处理历史数据的可扩展高延迟批处理系统和一个无法重新处理结果的低延迟流处理系统。但通过将两个东西连接在一起,实际上构成了一个可行的方案,也就是 lambda 架构。但尽管lambda 架构让人很痛苦,但确实也解决了重新计算这样通常让人忽略的问题。 但是Jay Kreps只认为 lambda 架构只是临时解决方案,它不是新的编程范例也不是大数据的未来方向。

Jay Kreps的经验

因为在 linkedin 内部已经进行过多次的讨论和尝试。发现保持两个不同系统中编写的代码完全同步非常非常困难。用于隐藏底层框架的API 被证明是最 Low 的抽象,因为这样设计会需要深入的 Hadoop 知识和对实时层的深入了解,而且当你在调试或者因为性能问题排查原因时,还加上需要深入了解抽象层是怎么转换到底层的处理框架的。 也许简单的才是最有效的。

Jay Kreps的灵魂拷问

  1. 为什么不能改进流式处理系统来处理它的目标域内的完整问题呢?
  2. 为什么需要粘在另一个系统上?
  3. 为什么不能同时进行实时处理并在代码更改时处理重新处理?
  4. 为什么不通过增加并行性和重播历史非常非常快地处理重新计算的问题?

Jay Kreps 的观点是什么?

Jay Kreps在思考为什么不能改进流式处理系统来处理它的目标域中完整的问题集呢。 因此出现了两种思路

  1. 使用一种语言或者框架来抽象实时和批处理框架,可以用更高层的框架 api 写代码,然后该框架会编译后选择使用实时处理或者批处理。

    这种方式肯定使得事情变得更好些,但是不能解决问题。 即使这样可以避免编写两次代码,但是运行和调试两个系统的负担也会非常高,而且新的抽象只能提供两个系统特性的并集(但现在 Beam 不是在做这样的事情吗)。而且这样做与跨数据库 透明的 ORM一样的臭名昭著。 在原有系统之上提供相似的接口和界面化语言,在几乎不稳定的分布式系统上构建统一的抽象层比构建完全不同的编程范式要难得多。

  2. 增强流式系统的能力,以解决其目标域内的完整问题。流处理的基本抽象是数据流DAG,它与传统数据仓库中的底层抽象完全相同,也是MapReduce后继Tez的基本抽象。流处理只是这种数据流模型的一种推广,它将中间结果的检查点和持续输出暴露给最终用户。

Jay Kreps提出的在流式处理系统中进行重新计算的逻辑

  1. 使用 kafka 或其他系统保留全部想要重新计算的 log 数据,比如保留 30 天内的数据。
  2. 当想要重新计算时,开启一个新的流式处理 job 的实例从头开始计算,并将计算结果输出到一个新的 table 中。
  3. 当第二个实例处理的数据追赶上前一个时,将应用切换到读新表。
  4. 停用老版本的 JOB,并删除老的表数据

该方式只在代码更改时需要重新计算。当然重新计算只是统一代码的改进版本,运行在相同的框架上,消费同样的输入数据。当然也可以提高 job 的并行度,以便快速完成。

而该架构被称为 Kappa架构

Lambda 架构

而且新旧两张表也可以同时存在,这样就可以通过将应用切换到旧表来恢复旧的逻辑。在特别重要的情况下,也可以使用AB 测试或 bandit 算法来确保无论是修复bug还是代码改进都不会意外降级。

同样的,数据还是可以存储在 HDFS 上的,但是数据的重新计算不会再在 HDFS 做了。

而对于 Kappa 系统,Linkedin 内部使用的Samza就正在使用。

比较

两种方法之间的效率和资源权衡在某种程度上有所不同

  1. Lambda架构需要始终运行重新处理和实时处理
  2. Kappa 架构只需要在需要重新处理时运行第二份作业,但是,Kappa 架构要求在输出数据库中暂时拥有2倍的存储空间,并且需要一个支持高容量写入的数据库来重新加载。

在这两种情况下,再加工的额外负荷可能会平均。如果你有很多这样的工作,他们不会一次全部重新处理,所以在一个有几十个这样的工作的共享集群上,你可能会为在任何给定时间激活重新处理的少数Job提供额外的几个百分点的容量预算。

  lambda 架构 kappa 架构
数据处理能力 可处理超大规模的历史数据 历史数据处理能力有限
机器开销 批处理和实时计算需一直运行,机器开销大 必要时进行全量计算,机器开销相对较小
存储开销 只需要保存一份查询结果,存储开销较小 需要存储新老实例结果,存储开销相对较大。但如果是多 Job 共用的集群,则只需要预留出一小部分的存储即可
开发、测试难易程度 实现两套代码,开发、测试难度较大 只需面对一个框架,开发、测试难度相对较小
运维成本 维护两套系统,运维成本大 只需维护一个框架,运维成本小

对比表格参考自:http://bigdata.51cto.com/art/201702/531038.htm

Kappa 的优势

Kappa 的真正优势不是关于效率,而是关于允许人们在单个处理框架之上开发,测试,调试和操作他们的系统。因此,在简单性很重要的情况下,请将Kappa 架构视为Lambda架构的替代方案。