时钟统一的概念及意义

我在六年前的一个令人兴奋的时刻加入到LinkedIn公司。从那个时候开始我们就破解单一的、集中式数据库的限制,并且启动到特殊的分布式系统套件的转换。这是一件令人兴奋的事情:我们构建、部署,而且直到今天仍然在运行的分布式图形数据库、分布式搜索后端、Hadoop安装以及第一代和第二代键值数据存储。

从这一切里我们体会到的最有益的事情是我们构建的许多东西的核心里都包含一个简单的理念:日志。有时候也称作预先写入日志或者提交日志或者事务日志,日志几乎在计算机产生的时候就存在,同时它还是许多分布式数据系统和实时应用结构的核心。

不懂得日志,你就不可能完全懂得数据库,NoSQL存储,键值存储,复制,paxos,Hadoop,版本控制以及几乎所有的软件系统;然而大多数软件工程师对它们不是很熟悉。我愿意改变这种现状。在这篇博客文章里,我将带你浏览你必须了解的有关日志的所有的东西,包括日志是什么,如何在数据集成、实时处理和系统构建中使用日志等。

日志是一种简单的不能再简单的存储抽象。它是一个只能增加的,完全按照时间排序的一系列记录。日志看起来如下:

我们可以给日志的末尾添加记录,并且可以从左到右读取日志记录。每一条记录都指定了一个唯一的有一定顺序的日志记录编号。

日志记录的排序是由“时间”来确定的,这是因为位于左边的日志记录比位于右边的要早些。日志记录编号可以看作是这条日志 记录的“时间戳”。在一开始就把这种排序说成是按时间排序显得有点多余 ,不过 ,与任何一个具体的物理时钟相比,时间 属性是非常便于使用的属性。在我们运行多个分布式系统的时候,这个属性就显得非常重要。

对于这篇讨论的目标而言,日志记录的内容和格式不怎么重要。另外提醒一下,在完全耗尽存储空间的情况下,我们不可能 再给日志添加记录。稍后我们将会提到这个问题。

日志并不是完全不同于文件或者数据表的。文件是由一系列字节组成,表是由一系列记录组成,而日志实际上只是按照时间顺序存储记录的 一种数据表或者文件。

此时,你可能奇怪为什么要讨论这么简单的事情呢? 不同环境下的一个只可增加的有一定顺序的日志记录是怎样与数据系统关联起来的呢?答案是日志有其特定的应用目标:它记录了什么时间发生了什么事情。 而对分布式数据系统许多方面而言, 这才是问题的真正核心。

不过,在我们进行更加深入的讨论之前,让我先澄清有些让人混淆的概念。每个编程人员都熟悉另一种日志记录-应用使用syslog或者log4j可能写入到本地文件里的没有结构的错误信息或者追踪信息。为了区分开来,我们把这种情形的日志记录称为“应用日志记录”。应用日志记录是我在这儿所说的日志的一种低级的变种。最大的区别是:文本日志意味着主要用来方便人们阅读,而我所说明的“日志”或者“数据日志”的建立是方便程序访问。

(实际上,如果你对它进行深入的思考,那么人们读取某个机器上的日志这种理念有些不顺应时代潮流。当涉及到许多服务和服务器的时候,这种方法很快就变成一个难于管理的方式,而且为了认识多个机器的行为,日志的目标很快就变成查询和图形化这些行为的输入了-对多个机器的某些行为而言,文件里的英文形式的文本同这儿所描述的这种结构化的日志相比几乎就不适合了。)

我不知道日志概念起源于何处-可能它就像二进制搜索一样:发明者认为它太简单而不能当作一项发明。它早在IBM的系统R出现时候就出现了。数据库里的用法是在崩溃的时候用它来同步各种数据结构和索引。为了保证操作的原子性和持久性,在对数据库维护的所有各种数据结构做更改之前,数据库把即将修改的信息誊写到日志里。日志记录了发生了什么,而且其中的每个表或者索引都是一些数据结构或者索引的历史映射。由于日志是即刻永久化的,可以把它当作崩溃发生时用来恢复其他所有永久性结构的可信赖数据源。

随着时间的推移,日志的用途从实现ACID细节成长为数据库间复制数据的一种方法。利用日志的结果就是发生在数据库上的更改顺序与远端复制数据库上的更改顺序需要保持完全同步。Oracle,MySQL 和PostgreSQL都包括用于给备用的复制数据库传输日志的日志传输协议。Oracle还把日志产品化为一个通用的数据订阅机制,这样非Oracle数据订阅用户就可以使用XStreams和GoldenGate订阅数据了,MySQL和PostgreSQL上的类似的实现则成为许多数据结构的关键组件。

正是由于这样的起源,机器可识别的日志的概念大部分都被局限在数据库内部。日志用做数据订阅的机制似乎是偶然出现的,不过要把这种 抽象用于支持所有类型的消息传输、数据流和实时数据处理是不切实际的。

日志解决了两个问题:更改动作的排序和数据的分发,这两个问题在分布式数据系统里显得尤为重要。协商出一致的更改动作的顺序(或者说保持各个子系统本身的做法,但可以进行存在副作用的数据拷贝)是分布式系统设计的核心问题之一。

以日志为中心实现分布式系统是受到了一个简单的经验常识的启发,我把这个经验常识称为状态机复制原理:如果两个相同的、确定性的进程从同一状态开始,并且以相同的顺序获得相同的输入,那么这两个进程将会生成相同的输出,并且结束在相同的状态

这也许有点难以理解,让我们更加深入的探讨,弄懂它的真正含义。

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

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

以相同的顺序获得相同输入的地方应当引起注意-这就是引入日志的地方。这儿有一个重要的常识:如果给两段确定性代码相同的日志输入,那么它们就会生成相同的输出。

分布式计算这方面的应用就格外明显。你可以把用多台机器一起执行同一件事情的问题缩减为实现分布式一致性日志为这些进程输入的问题。这儿日志的目的是把所有非确定性的东西排除在输入流之外,来确保每个复制进程能够同步地处理输入。

当你理解了这个以后,状态机复制原理就不再复杂或者说不再深奥了:这或多或少的意味着“确定性的处理过程就是确定性的”。不管怎样,我都认为它是分布式系统设计里较常用的工具之一。

这种方式的一个美妙之处就在于索引日志的时间戳就像时钟状态的一个副本——你可以用一个单独的数字描述每一个副本,这就是经过处理的日志的时间戳。时间戳与日志一一对应着整个副本的状态。

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

一千个人眼中有一千种日志的用法。数据库工作者通常区分物理日志和逻辑日志。物理日志就是记录每一行被改变的内容。逻辑日志记录的不是改变的行而是那些引起行的内容被改变的SQL语句(insert,update和delete语句)。

分布式系统通常可以宽泛分为两种方法来处理数据和完成响应。“状态机器模型”通常引用一个主动-主动的模型——也就是我们为之记录请求和响应的对象。对此进行一个细微的更改,称之为“预备份模型”,就是选出一个副本做为leader,并允许它按照请求到达的时间来进行处理并从处理过程中输出记录其状态改变的日志。其他的副本按照leader状态改变的顺序而应用那些改变,这样他们之间达到同步,并能够在leader失败的时候接替leader的工作。

为了理解两种方式的不同,我们来看一个不太严谨的例子。假定有一个算法服务的副本,保持一个独立的数字作为它的状态(初始值为0),并对这个值进行加法和乘法运算。主动-主动方式应该会输出所进行的变换,比如“+1”,“*2”等。每一个副本都会应用这些变换,从而得到同样的解集。主动-被动方式将会有一个独立的主体执行这些变换并输出结果日志,比如“1”,“3”,“6”等。这个例子也清楚的展示了为什么说顺序是保证各副本间一致性的关键:一次加法和乘法的顺序的改变将会导致不同的结果。

分布式日志可以理解为一致性问题模型的数据结构。因为日志代表了后续追加值的一系列决策。你需要重新审视Paxos算法簇,尽管日志模块是他们最常见的应用。 在Paxos算法中,它通常通过使用称之为多paxos的协议,这种协议将日志建模为一系列的问题,在日志中每个问题都有对应的部分。在ZAB, RAFT等其它的协议中,日志的作用尤为突出,它直接对维护分布式的、一致性的日志的问题建模。

我怀疑的是,我们就历史发展的观点是有偏差的,可能是由于过去的几十年中,分布式计算的理论远超过了其实际应用。在现实中,共识的问题是有点太简单了。计算机系统很少需要决定单个值,他们几乎总是处理成序列的请求。这样的记录,而不是一个简单的单值寄存器,自然是更加抽象。

此外,专注于算法掩盖了 抽象系统需要的底层的日志。我怀疑,我们最终会把日志中更注重作为一个商品化的基石,不论其是否以同样的方式 实施的,我们经常谈论一个哈希表而不是纠结我们 得到是不是具体某个细节的哈希表,例如线性或者带有什么什么其它变体哈希表。日志将成为一种大众化的接口,为大多数算法和其实现提升提供最好的保证和最佳的性能。

让我们继续聊数据库。数据库中存在着大量变更日志和表之间的二相性。这些日志有点类似借贷清单和银行的流程,数据库表就是当前的盈余表。如果你有大量的变更日志,你就可以使用这些变更用以创建捕获当前状态的表。这张表将记录每个关键点(日志中一个特别的时间点)的状态信息。这就是为什么日志是非常基本的数据结构的意义所在:日志可用来创建基本表,也可以用来创建各类衍生表。同时意味着可以存储非关系型的对象。

这个流程也是可逆的:如果你正在对一张表进行更新,你可以记录这些变更,并把所有更新的日志发布到表的状态信息中。这些变更日志就是你所需要的支持准实时的克隆。基于此,你就可以清楚的理解表与事件的二相性: 表支持了静态数据而日志捕获变更。日志的魅力就在于它是变更的完整记录,它不仅仅捕获了表的最终版本的内容,它还记录了曾经存在过的其它版本的信息。日志实质上是表历史状态的一系列备份。

这可能会引起你对源代码的版本管理。源代码管理和数据库之间有密切关系。版本管理解决了一个大家非常熟悉的问题,那就是什么是分布式数据系统需要解决的--- 时时刻刻在变化着的分布式管理。版本管理系统通常以补丁的发布为基础,这实际上可能是一个日志。您可以直接对当前 类似于表中的代码做出“快照”互动。你会注意到, 与其他分布式状态化系统类似,版本控制系统 当你更新时会复制日志,你希望的只是更新补丁并将它们应用到你的当前快照中。

最近,有些人从Datomic --一家销售日志数据库的公司得到了一些想法。这些想法使他们对如何 在他们的系统应用这些想法有了开阔的认识。 当然这些想法不是只针对这个系统,他们会成为 十多年分布式系统和数据库文献的一部分。

这可能似乎有点过于理想化。但是不要悲观!我们会很快把它实现。

在这篇文章的其余部分,我将试图说明日志除了可用在分布式计算或者抽象分布式计算模型内部之外,还可用在哪些方面。其中包括:

数据集成-让机构的全部存储和处理系统里的所有数据很容易地得到访问。

实时数据处理-计算生成的数据流。

分布式系统设计-实际应用的系统是如何通过使用集中式日志来简化设计的。

所有这些用法都是通过把日志用做单独服务来实现的。

在上面任何一种用法里,日志的用途开始都是使用了日志所能提供的某个简单功能:生成永久的、可重现的历史记录。令人意外的是,问题的核心是可以让多少台机器以特定的方式,按照自身的速度重现历史记录的能力。

请让我首先解释 一下“数据集成”是什么意思,还有为什么我觉得它很重要,之后我们再来看看它和日志有什么关系。

数据集成就是将数据组织起来,使得在与其有关的服务和系统中可以访问它们。“数据集成”(data integration)这个短语应该不止这么简单,但是我找不到一个更好的解释。而更常见的术语 ETL 通常只是覆盖了数据集成的一个有限子集(译注:ETL,Extraction-Transformation-Loading的缩写,即数据提取、转换和加载)——相对于关系型数据仓库。但我描述的东西很大程度上可以理解为,将ETL推广至实时系统和处理流程。

你一定不会听到数据集成就兴趣盎然屏住呼吸,并且天花乱坠的想到关于大数据的概念,不过,我相信世俗的问题“让数据可被访问” 是一个组织应该关注的有价值的事情。

对数据的高效使用遵循一种  。金字塔的基础部分包括捕获所有相关数据,能够将它们全部放到适当的处理环境(那个环境应该是一个奇妙的实时查询系统,或者仅仅是文本文件和python脚本)。这些数据需要以统一的方式建模,这样就可以方便读取和数据处理。如果这种以统一的方式捕获数据的基本需求得到满足,那么就可以在基础设施上以若干种方法处理这些数据——映射化简(MapReduce),实时查询系统,等等。

很明显,有一点值得注意:如果没有可靠的、完整的数据流,Hadoop集群除了象昂贵的且难于安装的空间取暖器哪样外不会做更多事情了。一旦数据和处理可用,人们就会关心良好数据模型和一致地易于理解的语法哪些更细致的问题。最后,人们才会关注更加高级的处理-更好的可视化、报表以及处理和预测算法。 

以我的经验,大多数机构在数据金字塔的底部存在巨大的漏洞-它们缺乏可靠的、完整的数据流-而是打算直接跳到高级数据模型技术上。这样做完全是反着来做的。

因此,问题是我们如何构建通过机构内所有数据系统的可靠的数据流。

两种趋势使数据集成变得更困难。

第一个趋势是增长的事件数据(event data)。事件数据记录的是发生的事情,而不是存在的东西。在web系统中,这就意味着用户活动日志,还有为了可靠的操作以及监控数据中心的机器的目的,所需要记录的机器级别的事件和统计数字。人们倾向称它们为“日志数据”,因为它们经常被写到应用的日志中,但是这混淆了形式与功能。这种数据位于现代web的中心:归根结底,Google的资产是由这样一些建立在点击和映像基础之上的相关管道所生成的——那也就是事件。

这些东西并不是仅限于网络公司,只是网络公司已经完全数字化,所以它们更容易用设备记录。财务数据一直是面向事件的。RFID(无线射频识别)将这种跟踪能力赋予物理对象。我认为这种趋势仍将继续,伴随着这个过程的是传统商务活动的数字化。

这种类型的事件数据记录下发生的事情,而且往往比传统数据库应用要大好几个数量级。这对于处理提出了重大挑战。

第二个趋势来自于专门的数据系统的爆发,通常这些数据系统在最近的五年中开始变得流行,并且可以免费获得。专门的数据系统是为OLAP, 搜索, 简单 在线 存储, 批处理, 图像分析, 等 等 而存在的。

更多的不同类型数据的组合,以及将这些数据存放到更多的系统中的愿望,导致了一个巨大的数据集成问题。

为了处理系统之间的数据流,日志是最自然的数据结构。其中的秘诀很简单:

将所有组织的数据提取出来,并将它们放到一个中心日志,以便实时查阅。

每个逻辑数据源都可以建模为它自己的日志。一个数据源可以是一个应用程序的事件日志(如点击量或者页面浏览量),或者是一个接受修改的数据库表。每个订阅消息的系统都尽可能快的从日志读取信息,将每条新的记录保存到自己的存储,并且提升其在日志中的地位。订阅方可以是任意一种数据系统 —— 一个缓存,Hadoop,另一个网站中的另一个数据库,一个搜索系统,等等。

例如,日志针对每个更改给出了逻辑时钟的概念,这样所有的订阅方都可以被测量。推导不同的订阅系统的状态也因此变得相对简单的多,因为每个系统都有一个读取动作的“时间点”。

为了让这个显得更具体,我们考虑一个简单的案例,有一个数据库和一组缓存服务器集群。日志提供了一种同步更新所有这些系统,并推导出每一个系统的接触时间点的方法。我们假设写了一条日志X,然后需要从缓存做一次读取。如果我们想保证看到的不是陈旧的数据,我们只需保证没有从任何尚未复制X的缓存中读取即可。

日志也起到缓存的作用,使数据生产与数据消费相同步。由于许多原因这个功能很重要,特别是在多个订阅方消费数据的速度各不相同的时候。这意味着一个订阅数据系统可以宕机,或者下线维护,之后重新上线以后再赶上来:订阅方按照自己控制的节拍来消费数据。批处理系统,如Hadoop或者是一个数据仓库,或许只是每小时或者每天消费一次数据,而实时查询系统可能需要及时到秒。由于无论是原始数据源还是日志,都没有各种目标数据系统的相关知识,因此消费方系统可以被添加和删除,而无需传输管道的变化。

"每个工作数据管道设计得就像是一个日志;每个损坏的数据管道以其自己的方式损坏。"—Count Leo Tolstoy (由作者翻译)

特别重要的是:目标系统只知道日志,不知道数据源系统的任何细节。消费方系统自身无需考虑数据到底是来自于一个RDBMS(关系型数据库管理系统Relational Database Management System),一种新型的键值存储,或者它不是由任何形式的实时查询系统所生成的。这似乎是一个小问题,但实际上是至关重要的。

这里我使用术语“日志”取代了“消息系统”或者“发布-订阅”,因为它在语义上更明确,并且对支持数据复制的实际实现这样的需求,有着更接近的描述。我发现“发布订阅”并不比间接寻址的消息具有更多的含义——如果你比较任何两个发布-订阅的消息传递系统的话,你会发现他们承诺的是完全不同的东西,而且大多数模型在这一领域都不是有用的。你可以认为日志是一种消息系统,它具有持久性保证和强大的订阅语义。在分布式系统中,这个通信模型有时有个(有些可怕的)名字叫做原子广播。

值得强调的是,日志仍然只是基础设施。这并不是管理数据流这个故事的结束:故事的其余部分围绕着元数据,模式,兼容性,以及处理数据结构的所有细节及其演化。除非有一种可靠的,一般的方法来处理数据流运作,语义在其中总是次要的细节。

在LinkedIn从集中式关系数据库向分布式系统集合转化的过程中,我看到这个数据集成问题迅速演变。

现在主要的数据系统包括:

 (键值存储)(译注:一种分布式数据库)

OLAP查询引擎(译注:OLAP联机分析技术)

 (监控图表和指标服务)

这些都是专门的分布式系统,在其专业领域提供先进的功能。

这种使用日志作为数据流的思想,甚至在我到这里之前就已经与LinkedIn相伴了。我们开发的一个最早的基础设施之一,是一种称为databus 的服务,它在我们早期的Oracle表上提供了一种日志缓存抽象,可伸缩订阅数据库修改,这样我们就可以很好支持我们的社交网络和搜索索引。

我会给出一些历史并交代一下上下文。我首次参与到这些大约是在2008年左右,在我们转移键值存储之后。我的下一个项目是让一个工作中的Hadoop配置演进,并给其增加一些我们的推荐流程。由于缺乏这方面的经验,我们自然而然的安排了数周计划在数据的导入导出方面,剩下的时间则用来实现奇妙的预测算法。这样我们就开始了长途跋涉。

我们本来计划是仅仅将数据从现存的Oracle数据仓库中剖离。但是我们首先发现将数据从Oracle中迅速取出是一种黑暗艺术。更糟的是,数据仓库的处理过程与我们为Hadoop而计划的批处理生产过程不适合——其大部分处理都是不可逆转的,并且与即将生成的报告具体相关。最终我们采取的办法是,避免使用数据仓库,直接访问源数据库和日志文件。最后,我们为了加载数据到键值存储 并生成结果,实现了另外一种管道。

这种普通的数据复制最终成为原始开发项目的主要内容之一。糟糕的是,在任何时间任意管道都有一个问题,Hadoop系统很大程度上是无用的——在错误的数据基础上运行奇特的算法,只会产生更多的错误数据。

虽然我们已经以一种通用的方式创建事物,但是每个数据源都需要自定义配置安装。这也被证明是巨量错误与失败的根源。我们在Hadoop上实现的网站功能已经开始流行起来,同时我们发现我们有一长串感兴趣的工程师。每个用户都有他们想要集成的一系列系统,他们想要的一系列新数据源.

有些东西在我面前开始渐渐清晰起来。

首先,我们已建成的通道虽然有一些杂乱,但实质上它们是很有价值的。在采用诸如Hadoop的新的处理系统生成可用数据的过程,它开启了大量的可能性。 基于这些数据过去很难实现的计算,如今变为可能。 许多新的产品和分析技术都来源于把分片的数据放在一起,这些数据过被锁定在特定的系统中。

第二, 众所周知,可靠的数据加载需要数据通道的深度支持。如果我们可以捕获所有我们需要的结构,我就就可以使得Hadoop数据全自动的加载,这样就不需要额外的操作来增加新的数据源或者处理模式变更--数据就会自动的出现在HDFS,Hive表就会自动的生成对应于新数据源的恰当的列。

第三,我们的数据覆盖率仍然非常低。如果你查看存储于Hadoop中的可用的Linked 数据的全部百分比,它仍然是不完整的。花费大量的努力去使得各个新的数据源运转起来,使得数据覆盖度完整不是一件容易的事情。

我们正在推行的,为每个数据源和目标增建客户化数据加载,这种方式很显然是不可行的。我们有大量的数据系统和数据仓库。把这些系统和仓库联系起来,就会导致任意一对系统会产生如下所示的客户化通道。

需要注意的是:数据是双向流动的:例如许多系统诸如数据库和Hadoop既是数据转化的来源又是数据转化的目的地。这就意味着我们我们不必为每个系统建立两个通道:一个用于数据输入,一个用于数据输出。

这显然需要一大群人,而且也不具有可操作性。随着我们接近完全连接,最终我们将有差不多O(N2)条管道。

替代的,我们需要像这样通用的东西:

我们需要尽可能的将每个消费者与数据源隔离。理想情形下,它们应该只与一个单独的数据仓库集成,并由此让他们能访问到所有东西。

这个思想是增加一个新的数据系统——或者它是一个数据源或者它是一个数据目的地——让集成工作只需连接到一个单独的管道,而无需连接到每个数据消费方。

这种经历使得我关注创建Kafka来关联我们在消息系统所见的与数据库和分布式系统内核所发布的日志。我们希望一些实体作为中心的通道,首先用于所有的活动数据,逐步的扩展到其他用途,例如Hadoop外的数据实施,数据监控等。

在相当长的时间内,Kafka是独一无二的底层产品,它既不是数据库,也不是日志文件收集系统,更不是传统的消息系统。但是最近Amazon提供了非常类似Kafka的服务,称之为Kinesis.相似度包括了分片处理的方式,数据的保持,甚至包括在Kafka API中,有点特别的高端和低端消费者分类。我很开心看到这些,这表明了你已经创建了很好的底层协议,AWS已经把它作为服务提供。他们对此的期待与我所描述的吻合:通道联通了所有的分布式系统,诸如DynamoDB, RedShift, S3等,它同时作为使用EC2进行分布式流处理的基础。

我们再来聊聊数据仓库。数据仓库是清洗和归一数据结构用于支撑数据分析的仓库。这是一个伟大的理念。对不熟悉数据仓库概念的人来说,数据仓库方法论包括了:周期性的从数据源抽取数据,把它们转化为可理解的形式,然后把它导入中心数据仓库。对于数据集中分析和处理,拥有高度集中的位置存放全部数据的原始副本是非常宝贵的资产。在高层级上,也许你抽取和加载数据的顺序略微调整,这个方法论不会有太多变化,无论你使用传统的数据仓库Oracle还是Teradata或者Hadoop。

数据仓库是极其重要的资产,它包含了原始的和规整的数据,但是实现此目标的机制有点过时了。

对以数据为中心的组织关键问题是把原始的归一数据联结到数据仓库。数据仓库是批处理的基础查询:它们适用于各类报表和临时性分析,特别是当查询包含了简单的计数、聚合和过滤。但是如果一个批处理系统仅仅包含了原始的完整的数据的数据仓库,这就意味着这些数据对于实时数据处理、搜索索引和系统监控等实时的查询是不可用的。

依我之见,ETL包括两件事:首先,它是抽取和数据清洗过程--特别是释放被锁在组织的各类系统中的数据,移除系统专有的无用物。第二,依照数据仓库的查询重构数据。例如使其符合关系数据库类型系统,强制使用星号、雪花型模式,或者分解为高性能的柱状格式等。合并这两者是有困难的。这些规整的数据集应当可以在实时或低时延处理中可用,也可以在其它实施存储系统索引。

在我看来,正是因为这个原因有了额外好处:使得数据仓库ETL更具了组织级的规模。数据仓库的精典问题是数据仓库负责收集和清洗组织中各个组所生成的全部数据。各组织的动机是不同的,数据的生产者并不知晓在数据仓库中数据的使用情况,最终产生的数据很难抽取,或者需要花费规模化的转化才可以转化为可用的形式。当然, 中心团队不可能恰到好处的掌握规模,使得这规模刚好与组织中其它团队相匹配,因此数据的覆盖率常常差别很大,数据流是脆弱的同时变更是缓慢的。

较好的方法是有一个中心通道,日志和用于增加数据的定义良好的API。与通道集成的且提供良好的结构化的数据文件的职责依赖于数据的生产者所生成的数据文件。这意味着在设计和实施其它系统时应当考虑数据的输出以及输出的数据如何转化为结构良好的形式并传递给中心通道。增加新的存储系统倒是不必因为数据仓库团队有一个中心结点需要集成而关注数据仓库团队。数据仓库团队仅需处理简单的问题,例如从中心日志中加载结构化的数据,向其它周边系统实施个性化的数据转化等。

如图所示:当考虑在传统的数据仓库之外增加额外的数据系统时,组织结构的可扩展性显得尤为重要。例如,可以考虑为组织的完整的数据集提供搜索功能。或者提供二级的数据流监控实时数据趋势和告警。无论是这两者中的哪一个,传统的数据仓库架构甚至于Hadoop聚簇都不再适用。更糟的是,ETL的流程通道的目的就是支持数据加载,然而ETL似乎无法输出到其它的各个系统,也无法通过引导程序,使得这些外围的系统的各个架构成为适用于数据仓库的重要资产。这就不难解释为什么组织很难轻松的使用它的全部数据。反之,如果组织已建立起了一套标准的、结构良好的数据,那么任何新的系统要使用这些数据仅仅需要与通道进行简单的集成就可以实现。

这种架构引出了数据清理和转化在哪个阶段进行的不同观点:

由数据的生产者在把数据增加到公司全局日志之前。

在日志的实时转化阶段进行,这将会产生一个新的转化日志。

在向目标系统加载数据时,做为加载过程的一部分进行。

理想的模形是:由数据的生产者在把数据发布到日志之前对数据进行清理。这样可以确保数据的权威性,不需要维护其它的遗留物例如为数据产生的特殊处理代码或者维护这些数据的其它的存储系统。这些细节应当由产生数据的团队来处理,因为他们最了解他们自己的数据。这个阶段所使用的任何逻辑都应该是无损的和可逆的。

任何可以实时完成的增值转化类型都应当基于原始日志进行后期处理。这一过程包括了事件数据的会话流程,或者增加大众感兴趣的衍生字段。原始的日志仍然是可用的,但是这种实时处理产生的衍生日志包含了参数数据。

最终,只有针对目标系统的聚合需要做了加载流程的一部分。它包括了把数据转化成特定的星型或者雪花状模式,从而用于数据仓库的分析和报表。因为在这个阶段,大部分自然的映射到传统的ETL流程中,而现在它是在一个更加干净和规整的数据流集在进行的,它将会更加的简单。

我们再来聊聊这种架构的优势:它支持解耦和事件驱动的系统。

在网络行业取得活动数据的典型方法是把它记为文本形式的日志,这些文本文件是可分解进入数据仓库或者Hadoop,用于聚合和查询处理的。由此产生的问题与所有批处理的ETL的问题是相同的:它耦合了数据流进入数据仓库系统的能力和流程的调度。

在LinkedIn中,我们已经以中心日志的方式构建了事件数据处理。我们正在使用Kafka做为中心的、多订阅者事件日志。我们已经定义了数百种事件类型,每种类型都会捕获用于特定类型动作的独特的属性。这将会覆盖包括页面视图、表达式、搜索以及服务调用、应用异常等方方面面。

为了进一步理解这一优势:设想一个简单的事务--在日志页面显示已发布的日志。这个日志页面应当只包括显示日志所需要的逻辑。然而,在相当多的动态站点中,日志页面常常变的添加了很多与显示日志无关的逻辑。例如,我们将对如下的系统进行集成:

需要把数据传送到Hadoop和数据仓库中用于离线数据处理。

需要对视图进行统计,确保视图订阅者不会攻击一些内容片段。

需要聚合这些视图,视图将用于作业发布者的分析页面显示。

需要记录视图以确保我们为作业推荐的使用者提供了恰当的印象覆盖,我们不想一次次的重复同样的事情。

推荐系统需要记录日志用于正确的跟踪作业的普及度。

不久,简单的作业显示变得相当的复杂。我们增加了作业显示的其它终端--移动终端应用等--这些逻辑必须继续存在,复杂度不断的增加。更糟的是我们需要与之做接口交互的系统现在是错综复杂的--在为显示日作业而工作的工程师们需要知晓多个其它系统和它们的特征,才可以确保它们被正确的集成了。这仅仅是问题的简单版本,真实的的应用系统只会更加的复杂。

“事件驱动”的模式提供了一种简化这类问题的机制。作业显示页面现在只显示作业并记录与正在显示的作业,作业订阅者相关的其它属性,和其它与作业显示相关的其它有价值的属性。每个与此相关的其它系统诸如推荐系统、安全系统、作业推送分析系统和数据仓库,所有这些只是订阅种子文件,并进行它们的操作。显示代码并不需要关注其它的系统,也不需要因为增加了数据的消费者而相应的进行变更。

当然,把发布者与订阅者分离不再是什么新鲜事了。但是如果你想要确保提交日志的行为就像多个订阅者实时的分类日志那样记录网站发生的每件事时,可扩展性就会成为你所面临的首要挑战。如果我们不能创建快速、高性价比和可扩展性灵活的日志以满足实际的可扩展需求,把日志做为统一的集成机制不再是美好的想像,

人们普遍认为分布式日志是缓慢的、重量经的概念(并且通常会把它仅仅与“原数据”类型的使用联系起来,对于这类使用Zookeeper可以适用)。但是深入实现并重点关注分类记录大规模的数据流,这种需求是不切实际的。在LinkedIn, 我们现在每天通过Kafka运行着超过600亿个不同的消息写入点(如果统计镜相与数据中心之间的写入,那么这个数字会是数千亿。)

我们在Kafk中使用了一些小技巧来支持这种可扩展性:

通过批处理读出和写入优化吞吐力

为了确保水平可扩展性,我们把日志进行切片:

个切片都是一篇有序的日志,但是各片之间没有全局的次序(这个有别于你可能包含在消息中的挂钟时间)。把消息分配到特定的日志片段这是由写入者控制的,大部分使用者会通过用户ID等键值来进行分片。分片可以把日志追加到不存在协作的片段之间,也可以使系统的吞吐量与Kafka聚簇大小成线性比例关系。

每个分片都是通过可配置数量的复制品复制的,每个复制品都有分片的一份完全一致的拷贝。无论何时,它们中的任一个都可以做为主分片,如果主分片出错了,任何一个复制品都可以接管并做为主分片。

缺少跨分片的全局顺序是这个机制的局限性,但是我们不认为它是最主要的。事实上,与日志的交互主要来源于成百上千个不同的流程,以致于对于它们的行为排一个总体的顺序是没什么意义的。相反,我们可以确保的是我们提供的每个分片都是按顺序保留的。Kafka保证了追加到由单一发送者送出的特定分片会按照发送的顺序依次处理。

日志,就像文件系统一样,是容易优化成线性可读可写的样式的。日志可以把小的读入和写出组合成大的、高吞吐量的操作。Kafka一直至立于实现这一优化目标。批处理可以发生在由客户端向服务器端发送数据、写入磁盘;在服务器各端之间复制;数据传递给消费者和确认提交数据等诸多环节。

最终,Kafka使用简单的二进制形式维护内存日志,磁盘日志和网络数据传送。这使得我们可以使用包括“Zero Copy”在内的大量的优化机制。

这些优化的积累效应是你常常进行的写出和读入数据的操作可以在磁盘和网络上得到支持,甚至于维护内存以外的大量数据集。

这些详细记述并不意味着这是关于Kafka的主要内容,那么我就不需要了解细节了。你可阅读到更多的关于LinkedIn的方法在这个链接,和Kafka的设计总述在这个链接。

到此为止,我只是描述从端到端数据复制的理想机制。但是在存储系统中搬运字节不是所要讲述内容的全部。最终我们发现日志是流的另一种说法,日志是流处理的核心。

但是,等等,什么是流处理呢?

如果你是90年代晚期或者21世纪初数据库文化或者数据基础架构产品的爱好者,那么你就可能会把流处理与建创SQL引擎或者创建“箱子和箭头”接口用于事件驱动的处理等联系起来。

如果你关注开源数据库系统的大量出现,你就可能把流处理和一些开源数据库系统关联起来,这些系统包括了:Storm,Akka,S4和Samza.但是大部分人会把这些系统作为异步消息处理系统,这些系统与支持群集的远程过程调用层的应用没什么差别(而事实上在开源数据库系统领域某些方面确实如此)。

这些视图都有一些局限性。流处理与SQL是无关的。它也局限于实时流处理。不存在内在的原因限制你不能处理昨天的或者一个月之前的流数据,且使用多种不同的语言表达计算。

我把流处理视为更广泛的概念:持续数据流处理的基础架构。我认为计算模型可以像MapReduce或者分布式处理架构一样普遍,但是有能力处理低时延的结果。

处理模型的实时驱动是数据收集方法。成批收集的数据是分批处理的。数据是不断收集的,它也是按顺序不断处理的。

美国的统计调查就是成批收集数据的良好典范。统计调查周期性的开展,通过挨门挨户的走访,使用蛮力发现和统计美国的公民信息。1790年统计调查刚刚开始时这种方式是奏效的。那时的数据收集是批处理的,它包括了骑着马悠闲的行进,把信息写在纸上,然后把成批的记录传送到人们统计数据的中心站点。现在,在描述这个统计过程时,人们立即会想到为什么我们不保留出生和死亡的记录,这样就可以产生人口统计信息这些信息或是持续的或者是其它维度的。

这是一个极端的例子,但是大量的数据传送处理仍然依赖于周期性的转储,批量转化和集成。处理大容量转储的唯一方法就是批量的处理。但是随着这些批处理被持续的供给所取代,人们自然而然的开始不间断的处理以平滑的处理所需资源并且消除延迟。

例如LinkedIn几乎没有批量数据收集。大部分的数据或者是活动数据或者是数据库变更,这两者都是不间断发生的。事实上,你可以想到的任何商业,正如:Jack Bauer告诉我们的,低层的机制都是实时发生的不间断的流程事件。数据是成批收集的,它总是会依赖于一些人为的步骤,或者缺少数字化或者是一些自动化的非数字化流程处理的遗留信息。当传送和处理这些数据的机制是邮件或者人工的处理时,这一过程是非常缓慢的。首轮自动化总是保持着最初的处理形式,它常常会持续相当长的时间。

每天运行的批量处理作业常常是模拟了一种一天的窗口大小的不间断计算。当然,低层的数据也经常变化。在LinkedIn,这些是司空见贯的,并且使得它们在Hadoop运转的机制是有技巧的,所以我们实施了一整套管理增量的Hadoop工作流的架构。

由此看来,对于流处理可以有不同的观点。流处理包括了在底层数据处理的时间概念,它不需要数据的静态快照,它可以产生用户可控频率的输出,而不用等待数据集的全部到达。从这个角度上讲,流处理就是广义上的批处理,随着实时数据的流行,会儿更加普遍。

这就是为什么从传统的视角看来流处理是利基应用。我个人认为最大的原因是缺少实时数据收集使得不间断的处理成为了学术性的概念。

我想缺少实时数据收集就像是商用流处理系统注定的命运。他们的客户仍然需要处理面向文件的、每日批量处理ETL和数据集成。公司建设流处理系统关注的是提供附着在实时数据流的处理引擎,但是最终当时极少数人真正使用了实时数据流。事实上,在我在LinkedIn工作的初期,有一家公司试图把一个非常棒的流处理系统销售给我们,但是因为当时我们的全部数据都按小时收集在的文件里,当时我们提出的最好的应用就是在每小时的最后把这些文件输入到流处理系统中。他们注意到这是一个普遍性的问题。这些异常证明了如下规则:流处理系统要满足的重要商业目标之一是:财务, 它是实时数据流已具备的基准,并且流处理已经成为了瓶颈。

甚至于在一个健康的批处理系统中,流处理作为一种基础架构的实际应用能力是相当广泛的。它跨越了实时数据请求-应答服务和离线批量处理之间的鸿沟。现在的互联网公司,大约25%的代码可以划分到这个类型中。

最终这些日志解决了流处理中绝大部分关键的技术问题。在我看来,它所解决的最大的问题是它使得多订阅者可以获得实时数据。对这些技术细节感兴趣的朋友,我们可以用开源的Samza,它是基于这些理念建设的一个流处理系统。这些应用的更多技术细节我们在此文档中有详细的描述。

流处理最有趣的角度是它与流处理系统内部无关,但是与之密切相关的是如何扩展了我们谈到的早期数据集成的数据获取的理念。我们主要讨论了基础数据的获取或日志--事件和各类系统执行中产生的数据等。但是流处理允许我们包括了计算其它数据的数据。这些衍生的数据在消费者看来与他们计算的原始数据没什么差别。这些衍生的数据可以按任意的复杂度进行压缩。

让我们再深入一步。我们的目标是:流处理作业可以读取任意的日志并把日志写入到日志或者其它的系统中。他们用于输入输出的日志把这些处理关联到一组处理过程中。事实上,使用这种样式的集中日志,你可以把组织全部的数据抓取、转化和工作流看成是一系列的日志和写入它们的处理过程。

流处理器根本不需要理想的框架:它可能是读写日志的任何处理器或者处理器集合,但是额外的基础设施和辅助可以提供帮助管理处理代码。

日志集成的目标是双重的:

首先,它确保每个数据集都有多个订阅者和有序的。让我们回顾一下状态复制原则来记住顺序的重要性。为了使这个更加具体,设想一下从数据库中更新数据流--如果在处理过程中我们把对同一记录的两次更新重新排序,可能会产生错误的输出。 TCP之类的链接仅仅局限于单一的点对点链接,这一顺序的持久性要优于TCP之类的链接,它可以在流程处理失败和重连时仍然存在。

第二,日志提供了流程的缓冲。这是非常基础的。如果处理流程是非同步的,那么上行生成流数据的作业比下行消费流数据的作业运行的更快。这将会导致处理流程阻塞,或者缓冲数据,或者丢弃数据。丢弃数据并不是可行的方法,阻塞将会导致整个流程图立即停止。 日志实际上是一个非常大的缓冲,它允许流程重启或者停止但不会影响流程图其它部分的处理速度。如果要把数据流扩展到更大规模的组织,如果处理作业是由多个不同的团队提供的,这种隔离性是极其重的。我们不能容忍一个错误的作业引发后台的压力,这种压力会使得整个处理流程停止。

Storm和Sama这两者都是按非同步方式设计的,可以使用Kafka或者其它类似的系统作为它们的日志。

一些实时流处理在转化时是无状态的记录。在流处理中大部分的应用会是相当复杂的统计、聚合、不同窗口之间的关联。例如有时人们想扩大包含用户操作信息的事件流(一系列的单击动作)--实际上关联了用户的单击动作流与用户的账户信息数据库。不变的是这类流程最终会需要由处理器维护的一些状态信息。例如数据统计时,你需要统计到目前为止需要维护的计数器。如果处理器本身失败了,如何正确的维护这些状态信息呢?

最简单的替换方案是把这些状态信息保存在内存中。但是如果流程崩溃,它就会丢失中间状态。如果状态是按窗口维护的,流程就会回退到日志中窗口开始的时间点上。但是,如果统计是按小时进行的,那么这种方式就会变得不可行。

另一个替换方案是简单的存储所有的状态信息到远程的存储系统,通过网络与这些存储关联起来。这种机制的问题是没有本地数据和大量的网络间通信。

我们如何支持处理过程可以像表一样分区的数据呢?

回顾一下关于表和日志二相性的讨论。这一机制提供了工具把数据流转化为与处理过程协同定位的表,同时也提供了这些表的容错处理的机制。

流处理器可以把它的状态保存在本地的表或索引--bdb,或者leveldb,甚至于类似于Lucene 或fastbit一样不常见的索引。这些内容存储在它的输入流中(或许是使用任意的转化)。生成的变更日志记录了本地的索引,它允许存储事件崩溃、重启等的状态信息。流处理提供了通用的机制用于在本地输入流数据的随机索引中保存共同分片的状态。

当流程运行失败时,它会从变更日志中恢复它的索引。每次备份时,日志把本地状态转化成一系列的增量记录。

这种状态管理的方法有一个优势是把处理器的状态也做为日志进行维护。我们可以把这些日志看成与数据库表相对应的变更日志。事实上,这些处理器同时维护着像共同分片表一样的表。因为这些状态它本身就是日志,其它的处理器可以订阅它。如果流程处理的目标是更新结点的最后状态,这种状态又是流程的输出,那么这种方法就显得尤为重要。

为了数据集成,与来自数据库的日志关联,日志和数据库表的二象性就更加清晰了。变更日志可以从数据库中抽取出来,日志可以由不同的流处理器(流处理器用于关联不同的事件流)按不同的方式进行索引。

我们可以列举在Samza中有状态流处理管理的更多细节和大量实用的例子。

当然,我们不能奢望保存全部变更的完整日志。除非想要使用无限空间,日志不可能完全清除。为了澄清它,我们再来聊聊Kafka的实现。在Kafka中,清理有两种选择,这取决于数据是否包括关键更新和事件数据。对于事件数据,Kafka支持仅维护一个窗口的数据。通常,配置需要一些时间,窗口可以按时间或空间定义。虽然对于关键数据而言,完整日志的重要特征是你可以重现源系统的状态信息,或者在其它的系统重现。

随着时间的推移,保持完整的日志会使用越来越多的空间,重现所耗费的时间越来越长。因些在Kafka中,我们支持不同类型的保留。我们移除了废弃的记录(这些记录的主键最近更新过)而不是简单的丢弃旧日志。我们仍然保证日志包含了源系统的完整备份,但是现在我们不再重现原系统的全部状态,而是仅仅重现最近的状态。我们把这一特征称为日志压缩。

我们最后要讨论的是在线数据系统设计中日志的角色。

在分布式数据库数据流中日志的角色和在大型组织机构数据完整中日志的角色是相似的。在这两个应用场景中,日志是对于数据源是可靠的,一致的和可恢复的。组织如果不是一个复杂的分布式数据系统呢,它究竟是什么?

如果换个角度,你可以看到把整个组织系统和数据流看做是单一的分布式数据系统。你可以把所有的子查询系统(诸如Redis, SOLR,Hive表等)看成是数据的特定索引。你可以把Storm或Samza一样的流处理系统看成是发展良好的触发器和视图具体化机制。我已经注意到,传统的数据库管理人员非常喜欢这样的视图,因为它最终解释了这些不同的数据系统到底是做什么用的--它们只是不同的索引类型而已。

不可否认这类数据库系统现在大量的出现,但是事实上,这种复杂性一直都存在。即使是在关系数据库系统的鼎盛时期,组织中有大量的关系数据库系统。或许自大型机时代开始,所有的数据都存储在相同的位置,真正的集成是根本不存在的。存在多种外在需求,需要把数据分解成多个系统,这些外在需求包括:规模、地理因素、安全性,性能隔离是最常见的因素。这些需求都可以由一个优质的系统实现:例如,组织可以使用单一的Hadoop聚簇,它包括了全部的数据,可以服务于大型的和多样性的客户。

因此在向分布式系统变迁的过程中,已经存在一种处理数据的简便的方法:把大量的不同系统的小的实例聚合成为大的聚簇。许多的系统还不足以支持这一方法:因为它们不够安全,或者性能隔离性得不到保证,或者规模不符合要求。不过这些问题都是可以解决的。

依我之见,不同系统大量出现的原因是建设分布式数据库系统很困难。通过削减到单一的查询或者用例,每个系统都可以把规模控制到易于实现的程度。但是运行这些系统产生的复杂度依然很高。

未来这类问题可能的发展趋势有三种:

第一种可能是保持现状:孤立的系统还会或长或短的持续一段时间。这是因为建设分布式系统的困难很难克服,或者因为孤立系统的独特性和便捷性很难达到。基于这些原因,数据集成的核心问题仍然是如何恰当的使用数据。因此,集成数据的外部日志非常的重要。

第二种可能是重构:具备通用性的单一的系统逐步融合多个功能形成超极系统。这个超级系统表面看起来类似关系数据库系统,但是在组织中你使用时最大的不同是你只需要一个大的系统而不是无数个小系统。在这个世界里,除了在系统内已解决的这个问题不存在什么真正的数据集成问题。我想这是因为建设这样的系统的实际困难。

虽然另一种可能的结果对于工程师来说是很有吸引力的。新一代数据库系统的特征之一是它们是完全开源的。开源提供了一种可能性:数据基础架构不必打包成服务集或者面向应用的系统接口。在Java栈中,你可以看到在一定程度上,这种状况已经发生了。

用于处理多个系统之间的协调,或许会从诸如 或者等高级别的抽象中得到一些帮助。

和用于处理流程可视化和资源管理。

和等嵌入式类库做为索引。

,和,等封装成高级别的用于处理远程通信。

,,和等其它类库用于处理序列化。

如果你把这些堆放在一起,换个角度看,它有点像是简化版的分布式数据库系统工程。你可以把这些拼装在一起,创建大量的可能的系统。显而易见,现在探讨的不是最终用户所关心的API或者如何实现,而是在不断多样化和模块化的过程中如何设计实现单一系统的途径。因为随着可靠的、灵活的模块的出现,实施分布式系统的时间周期由年缩减为周,聚合形成大型整体系统的压力逐步消失。

那些提供外部日志的系统如今已允许个人电脑抛弃他们自身复杂的日志系统转而使用共享日志。在我看来,日志可以做到以下事情:

通过对节点的并发更新的排序处理数据的一致性(无论在及时还是最终情况下)

提供节点之间的数据复制

提供”commit“语法(只有当写入器确保数据不会丢失时才会写入)

位系统提供外部的数据订阅资源

提供存储失败的复制操作和引导新的复制操作的能力

这实际上是一个数据分发系统最重要的部分,剩下的大部分内容与终端调用的API和索引策略相关。这正是不同系统间的差异所在,例如:一个全文本查询语句需要查询所有的分区,而一个主键查询只需要查询负责键数据的单个节点就可以了。

下面我们来看下该系统是如何工作的。系统被分为两个逻辑区域:日志和服务层。日志按顺序捕获状态变化,服务节点存储索引提供查询服务需要的所有信息(键-值的存储可能以B-tree或SSTable的方式进行,而搜索系统可能存在与之相反的索引)。写入器可以直接访问日志,尽管需要通过服务层代理。在写入日志的时候会产生逻辑时间戳(即log中的索引),如果系统是分段式的,那么就会产生与段数目相同数量的日志文件和服务节点,这里的数量和机器数量可能会有较大差距。

服务节点订阅日志信息并将写入器按照日志存储的顺序尽快应用到它的本地索引上。

客户端只要在查询语句中提供对应的写入器的时间戳,它就可以从任何节点中获取”读写“语义。服务节点收到该查询语句后会将其中的时间戳与自身的索引比较,如果必要,服务节点会延迟请求直到对应时间的索引建立完毕,以免提供旧数据。

服务节点或许根本无需知道”控制“或”投标选择(leader election)“的概念,对很多简单的操作,服务节点可以爱完全脱离领导的情况下提供服务,日志即是信息的来源。

分发系统所需要做的其中一个比较复杂的工作,就是修复失败节点并移除几点之间的隔离。保留修复的数据并结合上各区域内的数据快照是一种较为典型的做法,它与保留完整的数据备份并从垃圾箱内回收日志的做法几乎等价。这就使得服务层简单了很多,日志系统也更有针对性。

有了这个日志系统,你可以订阅到API,这个API提供了把ETL提供给其它系统的数据内容。事实上,许多系统都可以共享.相同的日志同时提供不同的索引,如下所示:

这样一个以日志为中心的系统是如何做到既数据流的提供者又同时加载其它系统的数据的呢?因为流处理器既可以消费多个输入的数据流,随后又可以通过其它系统对数据做索引为它们提供服务。

这个系统的视图可以清晰的分解到日志和查询API,因为它允许你从系统的可用性和一致性角度分解查询的特征。这可以帮助我们对系统进行分解,并理解那些并没按这种方式设计实施的系统。

虽然Kafka和Bookeeper都是一致性日志,但这不是必须的,也没什么意义。你可以轻松的把Dynamo之类的数据构分解为一致性的AP日志和键值对服务层。这样的日志使用起来灵活,因为它重传了旧消息,像Dynamo一样,这样的处理取决于消息的订阅者。

在很多人看来,在日志中另外保存一份数据的完整复本是一种浪费。事实上,虽然有很多因素使得这件事并不困难。首先,日志可以是一种有效的存储机制。我们在Kafka生产环境的服务器上存储了5 TB的数据。同时有许多的服务系统需要更多的内存来提供有效的数据服务,例如文本搜索,它通常是在内存中的。服务系统同样也需样硬盘的优化。例如,我们的实时数据系统或者在内存外提供服务或者使用固态硬盘。相反,日志系统只需要线性的读写,因此,它很乐于使用TB量级的硬盘。最终,如上图所示,由多个系统提供的数据,日志的成本分摊到多个索引上,这种聚合使得外部日志的成本降到了最低点。

LinkedIn就是使用了这种方式实现它的多个实时查询系统的。这些系统提供了一个数据库(使用数据总线做为日志摘要,或者从Kafka去掉专用的日志),这些系统在顶层数据流上还提供了特殊的分片、索引和查询功能。这也是我们实施搜索、社交网络和OLAP查询系统的方式。事实上这种方式是相当普遍的:为多个用于实时服务的服务系统提供单一的数据(这些来自Hadoop的数据或是实时的或是衍生的)。这种方式已被证实是相当简洁的。这些系统根本不需要外部可写入的API,Kafka和数据库被用做系统的记录和变更流,通过日志你可以查询系统。持有特定分片的结点在本地完成写操作。这些结点盲目的把日志提供的数据转录到它们自己的存储空间中。通过回放上行流日志可以恢复转录失败的结点。

这些系统的程度则取决于日志的多样性。一个完全可靠的系统可以用日志来对数据分片、存储结点、均衡负载,以及用于数据一致性和数据复制等多方面。在这一过程中,服务层实际上只不过是一种缓存机制,这种缓存机制允许直接写入日志的流处理。

如果你对于本文中所谈到的关于日志的大部内容,如下内容是您可以参考的其它资料。对于同一事务人们会用不同的术语,这会让人有一些困惑,从数据库系统到分布式系统,从各类企业级应用软件到广阔的开源世界。无论如何,在大方向上还是有一些共同之处。

学术论文、系统、评论和博客:

是实施微软基于日志的分布式存储系统的通用架构。

——并不是每个人都支持把逻辑时间用于他们的日志,Google最新的数据库就尝试使用物理时间,并通过把时间戳直接做为区间来直接建时钟迁移的不确定性。

。我发现这个有助于引入容错处理和数据库以外的应用系统日志恢复。

——事实上我并不清楚反应编程的确切涵义,但是我想它和“事件驱动”指的是同一件事。这个链接并没有太多的讯息,但由久富盛史的Martin Odersky讲授的课程是很有吸引力的。

原始文章在此。Leslie Lamport有一个有趣的历史:在80年代算法是如何发现的,但是直到1998年才发表了,因为评审组不喜欢论文中的希腊寓言,而作者又不愿修改。

甚至于论文发布以后,它还是不被人们理解。Lamport再次尝试,这次它包含了一些并不有趣的小细节,这些细节是关于如何使用这些新式的自动化的计算机的。它仍然没有得到广泛的认可。

我发现所有关于Paxos的论文理解起来很痛苦,但是值得我们费大力气弄懂。你不必忍受这样的痛苦了,因为日志结构的文件系统的大师John Ousterhout的这个让这一切变得相当的容易。这些一致性算法用展开的通信图表述的更好,而不是在论文中通过静态的描述来说明。颇为讽刺的是,这个视频录制的初衷是告诉人们Paxos很难理解。

。这是一篇很棒的介绍使用日志来构造数据存储的文章,Jun是文章的共同作者之一,他也是Kafka最早期的工程师之一。

Paxos有很多的竞争者。如下诸项可以更进一步的映射到日志的实施,更适合于实用性的实施。

由Barbara Liskov提出的是直接进行日志复现建模的较早的算法。

是易于理解的一致性算法之一。由John Ousterhout讲授的这个非常的棒。

你可以的看到在不同的实时分布式数据库中动作日志角色:

是探索在大规模的传统的分布式数据库系统中实施以日志为中心设计理念的系统。

和Bigtable都是在目前的数据库系统中使用日志的样例。

LinkedIn自己的分布式数据库和PNUTs一样,使用日志来复现,但有一个小的差异是它使用自己底层的表做为日志的来源。

如果你正在做一致性算法选型,这篇会对你所有帮助。

,这是收录了分布式系统一致性的大量论文的一本巨著。网上有该书的诸多章节。

流处理:这个话题要总结的内容过于宽泛,但还是有几件我所关注的要提一下:

:这篇论文讨论了Spark的流式系统。

:它可能是研究这一领域的最佳概述之一。

企业级软件存在着同样的问题,只是名称不同,或者规模较小,或者是XML格式的。哈哈,开个玩笑。

--据我所知:它就是企业级应用的工程师们常说的“状态机的复现”。有趣的是同样的理念会用在如此迥异的场景中。事件驱动关注的是小的、内存中的使用场景。这种机制在应用开发中看起来是把发生在日志事件中的“流处理”和应用关联起来。因此变得不那么琐碎:当处理的规模大到需要数据分片时,我关注的是流处理作为独立的首要的基础设施。

--在数据库之外会有些对于数据的舍入处理,这些处理绝大多数都是日志友好的数据扩展。

,当你有一些现成的类似客户类系管理CRM和供应链管理SCM的软件时,它似乎可以解决数据集成的问题。

没有人知道它的确切涵义或者它与流处理有什么不同。这些差异看起来集中在无序流和事件过滤、发现或者聚合上,但是依我之见,差别并不明显。我认为每个系统都有自己的优势。

--我认为企业服务总线的概念类似于我所描述的数据集成。在企业级软件社区中这个理念取得了一定程度的成功,对于从事网络和分布式基础架构的工程师们这个概念还是很陌生的。

是把日志作为服务的一个项目,它是后边所列各项的基础。

 和Hedwig 另外的两个开源的“把日志作为服务”的项目。它们更关注的是数据库系统内部构件而不是事件数据。

是提供类似日志的数据库表的覆盖层的系统。

 是用于Scala的动作者架构。它有一个事件驱动的插件,它提供持久化和记录。

 是我们在LinkedIn中用到的流处理框架,它用到了本文论述的诸多理念,同时与Kafka集成来作为底层的日志。

是广泛使用的可以很好的与Kafka集成的流处理框架之一。

一个流处理框架,它是的一部分。

是在Storm或Hadoop之上的一层,它提供了便洁的计算摘要。

对于这一领域,我将持续的关注,如何您知道一些我遗漏的内容,请您告知,谢谢。

}

1.1 智能终端产业飞速发展带来历史性机遇

当今世界物联网飞速发展,PC、手机、Pad 以及其他 IoT 设备等智能 终端飞速发展,呈指数级的增长趋势,我们逐渐进入万物互连,万物 智能的时代。

1.2 万物互联时代对操作系统提出新要求

IoT 、5G 的飞速发展带来了大量的智能终端设备,但目前不同的智 能终端应用不同的操作系统,设备间的连接复杂、操控繁琐,导致消 费者的智能体验分割,需要一个简便统一的操作系统来优化智能体 验。

1.3 中美关系背景下国产化操作系统是迫切的需求

如今,整个 PC 操作系统市场基本被 Windows 和 OS X 所占领,移动 操作系统则被 Android 和 iOS 统一,由于这些操作系统的主动权基本 掌握在外国公司手里,没有国产化的操作系统,未来中国公司还是有可能面临谷歌突然暂停向华为提供系统技术支持(GMS)这样的困境。

1.4 中国已具备终端产业的领先优势

当前,中国在 5G、智能设备、人工智能、大数据、云边计算和芯片 均有深厚的产业基础,有终端产业发展的肥沃土壤,未来中国有很大 的机会领导 5G+AI+IOT 的产业革命。

早在 2019 年,华为就有预见性地发布了——“1+8+N”全场景智慧生 活战略。未来 10 年,华为希望通过该长期战略,构建起牢固的终端 消费者生态系统。这个生态的构建,既包括华为自身的产品,也打通 了与生态伙伴之间的产品。

“1+8+N”战略的核心是 1,即智能手机。8 是指 PC、平板、智慧屏、 音箱、眼镜、手表、车机、耳机,这 8 项将由华为公司亲自研发和参 与市场,并且会追求市场领先地位。N 是摄像头、扫地机、智能秤等 外围智能硬件,涵盖移动办公、、运动健康、影音娱乐、智 慧出行五大场景模式。这些领域是与鸿蒙生态的合作伙伴进行共同开 发,在合作过程中,鸿蒙生态提供 HiLink 协议标准,HiAI 组件,Lite OS 等技术平台,同时将鸿蒙操作系统开源。

5G 为万物互联提供动力,而鸿蒙 OS 更是给万物互联提供了桥梁,给 “1+8+N”战略提供了统一的控制中心。未来,围绕鸿蒙 OS,华为可 以打造全场景智慧化生活设计。

2 及华为全场景新品发布会,正式发布鸿蒙 OS 2。

2.1 鸿蒙初衷和定位:一套代码、一个系统多终端使用

鸿蒙从一开始设计就采用全栈解耦的架构,做到一套代码满足大小系 统和硬件的要求。鸿蒙将所有业务逻辑切割开,给予每个模块标签, 根据用户需求进行模块组装,实现面对全场景的操作。“依托 HarmonyOS 的分布式能力,消费者可以按需调用、组合不同设备的软 硬件能力,为用户带来最适合其所在场景的智慧体验。今天除了鸿蒙 系统以外,没有一个系统能够做到全系统覆盖所有的设备。

2.2 基于分布式软总线的独立设备连接和自由硬件组合

鸿蒙创造性地提出分布式软总线技术,将各种各样的独立设备连接起 来。软总线就好象各个设备之间连接的一条高速公路,有了这样的能 力,消费者可以根据自己的需要来组装不同的硬件成一个超级终端。

比如一个手机想做多机位的拍摄,鸿蒙通过软总线的方式把无人机、 运动摄像头、其他设备的摄像头全部跟手机连接起来,手机可以根据 用户的需要,像调度本机摄像头一样调动其他硬件不同角度的摄像 头,组成一个多机位拍摄的超级终端。

2.3 统一控制中心,协助组建超级终端

鸿蒙系统统一的控制中心,让用户可以非常方便的操控本机以及与本 机连接的其他设备,更方便用户组成各种各样的超级终端。通过统一 控制中心的服务卡片可以完成音乐选择、输出选择、设备网络连接以 及设备状态的实时查看等功能。通过界面触控,无需复杂的硬件线连 接,只需点开超级终端页面,将悬浮在手机周围的设备拉动,就能一 键完成设备的发现、配对、连接以及组合,包括对设备的身份验证, 实现周边设备互联,组建超级终端。

超级终端将各种终端的硬件能力和终端分离开,打破终端之间的物理 边界,不仅将不同终端设备连接起来,更集每个终端最强的优势于一 身,虽然分属不同终端,但却如同在同一个终端一样。

2.4 软时钟+抗干扰算法实现高质量音画同步

超级终端使用场景:当用户在手机上观看一段非常精彩的视频,想要 提升观影体验,将视频转到客厅的大屏观看,只需要打开超级终端页 面轻轻一拉,让手机和大屏组成一个超级终端,那么瞬间手机的视频 就能在大屏上展示出来;在夜晚,为了不打扰家人,用户只需要把耳 机拉到智能终端,就能和手机、大屏组了一个新的超级终端,实现更 好的观影体验。

以上场景的实现,鸿蒙使用了软时钟同步和抗干扰算法两大关键技 术。软时钟同步通过对各路解码视频的视频数据在时钟域和数据域上 双重同步,使连接在一起的超级终端设备共同遵守一个时钟基准,保 持播出的电视画面稳定,提高观看效果;此外,无线通信频段集中了 大量无线发射、接收设备,包括路由器、手机、平板、电视以及其他 IOT 设备,大量设备同时工作会互相干扰,造成抖动、时延和丢包。 鸿蒙抗干扰算法可以将干扰降低到能够容忍的范围内。

2.5 打破硬件边界,多设备协同工作

当需要把手机图片传送到 Pad 文档时:传统场景下需要通过第三方软 件达到手机和 Pad 之间的联通,然后将所需图片传到 Pad,再进行拷贝和粘贴。在鸿蒙系统中,只需 Pad 和手机组成超级终端,在 Pad 屏 幕上操作将手机中的图片拖动到文档内,方便快捷。

对运行 Windows 系统的 PC,只需在 PC 的系统内安装鸿蒙分布式的 插件,通过鸿蒙分布式插件,能够使不同的操作系统设备之间文件管 理系统互通,方便的实现互相传输,共同组建超级终端。

2.5.3 任意组装场景化的超级终端,无穷创意空间

鸿蒙多机位模式,基于强大的分布式能力,呈现不同机位视角,超级 终端可以随意调用终端各个摄像头。

2.5.4 蚂蚁市场破局者,降低 IoT 使用成本,释放家电智慧化能力

如今的智能家电市场竞争激烈,品牌混杂,行业标准不统一,使用不 同的智能家电需要安装多个不同的 APP,导致家电 IoT 设备使用成本 高,使用便捷度低,智能设备配备的智能能力未得到发挥。

根据华为的统计情况,拥有智能家电设备的消费者,仅 10%安装了对 应的 APP,而在安装 APP 的消费者中只有 5%真正使用智能功能。 鸿蒙系统帮助智能家电设备的智慧化能力得到释放,大幅度降低 IoT设备的使用成本。通过接入鸿蒙系统的手机轻触一下搭载鸿蒙系统的 智能厨电上的 NFC 标志,无需下载 APP 直接跳转控制界面,简单实 现手机与智能家电的联网。

烤箱:用搭载鸿蒙系统的手机轻触安装鸿蒙系统的电烤箱快速联网,智 能功能通过卡片的形式展示。例如根据展示的菜谱配比食材,放入烤 箱,手机一按就完成了操作。

冰箱:过去消费者不确定食材的适当保存温度来降低营养流失,搭载鸿 蒙系统后,轻触即可看到智能化温控推荐,将食材放到最合适的温度。

2.5.5 带屏设备均能成为控制中心

基于鸿蒙分布式能力,手机、手表、PAD 均能运行统一的控制中心。 在未来鸿蒙生态里所有带屏的设备均具备控制中心能力,消费者可以 随时随地便捷操控所有设备,做到方便地控制中心与物互联。

2.6 全新的原子化服务,应用无需安装跨设备自由流转

鸿蒙操作系统基于分布式编程框架,通过原子化服务实现一次应用开 发适用所有终端。原子化服务下鸿蒙应用可以解耦出业务功能的最小 颗粒,通过免安装,卡片式交互让应用服务更高效;并可以随场景而 变,通过超级终端的组建,按场景在不同设备之间实现应用可分可合 可流转可分发,应用在不同的终端之间进行流转。

2.7 全栈优化,极致性能体验,超越安卓时代

鸿蒙全栈系统优化,通过内核层、硬件抽象层、RUNTIME 层以及框 架方面的优化努力。鸿蒙系统综合性能较基于安卓系统的 E-MUI 有大 幅度提升,有效降低内存顺序读/写,随机读/写的老化程度,给消费 者带来流畅的体验。

鸿蒙采用华为全新图形栈,图形渲染不仅仅依靠 GPU,而是联合 CPU 联合调度,解耦业务处理逻辑和渲染逻辑线程,提升画面流畅度和帧 率,并带来续航能力提升。 多设备协同认证,保证消费者隐私安全。经过验证 ID 设备才可以加 入超级终端,目前鸿蒙所有的终端认证均获得全球最高级别。

3 几大技术特性支撑鸿蒙万物互联

鸿蒙 OS 是基于微内核的全场景分布式操作系统,实现模块化解耦, 内核安全、分布架构、生态共享是鸿蒙系统的三大特性。

3.1 更灵活更安全的微内核系统

在微内核结构中,各模块采用 IPC 传递信息,这种方式天然支持分布 式系统运行,大大提高系统执行效率。基于微内核模块化、低耦合的 特性,操作系统的组件故障不会导致系统重启,系统稳定性大大提高; 微内核下的系统功能可以按需扩展,也非常容易移植。同时,鸿蒙 OS 微内核天然没有 Root,相当于微内核每个部分都有一把锁,只靠 一把钥匙无法获得所有权限,因此可以从源头提升系统安全性。

3.2 硬件互助、资源共享的分布式架构

分布式软总线架构,为异端设备互联互通提供统一基座;分 布式数据管理使得用户数据与物理设备不再绑定,实现流畅地跨终端 运行;分布式设备虚拟化平台将多种设备形成一个超级虚拟终端,各 终端可便捷调用;分布式任务调度根据不同设备的能力、位置、业务 运行状态、资源使用情况,选择合适的设备运行分布式任务。以上四大分布式技术使得鸿蒙可以实现不同的终端设备之间的快速连接、能 力互助、资源共享,匹配合适的设备、提供流畅的全场景体验。

比如场景:在烹饪时,手机可以通过碰一碰和烤箱连接,并 将自动按照菜谱设置烹调参数,控制烤箱来制作菜肴。与此类似,料 理机、油烟机、空气净化器、空调、灯、窗帘等都可以在手机端显示 并通过手机控制。设备之间即连即用,无需繁琐的配置。

3.3 一次开发,多端部署的生态共享

HarmonyOS 提供了用户程序框架、Ability 框架以及 UI 框架,借助统 一 IDE 及工具链,开发者能够实现应用的一次开发、多端部署,实现 跨终端生态共享。同时通过组件化和小型化等设计方法,支持多种终 端设备按需弹性部署。因此,基于以上三大特性:

对消费者而言,HarmonyOS 能够将生活场景中的各类终端进行能 力整合,可以实现不同的终端设备之间的快速连接、能力互助、 资源共享,匹配合适的设备、提供流畅的全场景体验。

对应用开发者而言,HarmonyOS 采用了多种分布式技术,使得应 用程序的开发实现与不同终端设备的形态差异无关。这能够让开 发者聚焦上层业务逻辑,更加便捷、高效地开发应用。

对设备开发者而言,HarmonyOS 采用了组件化的设计方案,可以 根据设备的资源能力和业务特征进行灵活裁剪,满足不同形态的 终端设备对于操作系统的要求。

在 GMS(谷歌应用服务)被谷歌“断供”后,华为转向研发和使用 自己的 HMS。华为 HMS 对标谷歌 GMS,为华为设备生态系统提供 的一套应用程序和服务,包含直接面向消费者的 HMS

未来 HMS 将协助鸿蒙构建全球内容生态。与安卓系统类似,第三方 应用开发时可以直接基于鸿蒙 OS 的 API 而不完全依赖于 HMS,同 时,HMS 也支持安卓操作系统,并且开发者未来从安卓系统向鸿蒙 系统切换时,无需对所开发应用进行修改。

3.5 为何升级鸿蒙的华为手机完全兼容此前的安卓应用生态

2007 年谷歌公司正式展示 Android 操作系统,宣布建立一个全球性的 联盟组织,该组织由 34 家手机制造商、软件开发商、电信运营商以 及芯片制造商共同组成。联盟将支持谷歌发布的手机操作系统以及应 用软件,将共同开发 Android 系统的开放源代码。

AOSP:安卓开源项目,所有手机厂商可以免费获得 Android 开源代 码。

代码开发,因此 升级鸿蒙的华为手机完全兼容此前的安卓应用生态。 此外,方舟编译器是华为为支持多种编程语言、多种芯片平台的联合 编译、运行而设计的统一编程平台,是鸿蒙生态建设的重要支撑。方 舟编译器在软件史上首次将 Java/C/C++等混合代码一次编译成机器 码直接在手机上运行,彻底告别 Java 的 JNI 额外开销,也彻底告别了 虚拟机 GC 内存回收带来的应用进程掉线,既实现了安卓 APP 无缝迁 移到鸿蒙系统,也让操作流畅度大幅提升。

4 鸿蒙成功的关键:生态

对于一个操作系统,生态就是它的生命。通常情况下,操作系统的竞 争同步发生在智能硬件的普及化阶段,比如 PC 互联网时代 Windows 造就了微软,移动互联网时代 Android 成就了谷歌。16%是华为内部 通过技术评估、市场调研得出的一个市场份额参照,只有 HarmonyOS 在智能手机市场的安装占比超过 16%,鸿蒙才有可能被市场承认成为 通用操作系统。

所做的第一个发行版。同时,华为开放了一整套的鸿蒙开发平台与工具链生态,欢迎其 他厂商一起基于 OpenHarmony 的开源社区,去开发各个领域的应用 和产品。

华为通过开放源代码、SDK、开发板/模组、HUAWEI DevEco 等平台 和工具链,使能南向的硬件生产厂商;通过为开发者提供鸿蒙编程框 架、APIs、DevEco、方舟编译器等一系列平台及工具链,使能北向的 应用开发者。

4.2 开放且持续扩大的鸿蒙生态圈

鸿蒙操作系统有望在物联网时代加速国产化方案整合与整体落地进 度,国产软硬件自主可控动能加速释放,华为生态合作伙伴也有望在 鸿蒙生态体系的快速扩张路径中持续受益。 从 2020 年 9 月 10 号鸿蒙系统开放给鸿蒙生态合作伙伴以来,鸿蒙生 态已经吸引了美的、九阳、等家电设备厂商以及、 等模组厂商、解决方案公司加入到鸿蒙生态阵营。未来,随 着鸿蒙的进一步开放和发展,相信会有更多领域更多应用场景的公司 加入鸿蒙生态。

6 月 2 日,华为正式发布鸿蒙手机系统,该系统正式搭载到智能手机。 同时,据华为消费者业务 CEO 与 HarmonyOS 的进 一步统一,有望进一步提升鸿蒙接入设备的数量。

5 鸿蒙生态的商业模式

5.1 华为、产品合作伙伴、方案公司三方共赢

华为从做通讯和硬件的公司,到推出鸿蒙 OS,和苹果软硬件一体化 的模式比较像,苹果靠高毛利的硬件赚钱,但华为高毛利的手机由于 芯片问题快速下滑,必须采用新的模式。

鸿蒙操作系统免费,但鸿蒙可以通过渠道来赚钱。从华为的角度来说, 虽然现在手机、笔记本等由于缺芯片,销量快速下滑,但华为这么多 年建立的线上线下渠道,短期内是可以变现的一种方式。华为的合作 伙伴公司的产品想进华为的渠道,第一个需要渠道认证、渠道准入; 合作伙伴的产品想进入华为商城的普选或者优选,有不同的认证标 准。合作伙伴的产品进入华为商城可以提高产品销量,华为也可以对 认证和渠道收费。

这里还有方案公司的商业机会,类似润和股份、中软国际、等公司。例如 A 是产品公司,B 是方案公司,A 的产品想进华为渠道 有一定的门槛,一是 A 想用鸿蒙系统但不知道怎么用,二是不知道 准入问题怎么解决。那么 B 就可以提供带鸿蒙的一套模组的解决方 案,使能 A 快速在鸿蒙系统上运行,并且通过一系列的 XTS 认证和 测试等。对 A 来说虽然提高了一定成本,但是通过合作顺利进入华为 大的生态体系,进入华为渠道以后可能带来更高的销量,可以继承华 为手机零售的成功经验。所以商业模式对产品公司、方案公司、华为 三方都是成立的,商业正循环就可以运行起来。

总的来说,在鸿蒙生态的跑马圈地过程中,华为技术赋能伙伴,认证 后通过华为渠道卖货(认证和渠道收费),达到双赢的目标。鸿蒙的 诞生使消费者有了超级终端体验:极简连接、万能卡片、极简交互、 硬件互助,实现 one as all, all as one,即一生万物,万物归一。横向: 从扩展到全场景,覆盖 7 大场景核心智能设备,建立全场景 鸿蒙精品设备圈;纵向:从品牌厂家扩展到全产业链,联合芯片、模 组、IDH、品牌厂家、服务商,快速打造鸿蒙生态产业链。

华为始终坚持平台+生态的战略,鸿蒙诞生加大在生态领域的投入, 和小米(自有产品)+涂鸦(中小企业服务)的战略不同,帮助伙伴 做好产品,卖好产品、运营好产品,低成本让大家接入鸿蒙智联,通 过华为商城卖货。

做好产品:鸿蒙易用、好用的特点,让生态伙伴快速低成本接入鸿蒙 网络。华为提供芯片、模组、OS 和上面软件的服务包套餐,预先集 成了全栈的解决方案,支撑生态伙伴的快速开发认证。

卖好产品:华为全渠道、全场景帮助伙伴卖好产品,网上包括华为商 城(3 亿会员)、天猫(2900 万粉丝)和京东旗舰店(5100 万粉丝), 线下 60000 多华为自有零售/服务渠道,还有 15000 多第三方垂直领域 专业/行业渠道。

运营好产品:用 10 亿设备圈,超过 10 万的原子化服务,帮助伙伴提 升产品活跃度,通过开放运营平台,帮助生态品牌持续曝光。

5.2 发现智能化的痛点,解决问题

据三方厂商统计,当前市面上出售的智能设备平均入网率仅 为 15%,平均 APP 安装率仅为 10%,智能特性使用率甚至只有 5%, 存在连不上、用不了、留不住等问题,这意味着消费者把智能产品买 回去后,95%的人还当传统设备在使用,存在联网体验差、学习成本 高、服务不持续、家居生态单一等很多问题。而经过 HarmonyOS Connect 认证的生态硬件产品则能够很好地解决这些痛点,让消费者 真正享受到智能设备所带来的便利。

生态产品将在系统层面融为一 体,成为超级终端的一部分,通过极简配网(入网率提升 2-4 倍)、万 能卡片(服务免安装、精准直达)、极简交互(更多入口、跨端联动)、 硬件互助等能力,轻松唤醒设备智能,有效解决了设备智能特性使用 率低等难题,实现快速、低成本连接设备,给消费者带来简捷,流畅, 连续,安全可靠的全场景交互体验。

过去是单设备非智能(按键/面板操控设备功能),现在是单设备智能 化(APP 控制功能+服务),华为鸿蒙实现多设备智慧体+跨设备服务, 用场景化超级终端,让设备更好用。以美的、九阳、海尔等合作伙伴 打造的 HarmonyOS Connect 智能硬件产品为例,展示出它们所带给消 费者的全新体验,厨房的改变让厨电触手可及,可以一碰连接、一碰 操作,精准控制设备,智能提醒。与手机只需轻轻一碰,美 的蒸烤箱就可以选择菜谱一键烹饪,九阳豆浆机根据健康数据推荐饮 品,让厨电设备变成私人营养师。

5.3 高频刚需的设备和服务,场景化联动提升产品的活跃度

1+8+N 全场景终端设备:“1”代表智能手机,每个人现在都离不开你 的手机,手机是分钟级交互,属于高频刚需;“8”代表 PC、平板、 手表、智慧屏、AI 音箱、耳机、AR/VR 眼镜、车机,一个小时的交 互的设备,属于中频设备,“N”代表 loT 生态产品,天级的交互设备, 低频的交互设备,每天会操作一两次这样的一个智能家具。

因为华为在手机-分钟级设备和 8 大-小时设备上,有非常多的存量, 华为将用高频刚需的设备来带动低频设备,提升所有安装设备的使用 激活。例如用户拿手机碰家电,弹出一张家电相关的卡片,实际上是 拿一个分钟级的设备去使用一个天级设备,高频设备带动低频设备, 这是华为给伙伴提供的一个商业价值。华为还有高频的一些内容和服 务的生态,会有 10 万种以上的原子化服务提供给伙伴,核心在于高 频设备拉低频设备,高频服务赋能所有的服务生态。

:跑步机秒变AI 教练

华为在手机、手环等健康领域有很多积累,结合鸿蒙能力加持,助力 的跑步机全智能,秒变 AI 教练,具有 AI 数据分析、专属语 音教练,开启科学运动旅程。一碰进入个人运动空间,懂你的身体状 态、多模式跑步场景、多设备联动,也可以安全退出,个人数据随人 走,跑步机不留痕迹。

教练。跑步前,基于鸿蒙极简连接能力,实现 快速登录,跑步机秒切个人运动空间,并根据运动能力、健康状态, 推荐适合的运动方案;跑步中,基于鸿蒙分布式能力实现多设备联动 获得更多维度的运动指标,智能监测和分析个人运动状态,提供科学 的实时语音指导;跑步后,科学评估运动能力和状态。更为方便的是, 手机视频还可以一键流转到跑步机,运动追剧两不误。

:XC3 成为华为鸿蒙生态的首辆电动车

新日电动车成为电动车行业第一家且唯一一家入驻华为鸿蒙生态的 电动两轮出行产品。新日与华为合作的重要意义在于,从简单功能到 骑行全场景的智慧出行,每一部华为手机都是打开新日电动车的“钥 匙”,从而让华为的智能工具到新日电动车都成为构建万物互联的载 体。新日与华为的合作对于整个电动车行业也具有划时代的意义,为 智能电动车可以实现的全场景的智慧化提供了范本。

通过华为智慧生活 APP 开启电源、上锁、解锁,甚至可以实现无钥匙 出行;在 APP 上查询电量和剩余里程,续航焦虑得到了解决;通过 APP 进行车辆健康诊断,电池、控制器、电机、转把的状态随时可以 查看,有问题及时发现,为出行安全增加一份保障。

华为这次将鸿蒙生态系统升级释放出了一个积极的信号,那就是未来 华为会和品牌方一道,为万物互联提供更好的解决方案。未来家电、出 行工具、手机等将是同处于一个鸿蒙生态系统下的有机个体。在下班 路上,可以通过向智能头盔发出指令,就可以开启家中的空调、洗衣机等,生活将带来翻天覆地的变化。

5.5 鸿蒙生态与小米的不同点

和小米自己做产品支持和通讯模组不同,华为授权润和、中软国际、 等做服务和通讯模组,并且华为对生态伙伴的收费也比较 低,加上华为的高端品牌力,对伙伴吸引力很大。

华为习惯后发制人,虽然小米生态发展的比较早,但小米的生态公司 毛利比较低,而且小米生态的开放度相对没有鸿蒙高。小米生态产品 都有一个网关的概念,设备需要设置相同的路由器和网络,产品通过 网关来交互。而鸿蒙设备是近场通讯,通过软总线,虽然设备间物理 是分离的,但鸿蒙设备间可以自己通讯,不需要网关去绕一层,并且 通讯器材本身就是华为的强项。对鸿蒙产品来说它的硬件形态只有一 个超级终端,超级终端里面有若干个硬件载体,然后组成一个系统。

6 鸿蒙生态上市公司

公司 2006 年成立,2012 年在深交所上市(股票代码:300339)。经过 十多年的发展,公司已经建立了完整的“预研-设计-开发-测试-交付运维”的一站式综合服务体系,是中国领先的产品与解决方案提供商、 平台运营商。 公司主营业务横跨、物联网两大领域,以国产化、数字化为 核心,致力于提供从芯片、硬件、底层软件到应用平台的综合解决方案与优质科技服务。

6.1.1 战略重心调整,物联网业务突飞猛进

公司营收自上市以来稳定增长,至 2020 年公司总营收超过 24 亿,其 中主要贡献来源于、智能物联和智慧能源信息化三方面业 务。2018 年前,润和发展重心和主要营收来源于金融科技业务,营收占比 超过 70%;2018 年润和战略规划调整,大力发展物联网相关业务,到 2020 年公司营收近 50%来自于金融科技业务,另外近 50%来源于物 联网下的智能物联和智慧能源信息化业务。 在过去三年公司毛利一直处于压力之下,主要由于金融科技业务收入 未达预期,员工薪酬成本总额大幅增加,公司向外外包减少。

公司 HiHope 芯片全栈解决方案平台是涵盖芯片设计服务、硬件开发 生产、硬件测试认证、板级支持软件、 芯片调测软件、应用解决方 案原型等的一站式芯片解决方案平台,领域涉及智慧联接、智慧视觉、 智慧工业、智慧媒体、智能计算。HiHope 芯片全栈解决方案平台沉 淀了包括华为、海思、紫光展锐、阿里平头哥、等多个重量 级合作伙伴,合作的国内外行业组织包括 Linaro、HDMI、开放原子 开源基金会、软件绿色联盟等,是 OpenHarmony 发起单位之一、华 为 HarmonyOS 生态共建者、 海思芯片及 IoT 战略合作伙伴等。

公司提供多芯片平台的适配和使能,提供搭载鸿蒙的模块以及板卡, 提供鸿蒙针对、智能支付终端、智能车载等不同场景的发行 版。公司提供了官方首批支持 Harmony OS

6.2 中国软件国际: 全栈式使能鸿蒙智联生态

中软国际成立于 2000 年,2008 年香港主板上市,是国内首家纯软件 服务收入突破百亿的企业。目前公司业务主要是四方面:第一增长曲线的基石业务;第二增长曲线的云智能业务;第三增长曲线的鸿蒙生态业务;推动解放号作为软件产业互联网平台全面升级。

6.2.1 搭建鸿蒙万物互联桥梁,一站式使能鸿蒙生态

中软国际与华为多领域的合作由于已久,深度参与华为生态建设。作 为第一家与华为签署“HUAWEI HiLink 生态方案服务合作协议”的合 作伙伴,中软国际已助力众多厂商接入 HUAWEI HiLink 生态,涵盖 、运动健康等领域,并同步储备硬件能力,加快厂商批量接 入。中软国际也荣获 2020 年度 HUAWEI HiLink 生态使能服务“卓越 合作伙伴”大奖。

未来,中软国际将为鸿蒙生态提供一站式使能服务。包括鸿蒙 Harmony Connect 接入服务、认证服务、数据运营、智能化解决方案。

认证服务:提供各项国际化标准认证服务加速认证完成,赢取市场信 任;

数据运营:数据中心、运营中心、品牌营销多维度管理,赋能产品提 升竞争力;

智能化解决方案:全品类、行业解决方案,助力极速完成智能化演进。

是中国领先的软件与信息技术服务商,致力于成为具有全球 影响力的数字技术服务领导企业,企业数字化转型可信赖合作伙伴。

拥有深厚的行业积累,领先和全面的技术实力,长期为客户 提供端到端的数字化解决方与服务,包括数字化转型咨询、数字化解 决方案设计与实施、云与 IT 基础设施建设与运维、软件开发与测试 服务和数字化运营服务等。以人工智能、区块链等 10 大类 70+项技术 作为基础行发展战略投入方向,推动创新链、产业链和市场需求有机 衔接,应对数字化转型需求。

服务于 10 余个行业,包括通讯设备、互联网服务、高 科技与智能制造、金融等,拥有 200 多个行业解决方案。公司的主要 业务可划分为软件与数字技术服务及数字化运营服务,软件与数字技 术服务占其营收的近 94%,其中软件与数字技术服务又分为通用技术 服务、数字技术服务及咨询与解决方案。公司的软件与数字技术服务 是根据客户需求,为其提供针对软件、信息系统、电子电路产品等的 设计、开发、测试、运维、数据处理等全方位服务。通过提供全栈数 字化服务,致力于成为是能者和企业数字转型可信赖合作伙 伴。

能够为各个客户提供产品全生命周期的 HarmonyOS Connect 定制化服务,既可以端到端完成客户产品的 HarmonyOS 接入,也可 以为客户对中间某个环节提供高质高效的 HarmonyOS 接入服务。

模组,以完成为客户多环节定制化服务中硬 件研发的重要一环。通过其长期积累的技术与能力,做到高校交付, 帮助客户短时间接入产品。携手华为,共建鸿蒙生态。目前公司已与 50 多家厂商和软通构筑长期稳定、互利共赢的合作伙 伴关系。已接入产品包括智能枕头、智能跳绳、智能马桶、智能护膝 等。

1. 鸿蒙 OS 系统接入设备量不及预期,导致生态建设滞后,产业链 厂商订单不足。

2. 中美关系持续恶化进入新一轮更高规格的制裁,影响华为正常的 企业经营及鸿蒙 OS 的持续推广。

3. 因苹果、安卓等众多竞争对手切入,加速市场竞争,竞争格局恶 化,导致鸿蒙 OS 渗透率不及预期。

(本文仅供参考,不代表我们的任何投资建议。如需使用相关信息,请参阅报告原文。)

}

作者:碎碎思 来源:

有一个有趣的现象,众多数字设计特别是与FPGA设计相关的教科书都特别强调整个设计最好采用唯一的时钟域。换句话说,只有一个独立的网络可以驱动一个设计中所有触发器的时钟端口。虽然这样可以简化时序分析以及减少很多与多时钟域有关的问题,但是由于FPGA外各种系统限制,只使用一个时钟常常又不现实。FPGA时常需要在两个不同时钟频率系统之间交换数据,在系统之间通过多I/O接口接收和发送数据,处理异步信号,以及为带门控时钟的低功耗ASIC进行原型验证。本章讨论一下在FPGA设计中多时钟域和异步信号处理有关的问题和解决方案,并提供实践指导。

这里以及后面章节提到的时钟域,是指一组逻辑,这组逻辑中的所有同步单元(触发器、同步RAM块以及流水乘法器等)都使用同一个网络作为时钟。假如设计中所有的触发器都使用一个全局网络,比如FPGA的主时钟输入,那么我们说这个设计只有一个时钟域。假如设计有两个输入时钟,如图1所示,一个时钟给接口1使用,另一给接口2使用,那么我们说这个设计中有两个时钟域。

平时我们在设计中遇到的门控时钟、衍生时钟以及事件驱动的触发器都可归为时钟域类别。如图2所示,通过一个简单门控时钟创建了一个新的时钟域。我们知道,这类时钟控制在FPGA设计中并不被推崇(可以使用时钟使能替代时钟门控),然而它却非常有利于我们理解时钟域这一概念。

本章我们将着重详细讨论以下主题:

  • 两个不同时钟域之间传输信号。
  • 亚稳态的产生以及对设计的可靠性的影响
  • 通过相位控制避免亚稳态
  • 在时钟域之间传输单个信号,将信号打两拍
  • 使用FIFO在时钟域之间传输多位数据
  • 使用分区同步器模块提高设计的组织架构
  • 处理ASIC验证原型里的门控时钟
  • 图2:通过门控时钟创建的时钟域

    设计中包含多时钟域,首先要解决的是在不同时钟域之间传输信号的问题。信号跨时钟域传输将会是一个大问题,原因如下:

    1、 信号跨时钟域传输产生的故障总是不太容易复现。设计中如果存在两个异步时钟域,故障往往与这两个时钟沿的相对时序有关。来自片外时钟源的时钟通常与器件实际功能并无任何关联。

    2、 根据技术的不同,问题也不一样。(尽管由于其他因素的影响,这种情况并不总是成立)我们常常会发现,如果约束较小的建立和保持时间,从统计上来说高速设计技术比低速设计技术更不容易产生故障。同时,其它因素,比如同步器件中设计实现对输出的缓冲,也会对一个可能的故障产生显著影响。

    3、 EDA工具一般不会探测和标注这类问题,静态时序分析工具是基于独立的时钟区域来进行时序分析,而且只有在特定的方式下根据指定的要求才能进行跨时钟域的时序分析。

    4、 通常来说,如果没有很好地理解,跨时钟域故障难以探测且难以调试。所以所有跨时钟域接口都必须要在任何功能实现之前被很好地定义和处理。

    让我们首先来看看在不同时钟域之间传输信号到底会产生什么错误。考虑图3所示的情况,一个信号在两个时钟域之间传播。

    如图4所示,低速时钟的周期是高速时钟周期的两倍。低速时钟上升沿与高速时钟上升沿之间的间隔为常量,而且总是等于dC。由于这两个时钟的这种相位匹配关系,dC总是保持不变(假定频率没有漂移),而且在这个例子中,dC总是大于逻辑延时与高速时钟驱动的触发器建立时间之和。

    图3:时钟域之间的简单信号传输

    图4:两个时钟域之间的时序关系

    当这些时钟一启动,它们之间存在一个固定的相位关系,如此可以避免任何建立时间和保持时间违规。只要时钟没有漂移,就没有任何时序违规出现,并且器件会如预想那样工作。现在我们再考虑另外一种情况,同样的时钟上电后的相位关系如图5所示。

    图5:会造成时序违规的时钟相位关系

    图5中两个时钟之间的这种相位关系就会造成时序问题。这种情况会在任意频率的两个时钟域之间。然而,如果时钟的频率匹配不对,这种时序问题在这种情况下也不会发生。

    总结来说,时钟同步问题在FPGA设计中通常是一种不可复现的问题,而且会对设计的可靠性带来严重后果。后面我们会讨论解决这类问题的方案,在此之前,我们必须要讨论当建立和保持时间违规时到底会发生什么。下一小节就是关于这个主题。

    触发器的建立时间和保持时间在时钟上升沿左右定义了一个时间窗口,如果触发器的数据输入端口上数据在这个时间窗口内发生变化(或者数据更新),那么就会产生时序违规。存在这个时序违规是因为建立时间要求和保持时间要求被违反了,此时触发器内部的一个节点(一个内部节点或者要输出到外部节点)可能会在一个电压范围内浮动,无法稳定在逻辑0或者逻辑1状态。换句话说,如果数据在上述窗口中被采集,触发器中的晶体管不能可靠地设置为逻辑0或者逻辑1对应的电平上。所以此时的晶体管并未处于饱和区对应的高或者低电平,而是在稳定到一个确定电平之前,徘徊在一个中间电平状态(这个中间电平或许是一个正确值,也许不是)。如图6所示,这就是所谓的亚稳态。

    图6:时序违规导致亚稳态

    如图6的波形所示,信号的跳变发生在建立和保持边界组成的时间窗口内,这意味着输出不会是逻辑0或逻辑1对应的确定电平,而是它们之间的一个中间电平。如果触发器包含有一个输出缓冲,那么亚稳态本身就可以称为随着内部信号的逐渐稳定而在输出上表现的杂散过渡。输出保持亚稳态的时间是随机的,甚至可能在整个时钟周期内都保持亚稳态。那么,如果这个亚稳态值输入到组合逻辑,根据逻辑门电路的切换门槛,错误的操作就可以发生。从时序收敛的角度来说,两个触发器之间的组合逻辑延时都要求要小于最小的时钟周期,但是这种亚稳态信号保持亚稳态的时间,本身就是变相地增加了逻辑延时。很显然,一个亚稳态信号会给设计带来致命的功能故障,而且该信号也将无法在各个时钟沿上采集到一致的结果。

    事实上需要注意的是,在FPGA设计流程中想通过仿真来确定亚稳态对设计的危害是非常困难的。纯数字的仿真器并不能检查到建立和保持违规,从而在违规发生时,仿真出一个逻辑“X”(未知)值。而普通的RTL仿真,并不会出现建立和保持违规,所以也就不会有信号出现亚稳态状态。尽管门级仿真的时候会检查建立和保持是否违规,但是仿真由两个异步信号对齐而导致一个同步故障依然是一件十分困难的事情。尤其困难的是,设计或者验证工程师并不是在设计伊始即查找问题。那么,理解如何保持设计的可靠性以及如何避免需要通过仿真来揭露设计的同步问题,就显得十分重要了。解决亚稳态的方法有很多,后面我们将逐一进行讨论。

    1.2 解决亚稳态方案1:相位控制

    考虑这样一个设计,两个时钟域的周期不同,而且相位关系任意。如果至少有一个时钟由FPGA内部的PLL或者DLL控制,而且在PLL或者DLL的精度范围内,其中一个时钟的周期是另外一个时钟周期的数倍。那么如图7所示,通过相位对齐可以避免实现违规。

    考虑这样一个例子,一个信号从低速时钟域传递进入另一个时钟域,而此时钟域的周期是低速时钟域的一半。根据前面的分析,如果没有任何相位关系的保证,那么时序违规就有可能发生。然后,通过使用DLL由低速时钟派生这个高速时钟,那么相位对齐就可以达成。

    图7中,DLL调整高速时钟(采集)的相位来对齐低速时钟(发送)。数据在两个时钟域之间传递的时间是dC,该传递时间总是处于其最大可能值。本例中,只要从低速触发器到高速触发器的传播延时小于高速时钟周期,那么就不会有建立时间违规发生。如果因为时钟歪斜不够小而导致保持时间要求无法满足,那么可以通过配置实用高速时钟的下降沿来采集信号,当然前提是有足够的时序余量能确保建立时间要求得到满足。

    图7:使用DLL对齐相位

    总结来说,相位控制技术可以在一个时钟频率是另外一个时钟的数倍且其中一个时钟可以由FPGA内部PLL或者DLL控制时使用。

    在很多例子中,设计控制时钟域之间的相位关系是很奢侈的。尤其是时序要求由FPG**外的芯片施加,或者时钟域之间没有任何确定相位关系的时候。举例来说,如果FPGA在两个系统之间提供了一个接口,而这两个系统施加在芯片输入输出延时上的时序要求非常紧张,调整任何这两个系统的时钟相位是不可能的。类似这种例子在实践中会经常遇到,所以需要使用新的方法来解决,下一节将讨论这种新的方法。

    1.3 解决亚稳态方案2:打两拍处理,即寄存两拍

    跨越两个异步时钟域传输单比特信号时,可以使用打两拍技术。根据上一节的讨论,建立或保持时间违规会导致一个触发器内节点上电平徘徊在一个中间状态,从而产生亚稳态问题,而且信号从这种中间状态到一个稳定状态需要时间,此时间的长度未知。这个未知的时间会被加入到时钟到输出的时间(Tco)里(影响随后路径上的延时),且会在下一级导致一个时序违规。如果该信号输入到一个控制分支或者一个判决树,那将是非常危险的。不幸的是,没有很好的办法来预测这种亚稳态将会持续多长时间,也没有很好的办法将这些信息反标注到时序分析工具以及优化工具。假定两个时钟域之间完全异步(即无法实现相位控制),那么尽可能避免亚稳态的一个最简单办法就是使用双触发。在其它也许教科书中也称这种方法为同步位、两级触发器或两级同步器。

    图8所示的配置中,同步器电路(其输入为Din)中的第一拍后也许会产生亚稳态,但是信号有机会在其被第二级锁存以及被其它逻辑看到之前稳定下来,如图9所示。

    图9中,Dsync是同步器中第一个触发器的输出,而Dout是第二个触发器的输出。Dout本质上是等到同步后的信号一旦稳定下来后将其往下传,并且确保其它电路不会收到亚稳态信号。同步器两级触发器之间不要添加任何逻辑,这样可以使得信号获得尽可能长的时间来回到稳定状态。所以总结来说,打两拍同步器在单比特信号跨异步时钟传输时,用来将该单比特信号重新同步到异步时钟域。

    理论上来说,第一个触发器的输出应该一直保持不确定的亚稳态,但是在现实中它会受到实际系统一系列因素影响后稳定下来。打个比方,想象一下一个皮球稳定地停住在一个山尖上,从任何方向上轻推一下球,它都会由相反的方向从山上滚落。同样,处于亚稳态的一个逻辑门,由发热、辐射等产生的随机波动都会促使该亚稳态回到逻辑0或者逻辑1对应的稳态。

    使用打两拍技术采样一个异步信号时,无法完全预知我们想要的信号跳变,将在当前时钟发生还是下一个时钟发生。当信号属于一个数据总线中的一部分(有些数据位比其它比特晚一个时钟周期跳变)时,或者关键数据必须要精确到单个时钟周期内到达时,这种打两拍技术是没有帮助的。不过,对于控制信号来说,如果它们可以忍受正负一个或更多个时钟周期的变化,这种技术还是非常有用的。

    举例来说,一个外部事件控制一个比特来触发FPGA内部动作,这个触发动作发生的频率可以非常的低,比如两个事件之间的间隔可以达到微秒甚至毫秒级。在这个例子中,一些额外的数纳秒的延时并不会影响该事件的行为。如果由外部事件驱动的改比特输入到一个状态机的控制结构中,通过同步器打两拍处理,那么想要的信号变化只是被延迟了一个时钟周期。然而,如果没有进行打两拍处理,那么判决逻辑也许会从该异步信号的亚稳态状态解码出不同状态跳转信息,并使得状态机同时跳转到不同的分支。

    除了纯数字系统外,还有一种混合信号系统,这种系统会通常会产生异步反馈信号到FPGA,如图10所示。

    图10:重新同步模拟反馈

    反馈信号会产生时序违规,而且fbr1在时钟沿后一个不确定的时间内处于亚稳态。那么,其它逻辑只可以使用的信号fbr2。

    使用打两拍同步处理技术时指定时序约束是非常重要的,需要施加的约束是将位于第一个和第二个寄存器时钟域之间的信号路径指定为假路径,即让时序分析器部分此路径。因为打两拍同步器结构用于重新同步信号,在这两个时钟域之间并没有需要分析的同步路径。此外,如前所述这两个触发器之间的时序要尽可能的小,这样可以减小亚稳态被传播到第二级触发器的可能性。

    1.4 解决亚稳态方案3:使用FIFO结构

    跨时钟域传输数据用得最多的方法就是使用先入先出(即FIFO)结构。FIFO可以用于在两个异步时钟域之间传输多个比特信号。我们通常看到的FIFO应用包括在两个标准总线之间传输数据,以及从可突发访问的存储器中读出数据或者对其写入数据。例如,如图11所示,显示的是一个可突发访问存储器与一个PCI总线之间的接口。

    在很多不同的应用中,FIFO都是一种非常有用的数据结构,不过这里我们仅仅关注其处理跨时钟域突发数据的能力。

    FIFO非常类似于在超市里的结账通道,每个客户到达结账台的时间多少有点随机性,结账速度在一定意义上说是匀速的。有时候结账客户可能会很少,而其他某些时候又会突发很多客户需要结账,收款员不可能立刻为每个客户服务,所以需要排队。抽象地来说,我们称这种排成一队的数据为一个序列。随后,收款员会以或多或少平均的速度为每一个顾客服务,并不会理会队列的长度。假如需要结账的顾客涌入收银台的速度超过了收款员的服务速度,那么这种收款结构就无法支撑了。那么此时,就需要采取措施,要么加快收款员的服务速率,要么减少新增顾客数。

    同样的道理也存在于数据传输中,数据可能到达某个时钟域的间隔是完全随机的,有时候或许会面临一个很大突发数据块。这种情况下,处在另一个时钟域的接收设备只能以指定的速率来处理数据。如图12所示,一个FIFO被用于缓存数据,这样在设备中就形成了一个数据序列。

    通过使用异步FIFO,数据发送端可以以随意的间隔发送数据,而接收端也可以以其固有的带宽从数据序列里取出数据并进行处理。由于任何由FIFO实现的数据序列的长度都不能无限制,所以需要一些控制来防止FIFO溢出。这时候,有两种选项可以采用:

  • 事先定义好的发送速率(可突发或不可突发),最小接收速率以及对应最大的序列尺寸。
  • 注意,发送设备的时钟频率没有必要高于接收端设备,否则容易造成溢出。以较慢的频率将数据送入FIFO,那么数据写入FIFO的时钟周期数要少于接收端将要处理数据的时钟周期数。那么,如果不采取握手控制,就必须要理解以上描述会产生溢出的最坏的情况。

    在任何一段时间内,假设数据发送写FIFO的速率大于接收处理数据的速率,那么很轻易地使系统无法维持。因为没有任何存储设备可以存得下无限的数据,这种问题需要在系统结构层级才能解决。通常来说,突发发送一般是以小周期性或非周期性发生。所以FIFO的最大尺寸要大于等于(具体还要根据数据接收器的属性)突发的尺寸。

    在很多例子中,不管是突发尺寸还是数据到达的分配都无法很好地定义。这种时候,就有必要使用握手控制来防止FIFO产生数据溢出。如图13所示,这种握手控制通常由一些标志信号来实现。这些标志信号,一个是发送侧的满标志,用于提示FIFO没有多余空间存储数据了,另一个是而空标志,用于提示接收侧,FIFO中没有数据需要处理了。管理这些握手信号可能还需要一个状态机,正如图13所示。

    图13:FIFO的握手控制

    FIFO在FPGA内一般是通过封装一个双口RAM来实现。表面上看微不足道的标志信号如空和满指示等,实际上是实现起来反而比较困难。原因就在于输入控制常常需要依据输出来产生,同样的输出控制也常常需要依据输入来产生。例如,驱动输入的逻辑必须要知道FIFO是否已满,而这只能通过获取从输出端读出的数据数量才能得知。同样的道理,在输出侧从FIFO读数据的逻辑必须要了解FIFO中是否还有数据(即FIFO是否已空),而这只能通过输入端口的写指针才能判决。

    这里我们探讨使用FIFO在两个异步时钟域之间传输数据,不过同样会面临实现FIFO本身时遇到的握手标志问题。为了在两个时钟域之间传递必要的信号,我们必须重回上一节讨论到的打两拍技术。下面我们以图14所示的简单异步FIFO框图为例进行阐述。

    图14:异步FIFO简单框图

    图14中,在产生空和满信号时,写地址和读地址都必须是异步传递到对方时钟域中。这样在重新同步多比特地址总线时,问题就来了,即根据各个比特不同的走线,总线中某些比特可能会比其它比特晚一个时钟周期。换句话说,由于两个时钟域异步的自然属性,使得地址总线有些比特在一个时钟沿上被采集,而另一些比特却在下一个时钟沿上被采集,当然这取决于数据是否在第一个触发器的时钟沿到达之前提前足够长时间有效。如果上述情况发生,那么会给系统带来严重后果,因为二进制地址中有些位变化有些位却没有,因此接收逻辑将会得到一个完全无效的地址,这个地址既不是当前地址也不是上一个地址。

    这个问题可以通过将二进制地址转换为格雷码来解决。格雷码是一种非常特殊的计数器,两个相邻地址中只有一个比特是不同的。所以当地址改变时,只需要改变地址中的一个比特即可,这样就可以避免上面提到的问题。如果发生变化的那个比特并没有被下一个时钟正确采集,地址线上会“同步地”保留旧的地址值。那么,任何不正确的地址(即既不是当前地址也不是旧地址)操作都被消除了。所以总结来说,格雷码常用来在异步时钟域之间传递多比特计数值,且多用于FIFO内。

    需要额外注意的一点是,由于只有读写地址是需要在异步时钟域之间传递,所以地址就有可能比预想的晚一个时钟周期,同时意味着空或者满标志置位晚一个时钟周期,但是这并不表示错误导致了数据溢出状况。如果这种情况在传递地址到读时钟域时,读逻辑将简单地认为数据没有写入,且将认为FIFO已空尽管此时FIFO已经被写入一个数据。这只会对总的吞吐率有一些小影响,但是不会导致下溢(即读已空的FIFO)状况发生。同样地,当地址被传递到写时钟域时,如果读地址被延时了,那么写逻辑会认为FIFO里没有多余空间,尽管此时FIFO还未满。这同样只会对总的数据吞吐率有些微小影响,却不会造成上溢(写已满的FIFO)发生。

    FIFO是一种足够通用的模块,大部分FPGA供应商都提供了工具,可以让客户根据自己的要求来自动产生软核。这些用户FIFO可以像其它IP模块那样由用户手动地在设计中例化。那么,在一个FPGA设计中使用自己的FIFO时,上述讨论的问题很可能将不必由设计自己来解决。当然,同样的问题也经常在异步时钟域之间传递数据的时候发生,所以理解这类设计实践对于一个高级FPGA设计者来说非常重要。

    1.5 设计分区同步器模块

    在顶层为设计划分好设计分区是一个好的设计实践行为,这样任何功能模块外面都包含一个独立的同步器模块。这样有利于在划分模块的基础上实现所谓的理想时钟域情况(即整个设计模块只有一个时钟),如图15所示。

    图15:设计分区同步器模块

    对设计进行分区有很多理由。首先,对每个独立的功能模块进行时序分析变得简易,因为模块都是完全的同步设计。其次,整个同步模块中的时序例外也很容易得到定义。再次,底层模块的同步器加时序例外在代入到设计顶层时,大大降低了由于人为失误造成的疏漏。所以,同步寄存器应该在功能模块外单独分区。还有很多类似的设计实践在使用FPGA作为ASIC的设计原型时得到应用,下一节我们将再进行详细地讨论。

    二、ASIC原型设计中的门控时钟

    ASIC设计一般对功耗非常敏感,同时ASIC的时钟树设计又非常灵活,所以会在整个设计中经常使用门控时钟在逻辑不需要活动的时候来去使能这些逻辑。虽然使用FPGA作为ASIC的原型可以模拟整个逻辑功能,但是二者之间的有些物理属性,如功耗方面,还是不太一样。那么,要求FPGA来模拟ASIC的整个低功耗优化是没有必要的。实际上,正是由于FPGA的粗放式的时钟资源,让其模拟这方面功能也是不太可能的。这一节我们将讨论一些解决这个问题方法,并且再讨论一些可以应用于ASIC设计的技术来使FPGA原型设计更加容易。

    如果一个ASIC设计中使用了大量的门控时钟,建议将所有这些门控操作统一放在一个专门的时钟生成模块中,并与功能模块隔离,如图16所示。

    图16:统一的时钟模块

    通过将时钟门控置于一个单一的模块,不但可以是约束处理更简单,而且当要对FPGA原型进行任何修改时也更容易。例如,如果设计者选择某次编译时删除所有门控单元,那么一个单一的模块里很容易实现。下一节我们将对此进行详细讨论。

    如果上述代码需要开放时钟门控,那么在FPGA原型设计中只需要修改宏定义即可。不足之处是,任何时候要将FPGA原型转化为ASIC设计时总是需要做出一些修改(其实就是修改宏定义)。很多设计者对此会感觉不是太舒服,因为他们认为二者使用的不是一样的RTL。一个更好的办法是使用一个自动门控删除工具来消除任何认为造成失误的可能。许多现代的综合工具通过正确的约束,现在都提供这项功能。例如,Synplify就有一个称为“Fix gated clocks”选项,就是用于自动地从时钟线上将门控操作删除,并将其移动到数据路径上。我们来看下面这个代码示例:

    在上面的代码中,系统时钟被一个使能信号门控产生一个门控时钟。这个门控时钟被用于驱动触发器oDat,而oDat用于寄存器输入iDat。如果没有启用“fixing the clock gating”选项,那么综合工具将会直接实现逻辑功能,如图17所示。

    图17的逻辑实现中,在时钟线上放置了门控操作。那么设计中现在有了两个时钟域,必须分别对它们进行约束,而且必须分别将它们布局到时钟资源。但是,如果启动了时钟门控删除,这个逻辑门就会比较容易地被移动到数据路径上,如图18所示。

    现在大部分逻辑器件里逻辑单元都提供了一个时钟使能输入,有了该使能输入就可以不使用本方案。然而,如果一个特定的技术并未提供触发器时钟使能,那么只能使用本技术来删除时钟门控,只是这样就将会在数据路径上增加延时。

  • 时钟同步问题通常是不可复现的问题,并且会给FPGA设计带来可靠性问题。
  • 亚稳态会给FPGA带来灾难性故障。
  • 相位控制技术在一个时钟频率是另外一个的数倍且其中一个时钟可以由内部PLL或者DLL控制的时候使用。
  • 打两拍技术可用于在异步时钟域之间同步单比特信号。
  • 在打两拍同步器中,时序分析应该忽略第一个触发器,同时要确保两个同步触发器之间的延时最小。
  • FIFO用于在两个异步时钟域之间传递多比特信号。
  • 格雷码用于在两个异步时钟域之间传递计数值数据,而且多用在FIFO内部。
  • 同步寄存器应该在功能模块外面独立分区。
  • 如果可能,请尽量不要使用时钟门控。若必须使用,请将所有的门控时钟放置在一个专门的时钟模块中,并与其它功能模块隔离。
}

我要回帖

更多关于 什么叫双时钟 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信