Jindo 是阿里云基于 Apache Spark / Apache Hadoop 在云上定制的分布式计算和存储引擎。 Jindo 原是阿里云 开源大数据团队的内部研发代号, 取自筋斗(云)的谐音,Jindo 在开源基础上做了大量优化和扩展, 深度集成和连接了众多阿里云基础服务。
JindoFS 是阿里云针对云上存储自研的大数据缓存加速服务, JindoFS 的设计理念是云原生: 弹性、 高效、 稳定和低成本。 JindoFS 完全兼容 Hadoop 文件系统接口, 给客户带来更加灵活、 高效的数据湖加速方案, 完全兼容阿里云 EMR 中所有的计算服务和引擎: Spark、 Flink、 Hive、 MapReduce、 Presto、 Impala 等。 JindoFS 有两种使用模式, 块存储模式(BLOCK)和缓存模式(CACHE)。 下面我们介绍下如何在 EMR 中配置和使用 JindoFS 以及不同模式对应的场景。

JindoFS 架构

JindoFS 主要包含两个服务组件: 元数据服务(NamespaceService) 和存储服务(StorageService):NamespaceService 主要负责元数据管理以及管理 StorageService;StorageService 主要负责管理节点的本地数据和 OSS 上的缓存数据。下图是 JindoFS 架构图: 元数据服务 NamespaceService 部署在独立的节点, 对于生产环境推荐部署三台(Raft)来实现服务高可用; 存储服务 StorageService 部署在集群的计算节点, 管理节点上的闲置存储资源( 本地盘/SSD/内存等) , 为 JindoFS 提供分布式缓存能力。

阿里云云原生数据湖体系全解读——数据湖加速JindoFS 计算节点数据缓存_云原生

元数据服务

JindoFS 的元数据服务叫 JindoNamespaceService, 内部基于 K-V 结构存储元数据, 相对于传统的内存结构有着操作高效, 易管理, 易恢复等优势。JindoFS NamespaceService 基于内存 + 磁盘管理和存储元数据, 但是性能上比使用内存的 HDFS NameNode 还要好, 一方面是 JindoFS 使用 C++ 开发, 没有GC 等问题, 响应更快; 另一方面是由于 Namespace Service 内部有更好的设计, 比如文件元数据上更细粒度的锁, 更高效的数据块副本管理机制。
有大规模 HDFS 集群维护经验的同学比较清楚, 当 HDFS 元数据存储量过亿以后,NameNode 启动初始化要先加载 Fsimage , 再合并 edit log, 然后等待全部DataNode 上报 Block, 这一系列流程完成要花费一个小时甚至更长的时间, 由于NameNode 是双机高可用( Active/Standby) , 如果 standby 节点重启时 active 节点出现异常 , 或两台 NameNode 节点同时出现故障, HDFS 将出现停服一小时以上的损失。 JindoFS 的元数据服务基于 Raft 实现高可用, 支持 2N+1 的部署方式, 允许同时挂掉 N 台; 元数据服务 (NamespaceService) 在元数据内部存储上进行了设计和优化, 进程启动后即可提供服务, 可以做到了快速响应。 由于 NamespaceService 近实时写入 OTS 的特点, 元数据节点更换, 甚至集群整体迁移也非常容易。
HDFS NameNode 采用内存形式来存储文件元数据。 在一定规模下, 这种做法性能上是比较不错的, 但是这样的做法也使 HDFS 元数据的规模受限于节点的内存, 经过推算,1 亿文件 HDFS 文件大约需要分配 60 GB Java Heap 给 NameNode, 所以一台256 GB 的机器最多可以管理 4 亿左右的元数据, 同时还需要不断调优 JVM GC。JindoFS 的元数据采用 Rocksdb 存储元数据, 可以轻松支持到 10 亿规模, 对于节点的内存需求也非常小, 资源开销不到 NameNode 的十分之一。

存储服务

JindoFS 的数据缓存服务叫 JindoStorageService, 本地 StorageService 主要提供高性能缓存加速, 所以运维上可以基于这样的设定大大简化。HDFS 使用 DataNode 在存储节点上来管理节点存储, 全部数据块都存储在节点的磁盘上, 依靠 DataNode 定期检查和心跳把存储状态上报给 NameNode,NameNode 通过汇总和计算, 动态地保证文件的数据块达到设定的副本数( 一般 3 副本) 。 对于大规模集群( 节点 1000+) , 经常需要进行集群节点扩容, 节点迁移, 节点下线, 节点数据平衡这样的操作, 大量的数据块的副本计算增加了 NameNode 负载, 同时,节点相关操作要等待 NameNode 内部的副本调度完成才能进行, 通常一个存储节点的下线需要小时级别的等待才能完成。 JindoFS 使用 StorageService 来管理节点上的存储,由于 JindoFS 保证了数据在 OSS 上有一副本, 所以本地的副本主要用来进行缓存加速。对于节点迁移、 节点下线等场景, JindoFS 无需复杂副本计算, 通过快速的“ 标记” 即可完成下线。
StorageService 采用 C++ 语言开发, 在对接最新高性能存储硬件上也有着天然优势。 StorageService 的存储后端不仅可以同时对接 SSD、 本磁盘、 OSS 满足Hadoop/Spark 大数据框架各种海量、 高性能的存储访问需求, 可以对接内存、 AEP 这样的高性能设备满足 AI/机器学习的低延时、 高吞吐的存储使用需求。

适用场景

JindoFS 的元数据存储在 Master 节点的 NamespaceService( 高可用部署)上,性能和体验上对标 HDFS; Core 节点的 StorageService 将一份数据块存储在 OSS上, 本地数据块可以随着节点资源进行快速的弹性伸缩。 多集群之间也可以相互打通。

阿里云云原生数据湖体系全解读——数据湖加速JindoFS 计算节点数据缓存_缓存_02


缓存模式:对于已经存在于 OSS 上的数据, 可以使用缓存模式访问, 正如“ 缓存” 本身的含义,通过缓存的方式, 在本地集群基于 JindoFS 的存储能力构建了一个分布式缓存服务, 把远端数据缓存在本地集群, 使远端数据“ 本地化” 。 使用上也沿用原来的路径访问, 如oss://bucket1/file1 , 这种模式全量的文件都在 OSS 上面, 可以做到集群级别的弹性使用。

存储模式:适用于高性能数据处理场景, 元数据存储在 NamespaceService( 支持高可用部署) 上, 性能和体验上对标 HDFS; StorageService 将一份数据块存储在 O S S 上 , 本 地 数 据 块 可 以 随 着 节 点 资 源 可 以 进 行 快 速 的 弹 性 伸 缩 。 基 于JindoFS Block 模式这样的特性, 可以用作构建高性能数仓的核心存储, 多个计算集群可以访问 JindoFS 主集群的数据。数据湖是开放的, 需要对接各种计算引擎。 目前 JindoFS 已经明确支持 Spark、Flink、 Hive、 MapReduce、 Presto 和 Impala 组件。 同时, JindoFS 为了支持更好地 使 用 数 据 湖 , 还 提 供 Ji n d o T a b l e 对 结 构 化 数 据 进 行 优 化 和 查 询 加 速 ; 提 供JindoDistCp 来支持 HDFS 离线数据往 OSS 迁移; 支持 JindoFuse 方便数据湖上加速机器学习训练。JindoFS 包含了 FUSE 客户端, 提供了简便的、 熟悉的数据访问方式。 通过 FUSE程序将 JindoFS 集群实例映射到本地文件系统, 就可以像访问本地磁盘文件一样, 享受到JindoFS 带来的加速效果

阿里云云原生数据湖体系全解读——数据湖加速JindoFS 计算节点数据缓存_云原生_03


配置 OSS Bucket 和 AK

阿里云云原生数据湖体系全解读——数据湖加速JindoFS 计算节点数据缓存_云原生_04


通过这些配置项, 我们创建了一个名为 test 的命名空间, 指向了 chengli-sh-test 这个 OSS bucket 的 xxx/k8s_c1 目录。后续我们通过 JindoFS 操作 test 命名空间的时候,就等同于操作该 OSS 目录。

阿里云云原生数据湖体系全解读——数据湖加速JindoFS 计算节点数据缓存_数据_05


在宿主机上访问/mnt/jfs/目录, 即等同于访问 JindoFS 的文件

阿里云云原生数据湖体系全解读——数据湖加速JindoFS 计算节点数据缓存_数据_06


Kubeflow 是开源的基于 Kubernetes 云原生 AI 平台, 用于开发、 编排、 部署和运行可扩展的便携式机器学习工作负载。 Kubeflow 支持两种 TensorFlow 框架分布式训练,分别是参数服务器模式和 AllReduce 模式。 基于阿里云容器服务团队开发的 Arena, 用户可以提交这两种类型的分布式训练框架。

阿里云云原生数据湖体系全解读——数据湖加速JindoFS 计算节点数据缓存_数据_07

JindoTable

数据湖需要存储来自各种数据源的数据。 对于 HDFS 集群, 小文件问题让很多用户倍感烦恼。 在存储计算分离的数据湖中, 小文件同样会产生很多问题: 过多的文件数会导致目录 list 时间显著变长, 小文件也会影响很多计算引擎的并发度。 此外, 由于对象存储一般以对象为单位, 小文件也会导致请求数量的上升, 会明显影响元数据操作的性能, 更会增加企
业需要支付的费用。 而如果数据文件过大, 如果数据又使用了不可分割的压缩格式, 后续计算的并发度会过低, 导致无法充分发挥集群的计算能力。 因此, 即使是数据湖架构中, 对数据文件进行治理和优化也是非常必要的。基于数据湖所管理的元数据信息, JindoTable 为客户提供了一键式的优化功能, 用户只要在资源较为空闲时触发优化指令, JindoTable 可以自动为用户优化数据, 规整文件大小, 进行适当的排序、 预计算, 生成适当的索引信息和统计信息, 结合计算引擎的修改, 可以为这些数据生成更加高效的执行计划, 大幅减少用户查询的执行时间。 数据优化对用户透明, 优化前后不会出现读取的数据不一致的情况。 这也是数据湖的数据治理所不可或缺的功能。

之前介绍的 JindoTable 数据优化功能, 是在存储端减少额外开销, 并且通过提前的计算, 为运行时优化打好基础。 JindoTable 的查询加速功能则是在查询执行时, 通过把计算推向存储, 减少计算时整体的 IO 压力, 同时利用存储端空闲的计算资源提供高效的计算, 缩短整体查询时间。 JindoTable 的加速服务结合修改后的各种计算引擎, 可以把尽可能多的算子下推到缓存端, 并且利用高效的 native 计算能力过滤大量原始数据, 再把数据高效地传输给计算引擎。 这样, 计算引擎所需处理的数据大大减少, 甚至一些计算也可以直接略过, 后续的计算所需的时间自然也就大为减少。

阿里云云原生数据湖体系全解读——数据湖加速JindoFS 计算节点数据缓存_云原生_08


阿里云的对象存储服务 OSS, 为用户提供了低频存储和归档存储, 对于访问不是那么频繁的数据, 如果能够转为低频或归档模式来存储, 可以尽量节约成本。 而一部分数据如果有频繁的访问需求, 放在远离计算资源的对象存储上, 又会导致计算时的 IO 出现瓶颈。JindoTable 对接数据湖中各种计算引擎, 以表或分区为最小单位, 统计数据的访问频次。根据用户设定的规则, JindoTable 可以告诉用户哪些表或者分区的访问频次较高, 让用户可以通过 JindoTable 命令, 借助 JindoFS 提供的底层支持, 把这些表或者分区对应的数据缓存到计算集群内, 加速查询的执行。 同时, 对于访问频次较低的表或者分区, 用户也可以使用 JindoTable 把对应的数据转为低频或者归档存储类型, 或是设置生命周期。 在需要对归档数据操作的时候, 可以直接用 JindoTable 对归档数据进行解冻。 JindoTable还为用户提供了元数据管理, 方便用户检视表或者分区当前的存储状态。 JindoTable 让用户 能 尽 可 能 高 效 地 管 理 自 己 的 数 据 , 节 约 成 本 的 同 时 , 不 牺 牲 计 算 性 能 。