文章目录

  • 0 前言
  • 1 发送事件流
    • 1.1 消息系统
      • 1.1.1 生产者与消费者之间的直接消息传递
      • 1.1.2 消息代理
      • 1.1.3 消息代理与数据库
      • 1.1.4 多个消费者
      • 1.1.5 确认和重新传递
    • 1.2 分区日志
      • 1.2.1 基于日志的消息存储
      • 1.2.2 对比日志和传统消息系统
      • 1.2.3 消费者偏移量
      • 1.2.4 磁盘空间使用
      • 1.2.5 当消费者跟不上生产者时
      • 1.2.6 重新处理信息
  • 2 数据库与流
    • 2.1 保持系统同步
    • 2.2 变更数据捕获
    • 2.3 事件溯源
      • 2.3.1 从事件日志导出当前状态
      • 2.3.2 命令和事件
    • 2.4 状态,流与不可变性
      • 2.4.1 不可变事件的优势
      • 2.4.2 相同的事件日志派生多个视图
      • 2.4.3 并发控制
      • 2.4.4 不变性的限制
  • 3 流处理
    • 3.1 流处理的适用场景
      • 3.1.1 复杂事件处理
      • 3.1.2 流分析
      • 3.2.2 维护物化视图
      • 3.2.3 在流上搜索
      • 3.2.4 消息传递和RPC
    • 3.3 流的时间问题
      • 3.3.1 事件时间与处理时间
      • 3.3.2 了解什么时候准备就绪
      • 3.3.3 使用谁的时钟
      • 3.3.4 窗口类型
    • 3.4 流式join
      • 3.4.1 流和流join
      • 3.4.2 流和表join
      • 3.4.3 表和表join
      • 3.4.4 join的时间依赖性
    • 3.5 流处理的容错
      • 3.5.1 微批处理和校验点
      • 3.5.2 重新审视原子提交
      • 3.5.3 幂等性
      • 3.5.4 故障后重建状态
  • 4 小结

0 前言

流处理的思想:频繁地运行处理,即在每秒钟结束时(甚至持续不断地)处理每秒的数据,完全放弃固定的时间片,每当有事件就开始处理。就是指随着时间的推移而持续可用的数据,如TCP连接,Java FileInputStream。
本章将视为一种数据管理机制:一种无界的、持续增量处理的方式。对应批处理中的"记录",流处理中的数据单位为"事件",它们的本质都是一个小的、独立的、不可变的对象。

1 发送事件流

在流属于中,事件由生产者(发布者、发送者)生成一次,然后可能由多个消费者(订阅者或接收者)处理。相关事件通常被组合成主题或流。
在批处理中,如果要实现生产-消费的模式,通常需要消费者进行轮询。轮询的方式在低周期的情况下,代价可能很大。而流处理的当新事件出现时,通知消费者,这比轮询的性能更好。

1.1 消息系统

向消费者通知新事件的常见方法是使用消息系统
发布/订阅模式中,没有一个标准的答案满足所有目的。有两个问题值得考虑:

  • 如果生产者发送消息的速度比消费者所能处理的快,会发生什么?三种选择:丢弃消息;消息缓存在队列中;阻止生产者发送更多消息。
  • 如果节点崩溃或暂时离线,是否有消息丢失?如果能够接受消息丢失,那么系统可以获得更高的吞吐量和更低的延迟。
    生产者与消费者有多种消息传递方式。

1.1.1 生产者与消费者之间的直接消息传递

许多消息系统将生产者直接连接到消费者,而不通过中间节点:

  • UDP组播:广泛应用于金融业,如股票市场等低延迟场景。尽管UDP不可靠,但即使数据丢失,重新发送(获取)即可。
  • 无代理的消息库(ZeroMQ,nanomsg).通过TCP/IP多播实现发布/订阅系统
  • StatsD,Brubek使用UDP进行消息传递
  • 如果消费者在网络上公开服务,则生产者可以直接发出HTTP/RPC请求将消息推送给消费者。这正是webhooks的思想:一个服务的回调URL被注册到另一个服务中,每当事件发生时都会向URL发送请求。

这种模式的缺点:消息有丢失的可能性。消费者不能处于离线状态,否则消息将会漏掉。

1.1.2 消息代理

消息代理也称消息队列:实质是一种针对处理消息流而优化的数据库。它作为服务器运行,生产者和消费者作为客户端连接到它。
在系统层面,引入消息代理相当于引入了一个系统内部的稳定组件,它使得系统可以适应客户端的各种变化(离线、重启等),持久性的问题也转移到代理那里。生产者只需要确认消息已经缓存至消息队列,而无需等待消费者处理。

1.1.3 消息代理与数据库

一些消息代理甚至可以使用XA或JTA参与两阶段提交协议,因此本质上消息代理与数据库非常相似,但也有差异:

  • 消息代理在消息成功处理后即自动删除,数据库则不会
  • 多数消息系统都假定当前工作集相当小,如果队列过长,代理需要在内存和磁盘之间交换数据,整个吞吐量都可能因此降低,而且可能越来越低
  • 如果有一个订单有两个相同事件发生,数据库可能产生冲突,导致第二条数据无法写入。而消息代理则不会出现这种问题(第一个事件已删除)。

消息代理使基于瞬间的消息传递思维构建的。数据库和文件系统的内容通常都期望永久保存。
这些事消息代理的传统视点,体现在JMS和AMQP这样的标准中。并有很多系统实现:RabbitMQ,ActiveMQ,HornetMQ,Qpid,TIBCO Enterprise Message Service,IBM MQ,Azure Service Bus,Google Cloud Pub/Sub等。

1.1.4 多个消费者

当有多个消费者读取同一个主题消息时,有两种消息传递模式:

  • 负载均衡式:每条消息只传递给其中一个消费者。当处理消息的代价很高,耗时较多时,非常有用,这样多个消费者可以并行处理消息。在JMS中它称为共享订阅。
  • 扇出式:每条消息都被传递给所有的消费者。这种模式下消费者者可视为互相独立工作。

这两种模式也可以组合使用。

1.1.5 确认和重新传递

为了确保消息被处理,消息代理可以配置使用确认机制:客户端必须在处理完消息后显式地告诉代理。
如果客户端在处理完消息之后断开,则代理可能会认为消息未处理。处理这种问题需要原子提交协议。
如果消息被重传,那么消息的消费顺序与生产顺序将不一致。这需要应用层考虑是否会对业务造成影响。为了避免此问题,可以为每个消费者使用单独的队列,而不使用负载均衡功能。

1.2 分区日志

消息系统具有明显的实时特性,消息处理完即删除,因此新的消费者只能接收到注册时间点后的消息。而数据库则可以随时添加新的客户端。
日志消息代理就是试图将消息系统和数据库系统混合使用,希望同时获得低延迟和持久化。

1.2.1 基于日志的消息存储

日志是磁盘上一个仅支持追加式修改记录的序列。
Apache Kafka,Amazon Kinesis Streams ,Twitter DistributerLog都是基于日志的消息代理系统。
为了提高系统的吞吐量,可以使用多节点消息存储,对日志进行分区,不同节点负责不同的分区。可以将主题定义为一组分区。它们的工作方式为:在每个分区内,代理为每个消息分配一个单调递增的序列号,这样分区内的消息是完全有序的。
每个客户端可以配置连接到多个日志分区。对于每个分区,消费者都使用单线程(可能有误。也许是日志分区内的限制,理论上消费者的消费方式是无法限制的)顺序读取分区内的消息。
通常不会配置负载均衡模式:即多个消费者连接到同一个主题的一个日志分区。

1.2.2 对比日志和传统消息系统

客户端使用单线程读取一个日志分区消息的缺陷:

  • 同一分区内的消息通常被传递到同一节点,所以消费一个主题的节点数最多等于该主题的日志分区数
  • 如果单个消息处理缓慢,会阻碍该分区中的后续消息处理

基于日志消息系统:需要确保消息顺序;消费者处理消息快;需要非常高的吞吐量。
JMS/AMQP传统消息系统:消息顺序不重要;消费者处理消息较慢;吞吐量不是非常高。

1.2.3 消费者偏移量

顺序读取一个分区可以很容易判断哪些消息已处理,哪些消息未处理。因此,代理不需要跟踪每条消息的确认,只需要定期记录消费者的偏移量(小于该序号的消息已处理,大于该序号的消息未处理),这有助于提高系统吞吐量。

1.2.4 磁盘空间使用

如果消费者的速度远远落后于生产者,那么消费者将会错过一些消息。日志实现了一个有限大小的缓冲区,缓冲区变满时,旧的消息就被丢弃,该缓冲区位于磁盘上,其容量可以非常大。一个典型大容量硬盘时6TB,顺序写入的速度为150MB/s,那么6000000/150=40000秒=11小时,即大约11小时就可以填满磁盘。实际很少有满速写入,日志通常可以保存几天~几周。由于每个消息都被写入磁盘,因此日志的吞吐量基本不变。而对于使用内存充当缓冲区的系统,如果发生磁盘与内存交换,则会大幅降低系统吞吐量。

1.2.5 当消费者跟不上生产者时

对于这个问题,基于日志的系统处理方法是采用较大但固定大小的缓冲区。

1.2.6 重新处理信息

基于日志的消息代理,使用消息是从文件中读取,不会改变日志。如果要重新处理消息,只需要改动消费者的偏移量。

2 数据库与流

基于日志的消息代理是结合了数据库和消息系统。现在将消息传递和流的思想尝试应用于数据库,即将事件流的想法引入到数据库。数据库的更新操作非常类似于事件流。

2.1 保持系统同步

数据库、缓存、搜索索引、数据仓库之间应该保持同步。数据仓库的同步通常由ETL进程执行:获取数据库的完整副本,批量转换加载到数据仓库中。

2.2 变更数据捕获

CDC:变更数据捕获,Change Data Capture。
CDC可以将数据库的变更记录复制到所有派生数据系统中(缓存、数据仓库等)。CDC使得数据库成为其他数据系统的主节点。CDC通常是异步的。
实现CDC的有:LinkedIn Databus,Facebool Wormhole,Yahoo! Sherpa.Bottled Water 使用解码预写日志的API实现PostgreSQL的CDC,Maxwell和Debezium通过解析binlog为MySQL实现CDC。读取MongoDB的oplog也能实现类似的功能。
快照
保留所有的更改日志需要太多磁盘空间。因此重建一个数据库副本可以使用一致性快照+CDC日志的方式。此时必须记录快照在CDC中的位置。
日志压缩
使用日志压缩也可以较好地实现数据复制。其原理就是对于某一个key只保留最新的记录。这种方式无需生成数据快照。Apache Kafka支持此日志压缩功能。
对变更流的API支持
有一些数据库直接支持变更流的API:如RethinkDB支持订阅查询结果发生变化的通知。

2.3 事件溯源

事件溯源是一种在领域驱动设计(DDD)中技术。

  • 应用程序以数据可变方式操作数据库,例如自由更新和删除记录。
  • 在事件溯源中,应用程序逻辑是基于写入事件日志的不可变事件构建的。事件存储仅支持追加。事件旨在反映应用程序及所发生的事情。
    例子:"学生取消课程注册"事件以一种中立的方式清楚地表达了一个行为。而"从入学表删除一个条目,并且一条取消的原因被写入到学生反馈表"则嵌入了使用数据方式的假设。
    事件溯源是一种强大的数据建模技术:将用户的行为记录为不可变的事件,而不是记录这些行为对可变数据库的影响。事件溯源保留了业务演化的过程,它类似于编年史数据模型。
    目前已有专门的数据库如Event Store来支持事件溯源的应用程序。

2.3.1 从事件日志导出当前状态

用户需要看到系统当前的状态,这不是事件溯源日志的强项。replay事件日志可以重建系统的当前状态。事件日志也不能像CDC事件日志一样进行日志压缩,因为系统当前状态是由一些列的事件决定,事件之间不一定是覆盖关系。

2.3.2 命令和事件

事件溯源的哲学是小心地区分事件命令。命令被验证可执行被接受以后才称为一个事件。

2.4 状态,流与不可变性

应用当前状态是事件流对时间积分得到的,而变化的流是状态对时间求导得到的。数据库是日志子集的缓存。当前状态与变化流是两个不同的方面,业务通常关注状态,而业务统计需求则通常同时关注状态与事件流(某某功能点击率等)。

2.4.1 不可变事件的优势

不可变是指不改变输入数据。这样诊断问题和重试就没有明显副作用。
事件的优势在于:不仅能够得到当前的状态,还记录了发生的过程。

2.4.2 相同的事件日志派生多个视图

从事件日志可以派生出面向读取的多个视图,这也是传统数据库不具备的。分析数据库Druid使用这个方法直接从Kafka获取事件,Pistachio是一个分布式的键值存储,使用Kafka作为提交日志。Kafka Connet sinks可以将来自Kafka的数据导出到各种不同的数据库和索引中。
如果不必考虑如何查询和访问数据,那么存储数据通常非常简单。模式设计、索引、存储引擎的许多复杂性是源于希望支持某些查询和访问模式。因此,将数据写入形式与读取形式分开,并允许多个不同的读取视图,可以获得极大的灵活性。这个想法也被称为命令查询责任分离(Command Query Responsiblility Segrefation,CQRS)。
数据库和模式设计的传统方法是基于查询与写入的形式必须相同。也就是说在写入时就必须考虑读取的优化。采用CQRS之后,有关规范化和非规范化的问题也可以忽略,因为现在数据库可以只面向读取端,而不会影响写入端。

2.4.3 并发控制

事件流的最大缺点是事件日志的消费者通常是异步的,所以可能会出现"读不到自己写"。一种解决方案是同步执行视图的更新。
事件流简化了并发控制。例如多对象事务并发,如果使用事件溯源,可以设计一个事件,使其成为用户操作的独立描述。用户操作只需要在一个地方进行一次写操作,这样多对象事务很容易实现原子化。
简单来说,事件流简化了写入操作,而写冲突正是并发控制的棘手问题。

2.4.4 不变性的限制

许多不是用事件溯源模型的系统也依赖于不变性:git、mercurial、Fossil的版本控制系统就依赖于历史数据的不可变性。
不变性有几处限制:

  • 历史数据可能变得过于庞大。例如变化非常快的数据(股票指数等),在数据库内只是几条记录,而在事件日志中可能多达上亿条。
  • 删除数据变得十分困难。由于事件日志读写分离,仅仅在件日志中的追加一条删除日志是不够的,因为数据仍然在事件日志中,只不过用户看不到,这可能并未用户实际希望的。删除困难的原因也在于,目前删除的定义更多是"使之检索更加困难",而非"使检索数据彻底不可能"。

3 流处理

目前已讨论的流的来源:用户活动事件,传感器,数据库写操作;流的传输:通过直接消息传递,通过消息代理或事件日志。
流处理作业与批处理作业的关键区别是:流不会结束。

3.1 流处理的适用场景

流处理主要用于监控目的。现在也有了其他用途。

3.1.1 复杂事件处理

复杂事件处理(Complex Event Processing ,CEP)是20世纪90年代未分析事件流而发展一种方法,尤其适用需要搜索特定的事件模式。CEP允许指定规则,从而可以在流中搜索特定模式的事件。CEP通常使用类似SQL这样高级声明式查询语言。
在普通数据库中,数据是静态的,查询是动态的。而CEP系统中,查询是长期存储的,而数据流是动态的。
CEP的实现包括:Esper,IBM Info Sphere Streams,Apama,TIBCO StreamBase,SQLstream。像Samza这样的分布式流处理器也对流支持声明式SQL查询。显卡能广泛应用于AI/比特币领域也许是由于显卡也使用的流处理器?

3.1.2 流分析

CEP和流分析的有些相似,流分析更多地面向大量时间的累计效果和统计指标。
流分析有时使用概率算法。例如用于设置成员关系的布隆过滤器,用于基数估计的HyperLogLog,以及各种百分比估值计算法。概率算法能产生近似的结果,虽然不精确但其优点是在流处理器中所需的内存明显少于精确算法。概率算法仅仅是一种优化,流处理本身并没有任何固有的近似处理。
许多分布式流处理框架都考虑对分析的支持:Apache Storm,Spark Streaming ,Flink,Concord,Samza,Kafka Streams.还有一些托管服务如Google Cloud Dataflow和Azure Stream Analytics.

3.2.2 维护物化视图

对某个数据集导出一个特定的视图以便高效查询。永久维护事件的需求与面向分析的框架的假设背道而驰,这些框架主要在有限持续时间的窗口上运行。Samza和Kafka Streams支持这种用法,基于Kafka的日志压缩功能。

3.2.3 在流上搜索

除了CEP,有时候还需要给予一些复杂条件(如全文搜索查询)来搜索单个事件。与CEP的区别在于,CEP的搜索结果常常是某些事件的集合,而这里的搜索是单个时间。例如Elasticsearch的过滤器功能。传统的搜索引擎索引文档,然后在索引上运行查询。而流殇搜索则反过来:查询条件先保存下来,所有文档流过查询条件。

3.2.4 消息传递和RPC

RPC类系统和流处理有一些交叉的地方。例如Apache Storm有一个称为分布式RPC的功能。
但它们的系统目标并不相同,RPC类系统通常没有容错。

3.3 流的时间问题

批处理处理的是静态数据,一般不存在时钟问题。而流处理经常需要和时间打交道。例如"最近5分钟内的请求数",这里有一个5分钟的时间窗口。如果事件发生的事件和事件处理的时间间隔较长,那么时间窗口上的监控可能就达不到要求。

3.3.1 事件时间与处理时间

如果流处理作业来测量请求频率,如果重新部署了流处理系统,中间会关闭一分钟,在重启之后继续处理积压的时间。那么重启之后会出现一个请求频率峰值,这是与实际情况不符的。出现该问题的原因就是混淆了事件事件与处理事件的时间。

3.3.2 了解什么时候准备就绪

基于事件发生事件定义的窗口,也面临一个棘手问题:无法确定何时关闭时间窗口。因为该窗口是基于时间发生时间定义的,它不能基于流处理系统自身的时间判断,因此无法确定是否还有一些事件未到来。大体上只有两个选择:

  • 忽略滞后的事件。当丢弃大量事件时发出警报
  • 发布一个更正:针对有滞后情况的时间窗口发布一个更新值。

3.3.3 使用谁的时钟

一般可以记录三种时间戳:

  • 根据设备的时钟,记录事件发生的时间
  • 根据设备的时钟,记录事件发送到服务器的时间
  • 根据服务器的时钟,记录服务器收到事件的时间

通过第二、三个时间戳可以估计出服务器和设备时钟的偏移量。将偏移量加到第一个时间戳即可以估计出事件发生的真实时间。

3.3.4 窗口类型

确定了事件的时间戳,下一步是决定如何定义时间段即时间窗口。

轮转窗口
长度固定,每个事件都属于一个窗口。例如1分钟间隔的窗口:10:00:0010:00:59,10:01:0010:01:59,…。
跳跃窗口
固定长度。但允许窗口重叠,有一些平滑的过渡。设定长度为5分钟,跳跃值(hop)为1分钟,则窗口可能为:10:03:0010:07:59,10:04:0010:08:59,…可以通过计算1分钟滚动窗口,然后聚合几个相邻的窗口实现跳跃窗口。
滑动窗口
滑动窗口包含在彼此的某个间隔时间内发生的所有事件。滑动窗口的长度是固定的,但边界是不断滑动的。将事件按时间排序,放入窗口缓冲区,并及时移除过期旧事件来实现滑动窗口。
会话窗口
会话窗口没有固定的持续时间。它是通常将同一用户在时间上紧密相关的所有事件分组在一起而定义的。在长时间(如30分钟)未活动,则窗口结束。

3.4 流式join

批处理作业中通过主键join数据集。流处理也有join的需求。流处理中随时可能有新事件发生,这是处理流式join的难点。
根据join两端的数据源可以为分三类:流join流,流join表,表join表。

3.4.1 流和流join

流和流join:一个数据流join另一个数据流。
举例:用户浏览某网站,会产生一个搜索事件流,后续会产生一个点击事件流。要分析搜索结果的质量,需要将搜索事件流join点击事件流。如果搜索结果质量低,那么可以预见点击事件流大小会远远小于搜索事件流。即要分析搜索结果质量,需要综合两个事件流。
实现方式是采用窗口join,可以将一段时间内同一会话ID的事件聚合到一起。
将搜索事件嵌入点击事件中,这种做法的问题在于,它不能收集到那些没有点击事件的用户行为。

3.4.2 流和表join

事件流和数据库中表的join是很常见的需求。如果采取实时查询远程数据库的方法,那么查询将会很慢,且可能导致业务数据库过载。
另一种方法是将数据库副本加载到流处理器中,以便在本地进行查询而无需经过网络往返。注意,由于流处理的特性,此处的数据库副本不是某个时间点的快照,而是需要持续更新,可以使用变更数据捕获手段解决。
流和表的join类似于流和流join,区别是数据库表的新纪录会覆盖旧记录,如果更新很快,这可能会是一个问题。数据库的记录有持久性保证,这是流不具备的。

3.4.3 表和表join

这里的表都是指事件日志的物化视图。它可能是SQL,也可能是NOSQL。
举例:Twitter时间线。通常的想法是:当用户想要查看其主页时间线时,循环遍历用户关注的所有人、查找他们最近的推文并将其合并。这一操作代价很高.
如果有一个时间线缓存,充当每个用户的"收件箱",在发送推文时就将其写入其中,因此读取时间线就只需要一次查询。实现和维护这个缓存需要以下事件处理:

  • 当用户u发送新推文时,它被添加到每个关注u的用户的收件箱(时间线)
  • 当用户u删除推文时,会从所有用户(u及关注u)的时间线中删除。
  • 当u1u_1u1​关注u2u_2u2​,u2u_2u2​最近的推文被添加到u1u_1u1​时间线。
  • 当用户u1u_1u1​取消关注u2u_2u2​,u2u_2u2​的推文将从u1u_1u1​的收件箱移除

我使用的新浪微博国际版(20190802),以上4条没有一条是令人满意的。取消关注但推文还在的现象很常见。

3.4.4 join的时间依赖性

依据多个事件流的join来维护(决定)某些状态(数据)时,就产生了一个分布式问题。多个事件流意味着多数据源,维持多数据源事件的顺序非常重要。例如取消关注事件和关注事件,不同的顺序得到的结果状态完全相反。

如销售某些商品,需要计算税率,join的税率是不断变化的,如果事件顺序不能确定,那么到底应该应用旧税率还是新税率就不能确定。在数据仓库中,这个问题被称为缓慢变化的维度(Slowly Changing Dimension,SCD)。它通过对特定版本的join记录赋予唯一标识符来解决,即将税率信息写入销售记录中。这种做法有破坏范式的嫌疑,也导致日志压缩几乎无法进行(不同版本的数据无法合并)。在业务上,也极难处理。如果该订单允许修改,那么可能一部分是旧税率,一部分是新税率;也就是说业务的结果跟过程紧密关联,而数据库只记录数据结果,这便是订单修改业务的难点所在。

3.5 流处理的容错

批处理只需要重试作业即可实现无副作用的容错机制。这种原则被称为恰好一次语义,虽然有效一次应该更准确。

3.5.1 微批处理和校验点

一种解决方案是将流分解成多个小块,并像小型批处理一样处理每个块。这种方法被称为微批处理,已经用于Spark Streaming。微批处理的大小通常为1s,这个值也就是流处理中时间窗口的单位,例如如果需要设置10s的轮转窗口,那么它可以被分解为10个微批处理作业。
Apache Flink中使用该方法的一个变体。它定期生成状态滚动检查点并将其持久化。如果流操作发生崩溃,它只从最近的检查点重新启动,并丢弃在上一个检查点和崩溃之间生成的所有输出。检查点是由消息流中的barrier触发,它不强制特定的窗口大小。

批处理作业重试无副作用的重要原因是由于它的输出只是HDFS上的文件,批处理作业的用途决定了这种做法可行。但流处理作业的用途比较广泛,包括和在线业务联系十分紧密的场景,这种情况下,微批处理无法杜绝重试的副作用。

3.5.2 重新审视原子提交

为了实现"看起来恰好处理一次",我们需要确保当且仅当处理成功时,所有输出和副作用才会生效。java stream api 就有类似机制,在调用求值方法前,流不会开始运行。
这些事情要么都发生,要么都不发生,这就是(分布式)事务中的原子提交问题。Apache Kafka计划增加该功能。

3.5.3 幂等性

安全重试除了采用分布式事务机制,还可以依赖写入操作本身的幂等性。
幂等性要求重复执行一个操作时,具有相同的结果。如果已经执行过,那么应该忽略操作,且返回执行成功。
幂等性的开销很小。

3.5.4 故障后重建状态

故障之后为了重建状态,一种选择是将状态保存在远程存储中并采取复制。另一种方法是将状态在本地保存,并定期进行复制。当流处理器从故障中恢复时,新任务可以读取副本状态并且在不丢失数据的情况下恢复处理。
例如Flink定期对操作状态执行快照,并写入HDFS。Samza和Kafka Streams通过将状态变更发送到具有日志压缩功能的专用Kafka主题来保存状态的副本(该功能可视为数据库),这类似于变更数据捕获。VoltDB则通过在多个节点上冗余处理每个输入消息来复制状态。
权衡屈居于底层基础架构的性能表现:某些系统网络延迟可能低于磁盘访问延迟。

4 小结

《数据密集型应用系统设计》笔记-8-流处理相关推荐

  1. 数据密集型应用系统设计——笔记

    本篇章内容为阅读<数据密集型应用系统设计>一书的读书笔记. 作为个人成长学习使用,同时希望对刷到的朋友有所帮助,一起加油哦! 生命就像一朵花,要拼尽全力绽放,芳香四溢,在风中舞蹈! 写在前 ...

  2. 数据密集型应用系统设计-第七章分布式系统的麻烦-笔记

    这阵子在看数据密集型应用系统设计书籍,自己把书籍比较重要的内容整理出来,基本一天一更,请感兴趣的朋友多多关注! 整个系列会在这几天都发布出来,可以关注一下 链接: 数据密集型应用系统设计-笔记. 文章 ...

  3. 《数据密集型应用系统设计》读书笔记——数据系统基础

    因为个人兴趣,想学学分布式方面的知识,然后找到了这本<数据密集型应用系统设计>,确实非常的不错,无论对于以前的工程还是现在的科研都有启迪和感悟,所以就写份读书笔记记录一下,里面提到的知识非 ...

  4. Designing Data-Intensive Application《数据密集型应用系统设计》笔记

    Designing Data-Intensive Application 中译<设计数据密集型应用>又名<数据密集型应用系统设计>,我看的是冯若航在gitbook开源的翻译版本 ...

  5. 《数据密集型应用系统设计》读书笔记——第一部分 数据系统基础

    第一部分 数据系统基础 第1章 可靠.可扩展与可维护的应用系统 当今许多新型应用都属于数据密集型,而不是计算密集型.对于这些类型应用,CPU的处理能力往往不是第一限制性因素,关键在于数据量.数据的复杂 ...

  6. 豆瓣评分 9.7 的神书:《数据密集型应用系统设计》

    我最近在读一本好书<数据密集型应用系统设计>(也被叫做 DDIA).这真是本相见恨晚的神书. 这是怎样一本神书?豆瓣评分高达 9.7 分! 什么是「数据密集型应用系统」? 当数据(数据量. ...

  7. 数据密集型应用系统设计 [Designing Data-Intensive Applications]

    作者:[美] Martin Kleppmann(马丁·科勒普曼) 著,赵军平 吕云松 耿煜 李三平 译 出版社: 中国电力出版社 出版时间:2018-09-01 数据密集型应用系统设计 [Design ...

  8. 数据密集型应用系统设计(读书笔记)第一天

    第一章: 可靠.可扩展与可维护的应用系统 数据密集型应用通常也是基于标准模块构建而成,每个模块负责单一的常用功能.例如,许多应用系统都包含以下模块: 数据库:用以存储数据,这样之后应用可以再次面问. ...

  9. 《数据密集型应用系统设计》读书笔记——第二部分 分布式数据系统(二)

    第8章 分布式系统的挑战 故障与部分失效 当你在⼀台计算机上编写一个程序时,它通常会以一种确定的方式运⾏:⽆论是⼯作还是不工作.充满错误的软件可能会让人觉得电脑有时候是"糟糕的一天" ...

  10. 《数据密集型应用系统设计》读书笔记

    个人读书笔记,有些地方用词不够严谨(欢迎评论指正),见谅.书籍链接 笔记是个人理解,与书籍可能有偏差,建议看书. 问题: 什么样的数据适合图数据库? 社交关系?网页数据?地图数据? mysql有没有事 ...

最新文章

  1. Jsoup获取全国地区数据(省市县镇村)
  2. [原创]浅谈持续集成在测试中的应用
  3. 最新:全球大型数据中心总数增至597个,是2015年数据中心数量的两倍
  4. 时间序列错位还原之SQL实现案例详解
  5. matlab文件目录表示,Matlab - 文件目录路径操作_读取不同路径下的相同文件名表格...
  6. 土压力图怎么画_电气系统图怎么画?
  7. Windows 2003下×××服务器架设攻略
  8. codeforces 732/D 二分
  9. MATLAB学习笔记(十)
  10. java流被关闭后怎样重新打开,java – 如何停止MediaPlayer流然后重新启动它? Android的...
  11. java语言程序设计期中考试_《java语言程序设计》期中试卷(答案).doc
  12. 不同修饰符的访问权限(private,缺省(默认即default),protected,public)
  13. solr的索引库配置
  14. 2018/3/9 省选模拟赛 0分
  15. 8 随机积分与随机微分方程
  16. MODBUS转EtherNet/IP网关连接罗克韦尔(AB)PLC与英威腾变频器配置案例
  17. “ 鸡声茅店月,人迹板桥霜” 道尽多少旅人的离愁别绪
  18. dos从优盘启动计算机,对老旧电脑升级很重要,教你制作纯DOS的U盘启动盘
  19. java学习 遇到的基本错误
  20. 全国最大直男论坛的性感女神翻车了,网友:乔碧萝第二

热门文章

  1. Android 10.0修改桌面时钟字体大小和字体颜色
  2. Windows下使用FreeSSL刷新网络安全证书
  3. Win 10 专业版重新激活详细操作步骤
  4. python提取句子_关于python:从句子中提取介词短语
  5. spss可以关键词词频分析吗_词频分析研究的现状、方法及工具,你值得拥有
  6. 解决缓存和数据库双写数据一致性问题
  7. 分享一个简单唯美的404页
  8. Win10系统高分辨率缩放时应用程序字体模糊
  9. VTracer - 将图片转化为矢量 SVG 图形的免费开源工具
  10. API安全前景与趋势