日志:每个程序员都应该了解的实时数据统一抽象

在4年前加入GLODON的时候,当时我们正在从传统的CS,单体的中心数据库,私有数据中心 向分布式,混合云架构演进。我们现在构建,部署,运营分布式关系/图像/键值数据库, 分布式检索,基于HDFS和对象存储的大数据分析平台。

在这个过程中,打心里认为学到的最重要的一个简单概念:日志。有时候我们叫它预写日志, 提交日志或事务日志。日志伴随着计算机出现就一直存在,是分布式数据系统和实时应用 架构的核心。

你不会完全理解数据库,NoSQL,键值存储,复制,paxos共识,hadoop,版本控制等任务 软件系统,除非完全理解日志。然而大部分程序员其实对日志并不熟悉。本贴将带你一步步 了解日志,包括什么是日志,如何有效的使用日志,通过日志来构建数据集成,实时数据处理 等业务系统。

第一个部分:什么是日志

日志可能是最简单的存储抽象。它是一个只可追加的,完全按照时间顺序记录的数据序列。 新的记录追加到日志存储的末尾。读取的时候从左向右处理。每一条记录条目分配了一个 唯一的日志序列号。

日志的存储次序定义了时间的概念,因为左边的日志条目始终比右边的日志存储的时间更早。 日志条目唯一序列号可以看做日志条目时间戳。把这个顺序定义为时间咋一看觉得奇怪,但 这个属性很方便的和特定的物理时钟隔离开来。这个属性很快证明是分布式系统所必须的。

日志条目的内容和格式不是本贴讨论内容要重点关心的。而且我们也不能无限的追加记录, 因为存储空间的限制。我们晚点开会谈到这一点。

因此,日志和文件,数据表没有根本不同。文件是字节数组,数据表是记录数组,日志只是 一个特定的类型的文件或数据表:日志数组按时间排序。

到此,你可能奇怪,我们有啥必要讨论如此简单的东西?只可追加的日志序列到底和数据系统 在哪些方面有关联呢?答案是日志有一个特殊的目的:记录什么时间发生了什么事。对分布式 系统来说,在很多方面,这都是核心问题。

但在我们继续讨论之前,让我先澄清一个让人困惑的事情。每一个程序员应该对另一种日志定义 非常熟悉并经常使用:非结构化的错误日志或跟踪日志,这些日志由应用程序利用syslog或 log4j写到本地文件系统。这类日志我们叫做应用日志。应用日志是我要描述的日志的退化形式。 他俩最大的区别是应用日志主要是用来运维开发人员读取使用,而我描述的数据日志主用来被 程序访问。

数据库日志

我不知道数据库日志的真正起源,可能就像二分查找一样,因为太过于简单,发明者都没有意识 到这是一个发明。它最早在IBM的System R中使用,用作各种数据结构和索引在崩溃的后同步。 为了保证数据的原子性和持久性,数据库把要修改的记录在提交前先写入日志。日志记录发生了什么 ,是每个数据表或索引表的历史投影。因为日志被立即写入存储盘,被作为系统崩溃发生后进行 系统恢复有效的数据来源。

慢慢的,日志的使用范围从ACID的实现细节扩展到数据库间的数据复制机制。实践证明,这些 本地数据库数据的变更记录正是要保持远程的数据库副本同步所必需的。Oracle, MySQL和 PostgreSQL都有日志传送协议,在从库上做数据库复制。

分布式系统日志

日志解决的两个问题:变更顺序和数据分发,在分布式数据系统中更加重要。对数据变更顺序的 达成一致是这些系统设计的核心问题。

以日志为中心作为分布式系统的解决思路,源于一个简单的观察结果,我称之为状态机复制规则:

如果两个相同的,”确定性”的程序从相同的状态启动,以相同的顺便获取 相同的输入,他俩会产生相同的输出并以相同的状态结束

“确定性”是指程序处理不依赖于时间,不会因为任何其他的带外的输入影响其处理结果。那些 输出结果依赖线程的执行顺序,或者API调用*gettimeofday*,或其他不可重复的调用的程序 都是非”确定性”。

机器里面的数据是程序的状态的表示,任务处理完后,无论是数据留在才内存,还是在磁盘。

以相同的顺序产生的相同输入这一点提醒我们:这就是日志上场了。这是一个直觉概念: “确定性”的程序会从相同的日志产生相同的结果。

分布式应用看来一个相当直观思路就是:实现一个分布式一致性的日志,作为输入分发到多个 机器上处理相同的任务的程序。日志的目的就是排除输入流产生的所有非确定性输出,保证 每个处理输入流的程序副本保持在相同的状态。

如果你理解了这一点,关于这个规则就没有多深奥或多复杂啦,它或多或少的等于说:确实性的 处理过程是确定性的。然而,我认为它只是分布式系统设计更通用的设计工具之一。

以日志为中心的分布式设计的一个亮点,以时间戳为索引的日志成为程序副本的状态的时钟。 你可以用一个数字来描述一个程序副本:该副本处理的最近日志条目的时间戳。时间戳和日志 一起唯一的快照了副本的完整状态。

不同应用组的人描述日志的使用可能有所不同,数据库组的人经常区分物理日志和逻辑日志, 物理日志记录每行改变的内容,逻辑日志记录导致改变的SQL命令(CRUD)。

分布式系统文献经常把处理和复制划分为两大类别:状态机模式和主备模式。状态机模式 经常指双活,对输入请求做日志记录,每一个副本处理每一个请求。主备模式和状态机模式 有稍微的差别,主备模式为推举一个主节点,主节点会按顺便处理请求,并把处理结果的 状态作为日志同步到从节点。

变更日志101:

参考

[1] What every software engineer should know about real-time data’s unifying abstraction

Related