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代码拾忆

I love log 读书笔记

2019年08月07日
摘要:

原书作者

Jay Kreps: kafka 的创始人,Linkedin 的首席科学家

什么是log?

最常见的log

2019-07-29 11:04:34.688 - - [INFO] main RequestMappingHandlerMapping  Mapped "{[/api/thrift/getAllBlockedList],methods=[GET]}" onto public com.test.oh.hecate.thrift.PoiIdsShopIdsResp com.test.hecate.web.api.ThriftController.test1()
2019-07-29 11:04:34.692 - - [INFO] main RequestMappingHandlerMapping  Mapped "{[/search/searchItems],methods=[GET]}" onto public com.test.oh.hecate.response.BaseResponse<java.util.List<com.test.oh.hecate.constant.SearchItemEnum>> com.test.oh.hecate.web.api.SearchController.getSearchItems()
2019-07-29 11:04:34.692 - - [INFO] main RequestMappingHandlerMapping  Mapped "{[/search/pageAndSortHistory],methods=[GET]}" onto public com.test.oh.hecate.response.PageListResponse<com.test.oh.hecate.domain.SearchHistInfoRep> com.test.oh.hecate.web.api.SearchController.pageAndSortHistory(int,int)
2019-07-29 11:04:34.693 - - [INFO] main RequestMappingHandlerMapping  Mapped "{[/search/download/request],methods=[GET]}" onto public com.test.oh.hecate.response.BaseResponse<com.test.oh.hecate.domain.SearchHistInfoRep> com.test.oh.hecate.web.api.SearchController.download(java.lang.String)

这种是写业务的程序员最常见的日志信息,结构化的可视化的日志信息。

但这种日志并非是 log 的全部,这些只是些业务日志,还有些日志时一般程序员平时接触不到的。但是重要的是我们将日志视为抽象数据结构,而不是文本文件

其他 log

log和文件或表没有任何区别,文件是字节数组,而表述记录的数组。而 log 实际上只是一种文件或表,其中的记录按照时间排好了序。

此时你可能会想,“为什么值得谈论这么简单的事情?”与数据系统有关的以仅追加的记录序列如何?答案是日志有一个特定的目的:它们记录了什么 发生了什么时候。 对于分布式数据系统,这在许多方面都是问题的核心

数据库中的 log

  1. 在数据库中的 log与系统崩溃时保持各数据结构和索引有关,为了使得log 是原子和可持久的,在数据库变更前,会将修改的信息记录并持久下来。因为 log 是立即持久的,因此可以在系统崩溃时作为数据恢复的权威来源。
  2. 在数据库间进行远程副本同步。比如 mysql 的主从结构等。oracle,mysql,mongo 等都有日志传输协议将数据副本传输到作为从库的远程节点上。这样可以保持主从一致。

分布式系统中的 log

在分布式系统中的日志使用方式其实是早期数据库中 log的两种使用方式的变种:

  1. log 用于发布/订阅机制,在主从间传递数据副本
  2. log 用于一致性机制,用于对应用的多个副本的更新保持有序。

状态机复制原理: 如果两个相同的确定性过程以相同的状态开始,以相同的顺序得到相同的输入,它们将产生相同的输出,并以相同的状态结束。

直观的概念就是: 对于相同的确定的代码片段,输入相同的 log,那么它们会按照相同的顺序产出相同的输出结果。

一句话总结: 确定性的处理是确定性的。

对于不同的社区对状态机的描述不同:

  1. 数据库社区会区分物理和逻辑日志。物理日志或者基于行的日志意味着记录更改的每一行的内容。逻辑日志或者声明日志不会记录改变的行,而是会记录导致行改变的 sql 命令。
  2. 分布式系统文献通常描述两种广泛的处理和复制的方法。
    1. 状态机模型:通常指的是主动模型,即保存输入请求的日志,每个副本都按日志顺序执行每个请求。所有节点都是对等的,先写入日志,所有节点按日志确定的顺序应用写入。 状态机模型
    2. 主备模型:状态机模型的改版。选举主节点,主节点按顺序处理请求,并将更改记录到由于处理请求而发生的状态。其他副本应用主节点的状态改变,保持同步并在主节点宕机后准备接替成为主节点。 主备模型

分布式日志可以被认为是模拟共识问题的模型。 对于Paxos,通常使用 multi-paxos 扩展协议,将日志建模为一系列的共识问题。一个用于日志中的每个槽。日志在其他协议中更为突出,比如 ZAB,RAFT 和Viewstamped Replication。他们直接模拟维护分布式一致日志的问题。

应用

数据集成

术语数据集成不常见,通常有 ETL 术语,但是数据集成是 ETL 的超集。

通过统一的方式捕获数据,以统一的方式建模,就可以在此基础上以各种方式处理这些数据。比如:批处理(Mapreduce),流处理,实时查询等。

数据的处理可能需要基于类马斯洛的金字塔模型。

用于数据的类马斯洛金字塔模型

困扰数据集成的两种问题

  1. 数据的多样化
    1. 业务数据,如订单数据,用户数据和产品数据等
    2. 事件数据或日志数据,如用户活动日志,机器日志和监控数据等,这些数据已经成为现代 web 的核心数据。
  2. 专业数据系统的爆炸

两种问题的解决办法

日志结构的数据流

日志是处理系统间数据流的自然数据结构。概念就是:获取组织的日志数据,并将其放入日志中心系统中进行实时订阅。 即以此理论实践出了kafka系统,多订阅用户系统。数据输出源和数据输出源可以是任意的系统。

kafka作为以日志为基础的统一的数据管道,不管订阅者或发布者新增,删除,崩溃等情况,都不会影响管道的数据。

数据流处理

使用统一的数据管道前的系统间数据传输的架构

使用统一的数据管道前的系统间数据传输的架构

使用统一的数据管道后的系统间数据传输的架构

使用统一的数据管道后的系统间数据传输的架构

新架构使用同一的数据管道,使用topic术语区分不同的系统和业务的数据结构,简化了系统间对接的复杂度。数据生产者和数据使用者互相不知道,他们只需要知道有类似于kafka这样的统一的数据管道即可。

实时流计算

为什么流计算需要 log ?

  1. log (如 kafka) 可以使得每个数据集都有多个订阅者
  2. 确保每个数据消费者在处理过程中保持顺序.如果乱序可能会导致错误的结果。
  3. 为每个处理进程提供数据的缓存和隔离
    1. 上游生产快被阻塞。起初阻止听起来像是一个可接受的选择,但实际上变成了一个大问题。考虑到我们想要的不仅仅是对单个应用程序的处理进行建模,而是对整个组织的全部数据流进行建模。这将不可避免地成为不同团队拥有的处理器之间非常复杂的数据流网络,并以不同的服务级别协议运行。在这个复杂的数据处理网络中,如果任何一个消费者失败或者跟不上,上游生产者将会阻塞,阻塞将会通过数据流图级联起来,把所有的东西都碾成两半
    2. 丢弃数据。某些情况可以,但一般不可取也不可接受。
    3. 缓存数据隔离生产和消费两个进程。缓存在其他地方并不罕见。比如 复杂的MapReduce 会使用文件产生中间结果和 checkpoint。复杂的 Sql 会产生中间表等。

对 Lambda 架构的评价和改进

参考文档:

http://followtry.cn/2019-06-25/questioning-the-lambda-arch.html

有状态的流计算

如果实际的流式计算中确实需要保存状态,那这也是 log 的一种用途。

在流式计算中可能会需要统计总数,聚合或加入流窗口等操作。

当然会想到集中保存状态的方式

  1. 将状态存在内存中。但是如果机器崩溃或重启后,内存中的数据就丢失了。
  2. 状态存在远程的存储系统中。但这样就会引入的网络,可能会存在大量的网络传输。
  3. 因为考虑到表和 log 的二重性,这为我们提供了能够将流转换为与我们的处理共存的表的工具,以及处理这些表的容错的机制
    1. 可以将状态保存在本地表或索引中,如bdb,rocksdb,lucene,fastbit等,存储的内容从输入流中获取。当进程失败后,可以从变更日志中恢复索引。日志将本地状态转换为一次性增量记录备份。
    2. 当与来自数据库的日志结合用于数据集成时,日志/表二元性的能力变得清晰。 可以从数据库中提取更改日志,并通过各种流处理器以不同形式编制索引以与事件流进行连接

日志的作用

  1. 通过对节点的并发更新排序来处理数据一致性(无论是最终的还是立即的)
  2. 提供节点间的数据复制
  3. 为作者提供“提交”语义(例如只有在保证不会丢失你的写入时才进行确认)
  4. 从系统提供外部数据订阅源
  5. 提供恢复丢失数据或引导新数据的失败副本的功能
  6. 处理节点之间数据的重新平衡