thelog每个想玩大数据的人都该懂

大神驾到!原LinkdIn首席数据科学家张溪梦;国内首例开源Hadoop部署管理平台Xadoop作者向磊,9.1现身数盟分享,详情报名点击文末阅读原文

出处:IT瘾

我在六年前加入到LinkdIn公司,那是一个令人兴奋的时刻:我们刚开始面临单一庞大的集中式数据库的限制问题,需要过渡到一套专门的分布式系统。这是一个令人兴奋的经历:我们构建、部署和运行分布式图数据库、分布式搜索后端、Hadoop以及第一代和第二代键值数据存储,而且这套系统一直运行至今。

这个过程中,我学到的最有益的事情是我们所构建这套系统的许多组件其核心都包含了一个很简单的概念:日志。日志有时会叫成预先写入日志、提交日志或者事务日志,几乎和计算机本身形影不离,是许多分布式数据系统和实时应用架构的核心。

不懂得日志,你就不可能真正理解数据库、NoSQL存储、键值存储、数据复制、paxos、Hadoop、版本控制,甚至几乎任何一个软件系统;然而大多数软件工程师对日志并不熟悉。我有意于改变这个现状。

本文我将带你浏览有关日志需要了解的一切,包括日志是什么,如何在数据集成、实时处理和系统构建中使用日志。

日志可能是一种最简单的不能再简单的存储抽象,只能追加、按照时间完全有序的记录序列。日志看起来的样子:

在日志的末尾添加记录,读取日志记录则从左到右。每一条记录都指定了一个唯一的顺序的日志记录编号。

日志记录的次序定义了『时间』概念,因为位于左边的日志记录表示比右边的要早。日志记录编号可以看作是这条日志记录的『时间戳』。把次序直接看成是时间概念,刚开始你会觉得有点怪异,但是这样的做法有个便利的性质:解耦了时间和任一特定的物理时钟。引入分布式系统后,这会成为一个必不可少的性质。

分布式系统的时间、次序、时钟是个最基础根本的问题,详见被引用最多的LsliLamport的论文TimClocksandthOrdringofEvntsinaDistributdSystm(中文翻译),现在先不要去看,除非读完本文后你还是有很兴趣要探个明白!

日志记录的内容和格式是什么对于本文讨论并不重要。另外,不可能一直给日志添加记录,因为总会耗尽存储空间。稍后我们会再回来讨论这个问题。

所以,日志和文件或数据表并没有什么大的不同。文件是一系列字节,表是由一系列记录组成,而日志实际上只是一种按照时间顺序存储记录的数据表或文件。

讨论到现在,你可能奇怪为什么要讨论这么简单的概念?只能追加的有序的日志记录究竟又是怎样与数据系统生产关系的?答案是日志有其特定的目标:它记录了什么时间发生了什么事情。而对分布式数据系统,在许多方面,这是要解决的问题的真正核心。

不过,在我们进行更加深入的讨论之前,让我先澄清有些让人混淆的概念。每个程序员都熟悉另一种日志记录的定义——应用使用syslog或者log4j写入到本地文件里的无结构的错误信息或者追踪信息。为了区分,这种情形的称为『应用日志记录』。

应用日志记录是我说的日志概念的一种退化。两者最大的区别是:文本日志意味着主要用来方便人去阅读,而构建我所说的『日志』或者『数据日志』是用于程序的访问。

(实际上,如果你深入地思考一下,会觉得人去阅读某个机器上的日志这样的想法有些落伍过时了。当涉及很多服务和服务器时,这样的做法很快就变得难于管理,我们的目的很快就变成输入查询和输出用于理解多台机器的行为的图表,因此,文件中的字句文本几乎肯定不如本文所描述的结构化日志更合适。)

数据库中的日志

我不知道日志概念的起源——可能就像二分查找一样,发明者觉得太简单了而不是一项发明。早在IBM的系统R出现时候日志就出现了。在数据库里的用法是在崩溃的时候用它来保持各种数据结构和索引的同步。为了保证操作的原子性和持久性,在对数据库维护的所有各种数据结构做更改之前,数据库会把要做的更改操作的信息写入日志。

日志记录了发生了什么,而每个表或者索引都是更改历史中的一个投影。由于日志是立即持久化的,发生崩溃时,可以作为恢复其他所有持久化结构的可靠来源。

随着时间的推移,日志的用途从ACID的实现细节成长为数据库间复制数据的一种方法。结果证明,发生在数据库上的更改序列即是与远程副本数据库保持同步所需的操作。Oracl、MySQL和PostgrSQL都包括一个日志传送协议,传输日志给作为备库的复本数据库。Oracl还把日志产品化为一个通用的数据订阅机制,为非Oracl数据订阅用户提供了XStrams和GoldnGat,在MySQL和PostgrSQL中类似设施是许多数据架构的关键组件。

正是由于这样的起源,机器可识别的日志的概念主要都被局限在数据库的内部。日志作为做数据订阅机制的用法似乎是偶然出现的。但这正是支持各种的消息传输、数据流和实时数据处理的理想抽象。

分布式系统中的日志

日志解决了两个问题:更改动作的排序和数据的分发,这两个问题在分布式数据系统中更是尤为重要。协商达成一致的更改动作的顺序(或是协商达成不一致做法并去做有副作用的数据拷贝)是分布式系统设计的核心问题之一。

分布式系统以日志为中心的方案是来自于一个简单的观察,我称之为状态机复制原理:

如果两个相同的、确定性的进程从同一状态开始,并且以相同的顺序获得相同的输入,那么这两个进程将会生成相同的输出,并且结束在相同的状态。

听起来有点难以晦涩,让我们更加深入的探讨,弄懂它的真正含义。

确定性意味着处理过程是与时间无关的,而且不让任何其他『带外数据』的输入影响处理结果。例如,如果一个程序的输出会受到线程执行的具体顺序影响,或者受到gtTimOfDay调用、或者其他一些非重复性事件的影响,那么这样的程序一般被认为是非确定性的。

进程状态是进程保存在机器上的任何数据,在进程处理结束的时候,这些数据要么保存在内存里,要么保存在磁盘上。

当碰到以相同的顺序输入相同的内容的情况时,应该触发你的条件反射:这个地方要引入日志。下面是个很直觉的意识:如果给两段确定性代码相同的日志输入,那么它们就会生产相同的输出。

应用到分布式计算中就相当明显了。你可以把用多台机器都执行相同事情的问题化简为实现用分布式一致性日志作为这些处理的输入的问题。这里日志的目的是把所有非确定性的东西排除在输入流之外,以确保处理这些输入的各个复本保持同步。

当你理解了这个以后,状态机复制原理就不再复杂或深奥了:这个原理差不多就等于说的是『确定性的处理过程就是确定性的』。不管怎样,我认为它是分布式系统设计中一个更通用的工具。

这样方案的一个美妙之处就在于:用于索引日志的时间戳就像用于保持副本状态的时钟——你可以只用一个数字来描述每一个副本,即这个副本已处理的最大日志记录的时间戳。日志中的时间戳一一对应了副本的完整状态。

根据写进日志的内容,这个原理可以有不同的应用方式。举个例子,我们可以记录一个服务的输入请求日志,或者从请求到响应服务的状态变化日志,或者服务所执行的状态转换命令的日志。理论上来说,我们甚至可以记录各个副本执行的机器指令序列的日志或是所调用的方法名和参数序列的日志。只要两个进程用相同的方式处理这些输入,这些副本进程就会保持一致的状态。

对日志用法不同群体有不同的说法。数据库工作者通常说成物理日志和逻辑日志。物理日志是指记录每一行被改变的内容。逻辑日志记录的不是改变的行而是那些引起行的内容改变的SQL语句(insrt、updat和dlt语句)。

分布式系统文献通常把处理和复制方案宽泛地分成两种。『状态机器模型』常常被称为主-主模型,记录输入请求的日志,各个复本处理每个请求。对这个模型做了细微的调整称为『主备模型』,即选出一个副本做为ladr,让ladr按请求到达的顺序处理请求,并输出它请求处理的状态变化日志。

其他的副本按照顺序应用ladr的状态变化日志,保持和ladr同步,并能够在ladr失败的时候接替它成为ladr。

为了理解两种方式的差异,我们来看一个不太严谨的例子。假定有一个要复制的『算法服务』,维护一个独立的数字作为它的状态(初始值为0),可以对这个值进行加法和乘法运算。

主-主方式所做的可能的是输出所进行的变换的日志,比如『+1』、『*』等。各个副本都会应用这些变换,从而经过一系列相同的值。而主备方式会有一个独立的Mastr执行这些变换并输出结果日志,比如『1』、『』、『6』等。

这个例子也清楚的展示了为什么说顺序是保证各副本间一致性的关键:加法和乘法的顺序的改变将会导致不同的结果。

分布式日志可以看作是建模一致性问题的数据结构。因为日志代表了『下一个』追加值的一系列决策。你需要眯起眼睛才能从Paxos算法簇中找到日志的身影,尽管构建日志是它们最常见的实际应用。

Paxos通过称为multi-paxos的一个扩展协议来构建日志,把日志建模为一系列一致性值的问题,日志的每个记录对应一个一致性值。日志的身影在ZAB、RAFT和ViwstampdRplication等其它的协议中明显得多,这些协议建模的问题直接就是维护分布式一致的日志。

个人有一点感觉,在这个问题上,我们的思路被历史发展有些带偏了,可能是由于过去的几十年中,分布式计算的理论远超过了其实际应用。在现实中,一致性问题是有点被过于简单化了。计算机系统几乎不需要决定单个的值,要的是处理一序列的请求。所以,日志而不是一个简单的单值寄存器,是更自然的抽象。

此外,对算法的专注掩盖了系统底层所需的日志抽象。个人觉得,我们最终会更







































北京哪个医院能治疗白癜风
北京白癜风哪个医院治得好



转载请注明:http://www.xcqg58.com/xxzl/3403.html