Samza状态管理分析

来源:互联网 发布:站长工具 网站数据 编辑:程序博客网 时间:2024/05/21 06:29

Samza是依赖Kafka作为通信层的流计算框架。本文主要分析其state的管理。


概述

增量

存储粒度:增量。这里的存储粒度指的是对状态的容错处理,在分布式环境中,保存在本地(内存OR硬盘)的状态随时可能丢失,所以需要把状态定期checkpoint到可靠的存储引擎中,增量还是全量取决于checkpoint的方式。

目前Trident靠HBase等数据库产品帮它做了增量的状态管理,但是当状态量过大时,内存装不下,这时状态的所有操作都只能退化到HBase的操作。

Flink目前虽然提供RocksDb+HDFS的状态容错管理,但是还是全量的checkpoint。

at-least-once

事务保证:at-least-once。由于Samza没有把版本号(数据的批次ID等)和状态结合起来,所以当计算失败时,状态却不能回溯到以前的状态。

Trident和Flink均可保证exactly-once。

状态应用

1.聚合:比如wordcount、uv、pv等,持续变化的值就是需要容错管理的状态。
2.Join:如果需要对两条stream进行join,就需要对这些实时产生的中间结果进行容错处理。
etc..

实现

如果像Trident把状态全部缓存到内存中(等到批次处理完才进行增量checkpoint),有些场景内存却撑不住,比如stream join stream的场景。
这时需要一个无界的存储机制来保存状态。

这里的Key-Value Store可以是外部的HBase等数据库产品,外部数据库主要有以下缺点:
1.性能问题:比起走内存和磁盘,网络的开销明显要大得多,而且外部存储的消耗也是成本的一部分。
2.依赖问题:毕竟要需要搭建和运维另外一套HBase的系统。
所以Samza使用了本地存储+增量Checkpoint的方案。实现了RocksDb(LevelDb的加强版)+Kafka Checkpoint的方案。


Samza将状态的changeLog和输出到下游的数据一样抽象成Stream的概念,其实这里就是将Kafka当做了一个分布式文件系统来用,并且使用了它的LogCompact功能,将越来越多的Log Compact聚合防止数据量过多。

在实现上,Samza使用了三个类来包装。
1.CachedStore:使用了LinkedHashMap来构建了一个缓存,达到四个效果:Batch操作RocksDb、聚合相同Key的操作、只flush Dirty的key、减少序列化反序列化。
2.LoggedStore:在操作key的同时记录Log到Kafka中,Log包括put和delete,格式为:stream+partitionId+key+value。delete时value为null值。
3.RocksDbKeyValueStore:RocksDb的put、get、delete以及range、batch等操作。

在恢复时,消费Kafka的所有Log,写入KV数据到RocksDb中。
Samza并没有实现Log日志的Compact,而是将此工作交给了Kafka。
Compact简单的实现可以是读取一条条日志,存储到RocksDb中,然后触发一次RocksDb的Compact,再读取所有值写到外部文件系统,把落盘+去重交给RocksDb来完成,所以我觉得完全可以将这部分实现成RocksDb+HDFS的增量存储方案。

详情可参考Samza官方网站。
0 0
原创粉丝点击