我所读过的最好的一篇分布式技术文章 学习笔记:The Log( 七 )


不管是原始数据的logs、feeds,还是事件、一行一行的数据记录,都来自应用程序的活动 。
可是,流处理还能够让我们处理来自其他feeds的数据,这些数据和原始数据,在消费者看来,并无二致,而这些派生的feeds能够包括随意程度的复杂性 。
一个流处理任务,应该是这样的:从logs读取数据 。将输出写入logs或者其他系统 。
作为输入和输出的logs,连通这些处理本身,和其他的处理过程 。构成了一个图 。
事实上,以log为核心的系统,同意你将公司或机构中的数据捕获、转换以及数据流 。看作是一系列的logs及在其上进行写入的处理过程的结合 。
一个流处理程序,事实上不必非常高大上:能够是一个处理过程或者一组处理过程,可是 。为了便于管理处理所用的代码,能够提供一些额外的基础设施和支持 。
引入logs有两个目的:
1) 保证了数据集能够支持多个订阅者模式,及有序 。
2) 能够作为应用的缓冲区 。这点非常重要,在非同步的数据处理进程中,假设上游的生产者出数据的速度更快 。消费者的速度跟不上 。这样的情况下,要么使处理进程堵塞 。要么引入缓冲区,要么丢弃数据 。
丢弃数据似乎不是个好的选择,而堵塞处理进程 。会使得全部的数据流的处理图谱中的处理进程卡住 。
而log 。是一种非常大 。特大,非常大的缓冲区 。它同意处理进程的重新启动,使得某个进程失败后,不影响流处理图谱中的其他进程 。这对于一个庞大的机构去扩展数据流是非常关键的,由于不同的团队有不同的处理任务 。显然不能由于某个任务错误发生 。整个流处理进程都被卡住 。
Storm和Samza就是这样的流处理引擎,而且都能用kafka或其他相似的系统作为它们的log系统 。
(注:Jay哥相当猛 。前有kafka,后有samza 。
)
2.10 有状态的实时处理
非常多流处理引擎是无状态的、一次一记录的形式 。但非常多用例都须要在流处理的某个大小的时间窗体内进行复杂的 , 和joins操作 。
比方 。点击流中,join用户信息 。
那么,这样的用例 。就须要状态的支持 。在处理数据的地方,须要维护某个数据的状态 。
问题在于 。怎样在处理者可能挂掉的情况下保持正确的状态?
将状态维护在内存中可能是最简单的,但抵不住crash 。
假设仅在某个时间窗体内维护状态,当挂掉或者失败发生,那么处理能够直接回退到窗体的起点来重放,可是,假设这个窗体有1小时那么长,这可能行不通 。
还有个简单的办法 。就是把状态存在某个远程的存储系统或数据库中,可是这会损失数据的局部性并产生非常多的网络间数据往返( round-trip) 。
回顾下,上文中曾提到的数据库中的表和log的对偶性 。
一个流处理组件,能够使用本地的存储或索引来维护状态:
通过记录关于本地索引的 。用于在crash后恢复状态 。这样的机制,事实上也揭示了一种一般化的 。能够存储为随意索引类型的,与输入流同一时候被切割(co-)的状态 。
当处理进程崩溃,其能够从中恢复索引,log充当了将本地状态转化为某种基于时间备份的增量记录的角色 。
这样的机制还提供了一种非常优雅的能力:处理过程本身的状态也能够作为log被记录下来,显然,其他的处理过程能够订阅这个状态 。
结合数据库中的log技术 。针对数据集成这一场景,往往能够做出非常强大的事:
将log从数据库中抽取出来,并在各种各样的流处理系统中进行索引 。那么 。与不同的事件流进行join就成为可能 。