diff --git a/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/part1.md b/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/part1.md
index fe8c298..2eb650f 100644
--- a/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/part1.md
+++ b/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/part1.md
@@ -11,7 +11,7 @@
日志记录编号可以看作是这条日志记录的『时间戳』。
把次序直接看成是时间概念,刚开始你会觉得有点怪异,但是这样的做法有个便利的属性:解耦了 时间 和 任一特定的物理时钟(`physical clock`)。引入分布式系统后,这会成为一个必不可少的属性。
-***【译注】***: 分布式系统的 时间、次序、时钟是最基础根本的问题,更多思考可以参见被引用最多的***Leslie Lamport***的论文[***Time Clocks and the Ordering of Events in a Distributed System***](http://duanple.blog.163.com/blog/static/709717672012920101343237/)。
+***【译注】*** 分布式系统的 时间、次序、时钟是最基础根本的问题,更多思考可以参见被引用最多的***Leslie Lamport***的论文[***Time Clocks and the Ordering of Events in a Distributed System***](http://duanple.blog.163.com/blog/static/709717672012920101343237/)。
日志记录的内容和格式是什么对于本文讨论并不重要。另外,不可能一直给日志添加记录,因为总会耗尽存储空间。稍后我们会回到这个问题。
@@ -61,59 +61,92 @@
进程***状态***是进程保存在机器上的任何数据,在进程处理结束的时候,这些数据要么保存在内存里,要么保存在磁盘上。
-以相同的顺序获得相同输入的地方应当引起注意-这就是引入日志的地方。这儿有一个重要的常识:如果给两段确定性代码相同的日志输入,那么它们就会生成相同的输出。
+当碰到以相同的顺序输入相同的内容的情况时,应该触发你的条件反射:这个地方要引入日志。
+下面是个很直觉的意识:如果给两段确定性代码相同的日志输入,那么它们就会生成相同的输出。
-分布式计算这方面的应用就格外明显。你可以把用多台机器一起执行同一件事情的问题缩减为实现分布式一致性日志为这些进程输入的问题。这儿日志的目的是把所有非确定性的东西排除在输入流之外,来确保每个复制进程能够同步地处理输入。
+分布式计算这样的应用格外明显。你可以把用多台机器一起执行同一件事情的问题化简为实现分布式一致性日志输入给这些进程的问题。
+这儿日志的目的是把所有非确定性的东西排除在输入流之外,来确保每个复本(`replica`)处理这些输入并保持同步。
-当你理解了这个以后,状态机复制原理就不再复杂或者说不再深奥了:这或多或少的意味着“确定性的处理过程就是确定性的”。不管怎样,我都认为它是分布式系统设计里较常用的工具之一。
+当你理解了这个以后,状态机复制原理就不再复杂或深奥了:这个原理差不多就等于说的是『确定性的处理过程就是确定性的』。不管怎样,我认为它是分布式系统设计中一个更通用的工具。
-这种方式的一个美妙之处就在于索引日志的时间戳就像时钟状态的一个副本——你可以用一个单独的数字描述每一个副本,这就是经过处理的日志的时间戳。时间戳与日志一一对应着整个副本的状态。
+这样方案的一个美妙之处就在于:用于索引日志的时间戳 就像 用于保持副本状态的时钟 —— 你可以只用一个数字来描述每一个副本,即这个副本已处理的最大日志记录的时间戳。关联了日志的时间戳 一一对应 副本的完整状态。
-由于写进日志的内容的不同,也就有许多在系统中应用这个原则的不同方式。举个例子,我们记录一个服务的请求,或者服务从请求到响应的状态变化,或者它执行命令的转换。理论上来说,我们甚至可以为每一个副本记录一系列要执行的机器指令或者调用的方法名和参数。只要两个进程用相同的方式处理这些输入,这些进程就会保持副本的一致性。
+视写进日志的内容,这个原理可以有不同的应用方式。举个例子,我们记录一个服务的输入请求日志,或者从请求到响应服务的状态变化日志,或者服务所执行的状态转换命令的日志。
+理论上来说,我们甚至可以记录每一个副本执行的机器指令序列的日志 或是 所调用的方法名和参数序列的日志。
+只要两个进程用相同的方式处理这些输入,这些副本进程就会保持一致的状态。
-一千个人眼中有一千种日志的用法。数据库工作者通常区分物理日志和逻辑日志。物理日志就是记录每一行被改变的内容。逻辑日志记录的不是改变的行而是那些引起行的内容被改变的SQL语句(insert,update和delete语句)。
+关于日志的用法,大家都仁者见仁智者见智。数据库工作者通常区分***物理***日志(`physical logging`)和***逻辑***日志(`logical logging`)。物理日志是指记录每一行被改变的内容。逻辑日志记录的不是改变的行而是那些引起行的内容改变的`SQL`语句(`insert`、`update`和`delete`语句)。
-分布式系统通常可以宽泛分为两种方法来处理数据和完成响应。“状态机器模型”通常引用一个主动-主动的模型——也就是我们为之记录请求和响应的对象。对此进行一个细微的更改,称之为“预备份模型”,就是选出一个副本做为leader,并允许它按照请求到达的时间来进行处理并从处理过程中输出记录其状态改变的日志。其他的副本按照leader状态改变的顺序而应用那些改变,这样他们之间达到同步,并能够在leader失败的时候接替leader的工作。
+分布式系统文献通常把处理和复制(`processing and replication`)方案宽泛地分成两种。『状态机器模型』常常被称为主动-主动模型(`active-active model`) ——
+记录输入请求的日志,每个复本处理每个请求。
+对这个模型做了细微的调整称为『主备模型』(`primary-backup model`),即选出一个副本做为`leader`,让`leader`按请求到达的顺序处理请求并输出它请求处理的状态变化日志。
+其他的副本按照顺序应用`leader`状态改变日志保持和`leader`同步,并能够在`leader`失败的时候接替它成为`leader`。

-为了理解两种方式的不同,我们来看一个不太严谨的例子。假定有一个算法服务的副本,保持一个独立的数字作为它的状态(初始值为0),并对这个值进行加法和乘法运算。主动-主动方式应该会输出所进行的变换,比如“+1”,“\*2”等。每一个副本都会应用这些变换,从而得到同样的解集。主动-被动方式将会有一个独立的主体执行这些变换并输出结果日志,比如“1”,“3”,“6”等。这个例子也清楚的展示了为什么说顺序是保证各副本间一致性的关键:一次加法和乘法的顺序的改变将会导致不同的结果。
+为了理解两种方式的差异,我们来看一个不太严谨的例子。假定有一个要复制的『算法服务』,维护一个独立的数字作为它的状态(初始值为0),可以对这个值进行加法和乘法运算。
+主动-主动方式所做的可能的是输出所进行的变换的日志,比如『+1』、『\*2』等。各个副本都会应用这些变换,从而经过一系列相同的值。
+而主备方式会有一个独立的`Master`执行这些变换并输出结果日志,比如『1』、『3』、『6』等。
+这个例子也清楚的展示了为什么说顺序是保证各副本间一致性的关键:加法和乘法的顺序的改变将会导致不同的结果。
-
+
-分布式日志可以理解为一致性问题模型的数据结构。因为日志代表了后续追加值的一系列决策。你需要重新审视Paxos算法簇,尽管日志模块是他们最常见的应用。 在Paxos算法中,它通常通过使用称之为多paxos的协议,这种协议将日志建模为一系列的问题,在日志中每个问题都有对应的部分。在ZAB, RAFT等其它的协议中,日志的作用尤为突出,它直接对维护分布式的、一致性的日志的问题建模。
+分布式日志可以用于建模[一致性](https://en.wikipedia.org/wiki/Consensus_(computer_science))(`consensus`)问题的数据结构。
+因为日志代表了『下一个』追加值的一系列决策。
+你需要眯起眼睛才能从[`Paxos`](http://en.wikipedia.org/wiki/Paxos_(computer_science))算法簇中找到日志的身影,尽管构建日志是它们最常见的实际应用。
+`Paxos`通过称为`multi-paxos`的一个扩展协议来构建日志,把日志建模为一系列一致性值的问题,日志的每个记录对应一个一致性值。
+日志的身影在[`ZAB`](http://www.stanford.edu/class/cs347/reading/zab.pdf)、[`RAFT`](https://ramcloud.stanford.edu/wiki/download/attachments/11370504/raft.pdf)和[`Viewstamped Replication`](http://pmg.csail.mit.edu/papers/vr-revisited.pdf)等其它的协议中明显得多,这些协议建模的问题直接就是维护分布式一致的日志。
-我怀疑的是,我们就历史发展的观点是有偏差的,可能是由于过去的几十年中,分布式计算的理论远超过了其实际应用。在现实中,共识的问题是有点太简单了。计算机系统很少需要决定单个值,他们几乎总是处理成序列的请求。这样的记录,而不是一个简单的单值寄存器,自然是更加抽象。
+个人有一点感觉,在这个问题上,我们的思路被历史发展有些带偏了,可能是由于过去的几十年中,分布式计算的理论远超过了其实际应用。
+在现实中,一致性问题是有点被过于简单化了。计算机系统几乎不需要决定单个的值,要的是处理一序列的请求。
+所以,日志而不是一个简单的单值寄存器,是更自然的抽象。
-此外,专注于算法掩盖了 抽象系统需要的底层的日志。我怀疑,我们最终会把日志中更注重作为一个商品化的基石,不论其是否以同样的方式 实施的,我们经常谈论一个哈希表而不是纠结我们 得到是不是具体某个细节的哈希表,例如线性或者带有什么什么其它变体哈希表。日志将成为一种大众化的接口,为大多数算法和其实现提升提供最好的保证和最佳的性能。
+此外,对算法的专注掩盖了系统底层所需的日志抽象。
+个人觉得,我们最终会更关注把日志作为一个商品化的基石而不是考虑它的实现,就像我们经常谈论一个哈希表而不是纠结于哪些细节,
+比如使用线性探测的杂音哈希(`the murmur hash with linear probing`)还是某个变种。
+日志将成为一种大众化的接口,可以有多种竞争的算法和实现,以提供最好的保证和最佳的性能。
变更日志101: 表与事件的二相性
-------------------------
-让我们继续聊数据库。数据库中存在着大量变更日志和表之间的二相性。这些日志有点类似借贷清单和银行的流程,数据库表就是当前的盈余表。如果你有大量的变更日志,你就可以使用这些变更用以创建捕获当前状态的表。这张表将记录每个关键点(日志中一个特别的时间点)的状态信息。这就是为什么日志是非常基本的数据结构的意义所在:日志可用来创建基本表,也可以用来创建各类衍生表。同时意味着可以存储非关系型的对象。
+让我们继续聊一下数据库。变更日志 和 表之间有着迷人的二相性。
+日志类似借贷清单和银行处理流水,而数据库表则是当前账户的余额。如果有变更日志,你就可以应用这些变更生成数据表并得到当前状态。
+表记录的是每条数据的最后状态(日志的一个特定时间点)。
+可以认识到日志是更基本的数据结构:日志除了可用来创建原表,也可以用来创建各类衍生表。
+(是的,表可以是非关系型用户用的键值数据存储(`keyed data store`)。)
-
+
-这个流程也是可逆的:如果你正在对一张表进行更新,你可以记录这些变更,并把所有更新的日志发布到表的状态信息中。这些变更日志就是你所需要的支持准实时的克隆。基于此,你就可以清楚的理解表与事件的二相性: 表支持了静态数据而日志捕获变更。日志的魅力就在于它是变更的完整记录,它不仅仅捕获了表的最终版本的内容,它还记录了曾经存在过的其它版本的信息。日志实质上是表历史状态的一系列备份。
+这个过程也是可逆的:如果你对一张表进行更新,你可以记录这些变更,并把所有更新的『变更日志(`changelog`)』发布到表的状态信息中。
+这些变更日志正是你所需要的支持准实时的复制。
+基于此,你就可以清楚的理解表与事件的二相性: 表支持了静态数据,而日志记录了变更。日志的魅力就在于它是变更的_完整_记录,它不仅仅包含了表的最终版本的内容,
+而且可以用于重建任何存在过其它版本。事实上,日志可以看作是表_每个_历史状态的一系列备份。
-这可能会引起你对源代码的版本管理。源代码管理和数据库之间有密切关系。版本管理解决了一个大家非常熟悉的问题,那就是什么是分布式数据系统需要解决的--- 时时刻刻在变化着的分布式管理。版本管理系统通常以补丁的发布为基础,这实际上可能是一个日志。您可以直接对当前 类似于表中的代码做出“快照”互动。你会注意到, 与其他分布式状态化系统类似,版本控制系统 当你更新时会复制日志,你希望的只是更新补丁并将它们应用到你的当前快照中。
+这可能会会让你想到源代码的版本控制。源码控制和数据库之间有着密切的关系。
+版本管理解决了一个和分布式数据系统要解决的很类似的问题 —— 管理分布式式并发的状态变更。
+版本管理系统建模的是补丁序列(`the sequence of patches`),实际上这个就是日志。
+你可以把当前的代码检出的一个『快照』并直接操作,这个当前代码可以类比成表。
+你会注意到,与其他分布式状态化系统类似,版本控制系统通过日志来完成复制:更新代码即是拉下补丁并应用到你的当前快照中。
-最近,有些人从Datomic --一家销售日志数据库的公司得到了一些想法。这些想法使他们对如何 在他们的系统应用这些想法有了开阔的认识。 当然这些想法不是只针对这个系统,他们会成为 十多年分布式系统和数据库文献的一部分。
+从销售日志数据库的公司[`Datomic`](http://www.datomic.com/)那里,大家可以看到一些这样想法。
+[这个视频](https://www.youtube.com/watch?v=Cym4TZwTCNU)有他们如何在他们的系统中应用这些想法的不错介绍。
+当然这些想法不是只专门于这个系统的,这十多年他们贡献了很多分布式系统和数据库的文献。
-这可能似乎有点过于理想化。但是不要悲观!我们会很快把它实现。
+这节的内容可能有点理论化了。但别沮丧!后面马上就是实操的干货。
接下来的内容
-------------------------
-在这篇文章的其余部分,我将试图说明日志除了可用在分布式计算或者抽象分布式计算模型内部之外,还可用在哪些方面。其中包括:
+本文剩下的内容,我会试着讲述,除了作为分布式计算内部实现或模型抽象,日志有什么优点。包含:
-1. 数据集成-让机构的全部存储和处理系统里的所有数据很容易地得到访问。
-1. 实时数据处理-计算生成的数据流。
-1. 分布式系统设计-实际应用的系统是如何通过使用集中式日志来简化设计的。
+1. _数据集成_(`Data Integration`) —— 让组织的全部存储和处理系统可以容易地得到访问组织的所有数据。
+1. _实时数据处理_ —— 计算生成的数据流。
+1. _分布式系统设计_ —— 如何通过集中式日志的设计来简化实际应用系统。
-所有这些用法都是通过把日志用做单独服务来实现的。
+所有这些用法都是通过把日志用做单独服务来实现的。
-在上面任何一种用法里,日志的用途开始都是使用了日志所能提供的某个简单功能:生成永久的、可重现的历史记录。令人意外的是,问题的核心是可以让多少台机器以特定的方式,按照自身的速度重现历史记录的能力。
+上面各个用法中,日志的好处都来自日志所能提供的简单功能:生成持久化的可重放的历史记录。
+令人意外的是,这些问题的核心是可以让多台机器以确定性的方式(`deterministic manner`)按各自的速率重放历史记录的能力。
-----------------
diff --git a/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/part3.md b/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/part3.md
index 176c633..81471bc 100644
--- a/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/part3.md
+++ b/log-what-every-software-engineer-should-know-about-real-time-datas-unifying/part3.md
@@ -48,7 +48,7 @@
日志集成的目标是双重的:
-首先,它确保每个数据集都有多个订阅者和有序的。让我们回顾一下状态复制原则来记住顺序的重要性。为了使这个更加具体,设想一下从数据库中更新数据流--如果在处理过程中我们把对同一记录的两次更新重新排序,可能会产生错误的输出。 TCP之类的链接仅仅局限于单一的点对点链接,这一顺序的持久性要优于TCP之类的链接,它可以在流程处理失败和重连时仍然存在。
+首先,它确保每个数据集都有多个订阅者和有序的。让我们回顾一下状态复制原理来记住顺序的重要性。为了使这个更加具体,设想一下从数据库中更新数据流--如果在处理过程中我们把对同一记录的两次更新重新排序,可能会产生错误的输出。 TCP之类的链接仅仅局限于单一的点对点链接,这一顺序的持久性要优于TCP之类的链接,它可以在流程处理失败和重连时仍然存在。
第二,日志提供了流程的缓冲。这是非常基础的。如果处理流程是非同步的,那么上行生成流数据的作业比下行消费流数据的作业运行的更快。这将会导致处理流程阻塞,或者缓冲数据,或者丢弃数据。丢弃数据并不是可行的方法,阻塞将会导致整个流程图立即停止。 日志实际上是一个非常大的缓冲,它允许流程重启或者停止但不会影响流程图其它部分的处理速度。如果要把数据流扩展到更大规模的组织,如果处理作业是由多个不同的团队提供的,这种隔离性是极其重的。我们不能容忍一个错误的作业引发后台的压力,这种压力会使得整个处理流程停止。