重构大数据平台的存储栈

当前大数据处理平台存在的问题

如图1是目前大数据处理平台最常见的Lambda架构,它的优势在于实时处理与批处理统一,但是它的缺点也很明显:

  1. 实时处理一条路径,批处理另外一条路径,不同的路径采用了不同的计算组件,这就增加了系统的复杂度;
  2. 数据存储多组件化、多份化,如下图,同样的数据会被存储在ElasticSearch 里、S3对象存储系统里、Kafka里、HDFS里以及Cassandra里,而且考虑到数据的可靠性,数据还都是多份冗余的,这就极大的增加了用户的存储成本;
  3. 系统里组件太多太复杂,也增加了用户的运维成本。

lambda架构

​图1. Lambda架构

因此,为了解决Lambda架构的以上三大缺点,流式架构被提出。在流式架构里,流计算一般选用Flink作为计算组件,那么对于存储来说又意味着什么呢?为了降低系统复杂度、减少用户的存储成本与运维成本,我们推出了 流存储,目的之一就是为了重构Lambda架构里的存储栈,这样流式架构就可以由”流计算+流存储“组成。

第4种存储类型 - 流存储

首先,流式大数据处理平台里的数据一般被称之为“流数据”,流数据在百度百科里是这样被定义的:

流数据是一组顺序、大量、快速、连续到达的数据序列,一般情况下,数据流可被视为一个随时间延续而无限增长的动态数据集合。应用于网络监控、传感器网络、航空航天、气象测控和金融服务等领域。

那么目前又有哪种存储系统最适合用于“流数据”呢?正如当前技术条件下最适合“流数据”计算的是类似Flink这样的流计算应用,最适合“流数据”存储的应当是流存储系统。

如图2所示,从 存储的视角来说,每种类型的数据都有其原生的属性和需求,对应有最佳的适用场景以及最合适的存储系统。

存储类型

​ 图2. 4大存储类型

简单来说就是传统数据库这类对于IOPS要求高的业务需要块存储系统。文件共享场景下需要在用户间共享文件进行读写操作,因此适合采用分布式文件存储系统。而互联网业务文件以及图片、视频等适合采用对象存储系统。

流数据存储具有性能要求高、严格次序保证、连续而又无限、大规模租户隔离等特点,而目前市面上又没有这样一个专门针对流数据进行设计的存储系统。因此,为了满足业务需求、平衡商业成本与技术成本,也为了给流数据提供最佳最合适的存储系统,分布式流存储Pravega被推出。

I/O路径隔离

​ 图3. 日志结构

如图3所示:在Pravega里,日志是作为共享存储原语而存在的。Pravega被推出的目的之一就是为了 重构Lambda架构里的存储栈:流批统一、降低存储成本以及运维成本。 一般数据的批处理对应于处理历史数据,因此Pravega支持高吞吐量的追赶读;数据的流处理对应于处理实时数据,因此Pravega又支持低时延的尾部读取以及写入;同时Pravega通过分层存储以及资源自动伸缩降低了用户的存储成本以及运维成本。

Pravega关键架构

架构目标

  • 持久化:在客户端确认写入前,数据被复制并且写入磁盘;
  • 严格的顺序保证以及恰好一次语义:支持追赶读、尾部读以及从中间任意位置读,支持事务
  • 轻量级:一个流就如同一个文件,可以在单集群里创建千万量级起的流;
  • 可弹性:可基于负载和吞吐量智能地动态扩展或者收缩流;
  • 无限性:存储空间大小不受单个节点的容量限制;
  • 高性能:写入延迟低于10ms,吞吐量仅受网络带宽限制,读模式(例如:追赶读)不影响写性能;

逻辑架构

”技术在某种程度上一定是来自此前已有技术的新的组合“ – 《技术的本质》,布莱恩·阿瑟

Pravega为连续而又无限的数据提供了一种新的存储原语 - 流存储,然而Pravega也并不是凭空发明出来的,它是以前成熟技术与新技术的组合,例如Pravega的 范围、流、段、事件就跟Kafka的主题、分区、段、消息对应,而一层存储又用了Bookkeeper,协调器用了Zookeeper等,如图4 :Pravega的逻辑架构。

逻辑架构图

​ 图4. 逻辑架构

  1. Pravega提供了一个用Java编写的客户端库,抽象出了流协议层接口,用于支持客户端应用,例如Flink、Spark以及一些检索系统等;
  2. Pravega实现了一个流数据抽象层,用于事件流和字节流的抽象;
  3. Pravega遵循软件定义存储的设计规则,其控制面与数据面分离,控制实例组成控制面,实现了检索流信息、监控集群、收集相关指标等功能,同时为了实现高可用,通常有多个(建议至少3个)控制实例同时对外提供服务;
  4. Pravega采用Zookeeper作为集群中的协调组件;
  5. Pravega的第1层存储系统由bookkeeper实现,第2层存储系统由开源的HDFS、Ceph、GlusterFS、Swift或者商业存储产品组成。

流批统一 - 降低系统复杂度

通过使用Pravega,实现了流批统一的大数据处理架构,重构了大数据处理平台的存储栈,有效降低了系统复杂度.

存储分层 - 降低存储成本

如图4所示,在Pravega里,底层存储系统由两部分组成:第1层为低时延存储层,主要关注性能,用于存储热点数据,由bookkeeper实现,保证了存储系统的低时延、高性能。第2层为长期存储层,主要关注低成本、高吞吐量以及高可扩展性,提供数据的长期存储,由开源的或者商业的存储产品组成。随着数据的老化,第1层中的数据将自动分层流入第2层。通过这种方式,冷热数据分离有效降低了数据存储成本。

资源自动缩放 - 减少运维成本

在Pravega里,当流中的负载上升或下降时,流中段的数量会随着负载自动增长或收缩,此特性被称之为“自动缩放”,该特性无需人工干预自动完成,有效减少了系统的运维成本。当创建流时,可以使用缩放策略配置流,该策略确定流如何响应其负载变化,目前支持三种策略:1)固定,流段的数量不随负载而变化;2)基于写入的字节数,当每秒写入流的数据字节数增量超过某个目标速率时,流段的数量增加,相应的如果它低于某个流速时,流段数量减少;3)基于事件的个数,与基于字节数的扩展策略类似,不同之处在于它使用事件的个数而不是字节数。

Pravega的一些关键概念与特性

本章节将简要介绍一些Pravega的关键特性。

范围(scope):在Pravega里,范围是流的命名空间,例如可以把一台机器命名为一个范围,也可以把一个无人车命名为一个范围,还可以把整个工厂命名为一个范围。

流(stream):在同一个范围内流具有命名唯一性,所有流的名称在同一个范围内都是唯一的。在pravega里数据被组织到流中的,流是一种可持久化、可伸缩、仅附加、字节大小无限制的序列,具有高性能和强一致性的特性。

段(segment):流由段组成,段是流的分片。

事件(event): 段由事件组成,事件存储在段里,事件是流中的可以表示为一组字节的任何事物。例如:来自温度传感器的读数,它包含少量的字节且由时间戳,度量标识符和温度值组成。另外事件也可以是与用户点击网站或APP相关联的日志数据等。

写客户端(writers):写客户端是一个可以创建事件并将事件写入流中的应用,所有的事件数据都可以通过附加到流的尾部来写入。

读客户端(readers):读客户端是一个可以从流中读取事件的应用,读客户端可以从流中的任何一点读取,比如头部、尾部、中间任何一点。

读者组(readerGroups):读者组由读客户端组成,读者组本质上是为了实现同一个组内读客户端的平衡以及不同组的扇出。同一个读者组内的读客户端可以一起并行读取给定的一组流段内的事件,比如一个读客户端对应一个段。不同的应用可以定义不同的读者组实现扇出,比如定义一个Flink读者组,再定义一个检索读者组,这样二者互不影响,互不干涉,可以优雅而又和谐地一起读取同一个流段内的事件。

顺序保证:流是由段组成的,写入流的事件被写入单个段,在同一个段内的事件具有顺序性。对于读客户端来说,可以分配多个可并行读取的段,从多个段读取的也许是交错的事件,但在同一个段内读取的数据是有严格有序的。

检查点:Pravega为应用提供了在读者组上初始化检查点的功能,使用检查点的意图是通过使用检查点事件来确保每个读客户端能保存原来的使用状态。

事务: Pravega提供了事务功能,事务是写客户端可以“批处理”一堆事件并将它们作为一个处理单元原子性地提交到流中。这一堆事件要么所有都处理成功,要么所有都处理失败。在提交事务之前,发布到事务中的事件永远不会被读客户端看到。

状态同步器: Pravega也提供了在分布式计算环境中作为协调器的功能,类似Zookeeper、ETCD这样的提供分布式共识和领导者选举能力。这样的组件在Pravega里被称作“状态同步器”。状态同步器为在集群中运行的多个进程之间的共享状态提供同步机制,使用户可以轻松地构建高级服务,从而使用户更加的容易构建分布式应用。

恰好一次: Pravega确保每个事件只被处理一次,即使客户端、服务器或网络出现故障也能保证精确的处理顺序。

性能: Pravega的延迟目标为毫秒级(<10ms);

永久保留: Pravega将流的抽象与实际数据存储分离,这使得Pravega可以透明地将数据从低延迟、持久的存储层移到云存储服务层。

高效存储: Pravega统一了流(有序)数据和批量(并行)数据的访问,可以将批量和实时应用程序结合起来而无需为流式计算流水线(比如Flink)的每个步骤复制数据从而有效的提高了数据的存储效率。



## 与kafka对比

前面我们已经提到过Pravega是从 存储的视角来看待流数据,而Kafka本身的定位是消息系统而不是存储系统,它是从 消息的视角来看待流数据。消息系统与存储系统的定位是不同的,简单来说,消息系统是消息的传输系统,关注的是数据传输与生产消费的过程。而存储系统除了关注存储用的物理媒介,数据的持久化、安全、可靠性、一致性、隔离等都是它的原生属性,它关注数据的生产、传输、存放、访问等整个数据的生命周期。

这里我们把Pravega与Kafka做了对比,大体在功能上的差异如下表所示。功能上的差异也只是说明各个产品针对的业务场景不同,看待数据的视角不同,并不是说明这个产品不好,另外每个产品自身也在演进,因此本对比仅供参考。

名称 Kafka 2.1.0 Pravega GA
自动扩容缩容 部分支持 支持
完全不丢数据 不支持 支持
多协议可入 支持 支持
无限个流 不支持 支持
事务 支持 支持
恰好一次 支持 支持
顺序保证 支持 支持
兼容Kafka API 支持 支持
数据链接与汇聚 支持 部分支持
多种二层存储支持(ECS,HDFS,S3,etc) 不支持 支持
安全与加密 支持 支持
无限多租户 不支持 部分支持
服务质量保证 部分支持 部分支持
流计算应用集成 支持 支持
数据治理 不支持 支持

总结

本文讲述了推出分布式流存储Pravega的原因,介绍了一些Pravega的关键架构以及关键特性,另外还与Kafka做了简要对比。有关Pravega的更多详细信息,请参阅官方网站以及关注我们的后续文章。另作者能力有限,如有不足之处欢迎留言批评指正。

问题思考

最后给大家留一个问题:一般来说从开源项目到商业产品还是有一段距离的(注意这里的用词:开源的“项目”,商业的“产品”),那么对于设计开发人员来说应该如何弥补这段距离,从而使得开源项目产品化?