写点什么

作业帮检索服务基于 Fluid 的计算存储分离实践

  • 2021 年 11 月 29 日
  • 本文字数:3435 字

    阅读完需:约 11 分钟

作业帮检索服务基于Fluid的计算存储分离实践

大规模检索系统一直都是各个公司平台业务的底层基石,往往是以千台裸金属服务器级别的超大规模集群的方式运行,数据量巨大,对于性能、吞吐、稳定性要求极为苛刻,故障容忍度很低。


除了运行层面外,超大规模集群和海量数据场景下的数据迭代和服务治理也往往是一个巨大的挑战:增量和全量的数据分发效率,短期和长期的热点数据追踪等都是需要深入研究的问题。


本文将介绍作业帮内部设计实现的基于 fluid 计算存储分离架构,能够显著降低大规模检索系统类服务的复杂度,使得大规模检索系统可以像正常在线业务一样平滑管理。

大规模检索系统所面临的问题


作业帮的众多学习资料智能分析和搜索功能中都依赖于大规模数据检索系统,我们的集群规模在千台以上,总数据量在百 TB 级别以上,整个系统由若干分片组成,每个分片由若干服务器加载相同的数据集,运行层面上我们要求性能达到 P99 1.Xms,吞吐量高峰百 GB 级,稳定性要求 99.999%以上。



以往环境中为了提高数据读取效率和稳定性,更多的在考虑数据本地化存储,我们的检索系统每日产生索引项并需要进行 TB 级别的数据更新,这些数据通过离线建库服务产出之后,需要分别更新到对应的分片中,这种模式下带来了许多其他挑战,比较关键的问题集中在数据迭代和扩展性上:


1、数据集合的离散:


由于实际运行中,每个分片的每个节点都需要复制下来本分片所有数据,由此带来了同步数据下发困难的问题。实际运行中如果要同步数据到单服务器节点,需要使用分级下发,先下发一级(十级)由一级分发给二级(百级)再分发给三级(千级),这个分发周期长且需要层层校验来保证数据准确性。


2、业务资源弹性扩缩较弱:


原先的系统架构采用的是计算和存储紧耦合,数据存储和算力资源紧密捆绑,资源灵活扩展能力不高,扩容往往需要以小时为单位进行,缺乏应对突发峰值流量扩容能力。


3、单分片数据扩展性不足:


单分片数据上限受分片集群内的单机存储上限限制。如果达到存储上限,往往需要拆分数据集,而这种拆分不是由业务需求驱动的。


而数据迭代和扩展性的问题又不得不带来了成本压力和自动化流程上的薄弱。


通过对检索系统运行和数据更新流程的分析,当前面临的关键问题是由于计算和存储的耦合所带来的,因此我们考虑如何去解耦计算和存储,只有引入计算存储分离的架构才能够从根本上解决复杂度的问题。


计算存储分离最主要的就是将每个节点存储本分片全量数据的方式拆分开,将分片内的数据存储在逻辑上的远程机器上 但是计算存储分离又带来了其他的问题,比如稳定性问题,大数据量下的读取方式和读取速度,对业务的入侵程度等等问题,虽然存在这些问题,但是这些问题都是可解决以及易解决的 基于此我们确认计算存储分离一定是该场景下的良方,可以从根本上解决系统复杂度的问题。

计算存储分离架构解决复杂度问题


为了解决上述计算存储分离所需要考虑的问题,新的计算存储分离架构必须能达到以下目标:


1、读取的稳定性,计算存储分离终究是通过各种组件配合替换掉了原始文件读取,数据加载方式可以替换,但是数据读取的稳定性依然需要和原始保持同等水平。


2、每个分片千节点同时数据更新场景下,需要最大限度的提升读取速度,同时对网络的压力需要控制在一定程度内。


3、支持通过 POSIX 接口读取数据,POSIX 是最具备对各种业务场景的适应性的方式,这样无需侵入业务场景下,屏蔽了下游变动对上游的影响。


4、数据迭代的流程的可控性,对于在线业务来说,数据的迭代理应被视为和服务迭代等同的 cd 流程,那么数据迭代的可控性就及其重要,因为本身就是 cd 流程的一部分。


5、数据集合的可伸缩性,新的架构需要是一套可复制,易扩展的模式,这样才能面对数据集合的伸缩、集群规模的伸缩具备良好的应对能力。


为了达成上述目标,我们最终选用了 Fluid 开源项目作为整个新架构的关键纽带。

组件介绍


Fluid 是一个开源的 Kubernetes 原生的分布式数据集编排和加速引擎,主要服务于云原生场景下的数据密集型应用,例如大数据应用、AI 应用等。


通过 Kubernetes 服务提供的数据层抽象,可以让数据像流体一样在诸如 HDFS、OSS、Ceph 等存储源和 Kubernetes 上层云原生应用计算之间灵活高效地移动、复制、驱逐、转换和管理。


而具体数据操作对用户透明,用户不必再担心访问远端数据的效率、管理数据源的便捷性,以及如何帮助 Kuberntes 做出运维调度决策等问题。用户只需以最自然的 Kubernetes 原生数据卷方式直接访问抽象出来的数据,剩余任务和底层细节全部交给 Fluid 处理。


Fluid 项目当前主要关注数据集编排和应用编排这两个重要场景。数据集编排可以将指定数据集的数据缓存到指定特性的 Kubernetes 节点,而应用编排将指定该应用调度到可以或已经存储了指定数据集的节点上。这两者还可以组合形成协同编排场景,即协同考虑数据集和应用需求进行节点资源调度。



我们选择使用 fluid 的原因


1、检索服务已经完成容器化改造,天然适合 fluid。


2、Fluid 作为数据编排系统,使得上层无需知道具体的数据分布就可以直接使用,同时基于数据的感知调度能力,可以实现业务的就近调度,加速数据访问性能。


3、Fluid 实现了 pvc 接口,使得业务 pod 可以无感知的挂载进入 pod 内部,让 pod 内可以像使用本地磁盘一样无感知 Fluid 提供元数据和数据分布式分层缓存,以及高效文件检索功能。


4、Fluid+jindoruntime 内置了多种缓存模式(回源模式,全缓存模式),不同的缓存策略(针对小文件场景的优化等)和存储方式(磁盘,内存),对于不同的场景具备良好的适应性,无需太多修改即可满足多种业务场景。

落地实践


1、缓存节点和计算节点的分离: 虽然使用 fuse 和 worker 结合部署可以获得更好的数据本地性能,但是在在线场景下,我们最终选用了缓存和计算节点分离的方案,原因是通过延长一定的启动时间换来更优的弹性是值得的,以及我们并不希望业务节点稳定性问题和缓存节点的稳定性问题纠缠在一起。


2、Fluid 支持 dataset 的可调度性,换言之就是缓存节点的可调度性,我们通过指定 dataset 的 nodeAffinity 来进行数据集缓存节点的调度,从而保证缓存节点可高效,弹性化的提供缓存服务。


  • 在线场景的高要求:


对于在线业务场景,鉴于系统对于数据的访问速度、完整性和一致性有较高的要求,因此不能出现数据的部分更新、非预期的回源请求等; 所以对数据缓存和更新策略的选择就会很关键。


  • 合适的数据缓存策略:


基于以上需求,我们选择使用 Fluid 的全缓存模式。在全缓存模式下,所有请求只会走缓存,而不在回源到数据源,这样就避免了非预期的长耗时请求。同时 dataload 的过程则由数据更新流程来把控,更安全和标准化。


  • 结合权限流的更新流程:


在线业务的数据更新也是属于 cd 的一种,同样也需要更新流程来管控,通过结合了权限流程的 dataload 模式,使得线上数据发版更安全和标准化


  • 数据更新的原子性:


由于模型是由许多文件组成,只有所有的文件全部缓存起来之后,才是一份可以被使用的完整的模型;所以在全缓存无回源的前提下,就需要保证 dataload 过程的原子性, 在数据加载的过程中过,新版本数据不能被访问到,只有在数据加载完成之后,才可以读取到新版本数据。


以上方案和策略配合我们自动化的建库和数据版本管理功能,大大提高了整体系统的安全性和稳定性,同时使得整个过程的流转更加智能和自动化。



总结


基于 Fluid 的计算存储分离架构,我们成功地实现了:


1、分钟级百 T 级别的数据分发。


2、数据版本管理和数据更新的原子性,使得数据分发和更新成为一种可管控,更智能的自动化流程。


3、检索服务能够像正常无状态服务一样,从而能够轻松通过 k8s HPA 实现横向扩展,更快捷的扩缩带来了更高的稳定性和可用性。


展望


计算和存储分离的模式使得以往我们认为非常特殊的服务可以被无状态化,可以像正常服务一样被纳入 devops 体系中,而基于 Fluid 的数据编排和加速系统,则是实践计算和存储分离的一个切口,除了用于检索系统外,我们也在探索基于 Fluid 的 OCR 系统模型训练和分发的模式。


在未来工作方面,我们计划继续基于 Fluid 优化上层作业的调度策略和执行模式,并进一步扩展模型训练和分发,提高整体训练速度和资源的利用率,另一方面也帮助社区不断演进其可观测性和高可用等,帮助到更多的开发者。


作者介绍


董晓聪,作业帮基础架构负责人,主要负责架构研发、运维、DBA、安全等工作。曾在百度、滴滴等公司负责架构和技术管理工作,擅长业务中台、技术中台、研发中台的搭建和迭代。


张浩然,2019 年加入作业帮,作业帮基础架构-高级架构师,在作业帮期间,推动了作业帮云原生架构演进、负责多云 k8s 集群建设、k8s 组件研发、linux 内核优化调优、底层服务容器化相关工作。

2021 年 11 月 29 日 14:351387
用户头像
刘燕 InfoQ记者

发布了 759 篇内容, 共 247.2 次阅读, 收获喜欢 1448 次。

关注

评论

发布
暂无评论
发现更多内容

一文带你读懂数字管家

HarmonyOS开发者社区

HarmonyOS OpenHarmony

Java中抽象类和接口的区别

编程江湖

JAVA开发 java编程

【活动报名】Apache ShardingSphere Dev Meetup 重启!

SphereEx

开源项目 开源社区 ShardingSphere Meetup SphereEx

面试官:Java 线程如何启动的?

华为云开发者社区

Java 线程 JVM 时序图 Java 线程

你该不会拿 CSAPP 垫显示器吧

Zilliz

老铁久等了,尚硅谷Vue大型电商项目:尚品汇教程发布!

编程江湖

Vue 大前端

大数据中不同文件格式的比较

DisonTangor

大数据 云存储

技术驱动未来,保险极客凭借数字团险领跑

科技热闻

大数据开发开源平台之Spark SQL的基础

飞不起来的童年

大数据 spark SQL

前端开发面试之框架react的相关问题及答案

飞不起来的童年

大前端 React

12.7直播预告|「淼懂·观测云实践学堂」全新栏目上线!带你走进观测云的精彩世界!

观测云

可观测性 直播 可观测

看FusionInsight Spark如何支持JDBCServer的多实例特性

华为云开发者社区

大数据 SQL语句 FusionInsight Spark JDBCServer 多实例

Android技术分享| ViewPager2离屏加载,实现抖音上下视频滑动

anyRTC开发者

android 音视频 移动开发 ViewPager 视频滑动

模块5-课后作业

21°Char

技术管理哲学随笔:面对大量事业部需求与产研团队资源之间的矛盾

dclar

团队管理 管理 CTO

Flink CDC 系列 - 构建 MySQL 和 Postgres 上的 Streaming ETL

Apache Flink

大数据 flink 编程 后端 实时计算

你知道什么时候用Vue计算属性吗?

华为云开发者社区

Vue 字符串 逻辑 模板 计算属性

对象存储手把手教七 | 存储空间授权策略 Bucket Policy

QingStor分布式存储

分布式系统 对象存储 分布式存储 分布式,

使用 HTML、CSS、JavaScript 创建一个简单的井字游戏

海拥(haiyong.site)

大前端 js 28天写作 签约计划第二季 12 月日更

全程干货,用 python 下载某站全部【免抠图片】,图片背景透明,格式PNG

梦想橡皮擦

12月日更

如何在 ShardingSphere 中开发自己的 DistSQL

SphereEx

Java 数据库 ShardingSphere database SphereEx

Flink 是如何统一批流引擎的

编程江湖

大数据 flink

Linux学习方法《Linux一学就会》Linux系统进程管理

侠盗安全

Linux linux运维 运维工程师 云计算架构师

AI 收藏夹 Vol.003:AI 能听懂阴阳怪气吗?

Zilliz

神经网络 AI 计算机视觉

Groovy热更新Java实践

FunTester

Java 测试开发 热更新 Groovy FunTester

实战篇:Security+JWT组合拳 | 附源码

阿Q说代码

spring security JWT 签约计划第二季 权限验证

Rust 元宇宙 10 —— 接入和协议

Miracle

rust 元宇宙

【Pandas学习笔记02】-数据处理高阶用法

恒生LIGHT云社区

Python 数据分析 pandas 数据可视化

华为云企业级Redis评测第一期:稳定性与扩容表现

华为云开发者社区

redis 测评 GaussDB(for Redis) NoSQL数据库 企业级Redis

如何在 Vue 中使用 防抖 和 节流

编程江湖

尚硅谷Vue大型电商项目:尚品汇教程发布!

飞不起来的童年

Vue 大前端

ShadowRealm 与微前端沙箱

ShadowRealm 与微前端沙箱

作业帮检索服务基于Fluid的计算存储分离实践-InfoQ