多云缓存在知乎的演进 (多云数据)

技术教程 2025-05-10 19:10:23 浏览
多云数据

多云缓存在知乎的演进

2023-06-27 07:20:45随着云原生技术的飞速发展,各大公有云厂商提供的云服务也变得越来越标准、可靠和易用。用户不仅可以在不同的云上低成本部署自己的业务,而且还可以享受到每个云厂商在特定技术领域上的优势服务,因此多云架构备受青睐。伴随着多云架构的广泛应用,缓存机制的设计对系统的性能影响至关重要,本次分享将结合知乎中缓存机制的设计演进,介绍多云缓存技术的应用。

一、多云缓存产生的背景

1、多云架构

知乎目前采用的是多云架构,主要基于以下三个方面的考虑:

知乎目前的数据中心有5-6个,核心的机房有两个。一个是在线机房,它部署直接面向知乎主站用户的服务,比如评论、回答和推荐等。另一个是离线机房,主要部署一些离线计算相关的服务,比如我们常见的数据平台、离线存储以及OLAP引擎等。这两个机房之间依靠机房专线进行通信,所以机房专线很重要。

衡量机房专线是否稳定的重要指标之一,就是机房的流量。一般情况下,服务之间的调用不会影响到机房专线流量,因为服务之间的调用使用的机房流量非常少。但是在我们的算法场景中,有一类非常特殊的情况,它会直接占满整个机房专线。这就是接下来要介绍的推荐/搜索模型上线场景。

2、推荐/搜索模型上线场景

我们模型的产出,依赖于离线机房的机器学习平台和Spark集群进行大规模的分布式计算,模型最后写入到离线HDFS。模型上线的时候,推理服务容器会有几百个容器,多的甚至有上千个容器,同时去拉取HDFS上面的模型,这样会产生比较大的跨专线流量,会带来两个问题:

3、多HDFS集群方案

早期我们解决这种模型上线问题的方案十分简单,就是多HDFS集群方案。相比于之前直接从离线HDFS拉取,我们在模型产出时,采用一个离线拷贝任务将模型拷贝到在线的HDFS,拉取的时候直接从在线HDFS读取模型。这样做有两个好处:

但是这种做法也存在一些不足:

接下来介绍我们迭代的第三个版本,就是我们的自研组件UnionStore。

1、自研组件——UnionStore

我们的多云缓存自研组件叫UnionStore。顾名思义,它是联合存储的意思,联合了HDFS和对象存储,对外提供对象存储的访问接口。其工作流程为:模型通过机器学习平台和spark产出,最后写入HDFS。读取的时候通过对象存储协议向UnionStore发出请求。UnionStore接收到读取文件请求后,会检查对象存储里面是否存在这个文件,如果存在就直接返回给用户,如果不存在就从离线HDFS进行读取,然后上传到对象存储,最后再从对象存储返回给用户。

2、UnionStore的优势

这是UnionStore的第一个使用场景。UnionStore提供了对象存储的访问方式,它其实还可以做一件事情,就是用户可以把UnionStore用s3fs-fuse挂载到POSIX本地目录上,读取训练数据的时候直接通过本地目录来读,从而为机器学习平台提供更好的帮助。

这个方案一上线就备受用户好评。当时HDFS挂载采用了两种方式,第一种是Hadoop社区提供的HDFS挂载本地目录的方式,另外一种是以go语言写的HDFS挂载方式。但是这两种方案的重试都做得不够好。s3fs-fuse的重试做得比较好,所以我们选择了s3fs-fuse这种方式。

3、UnionStore的不足

UnionStore在知乎内部运行了足足两年时间,早期没有出现任何问题,但是随着模型规模的不断扩大,逐渐出现了以下问题:

以上缺点使我们面临两个选择,第一个方案就是继续迭代UnionStore,使它能够满足我们内部的需求;第二个方案就是寻找一个合适的开源解决方案,替代UnionStore的使用场景。基于人力资源的宝贵,我们选择了第2个方案,找一个合适的开源解决方案。

开源方案需要解决两个使用场景,第一个是模型读取加速场景,它要提供一个对象存储协议;第二个是模型训练加速场景,它要提供本地目录的一种访问方式。

我们调研了很多开源解决方案,内部也有很多缓存组件,最后发现只有Alluxio能够满足我们的需求。Alluxio具有以下优势:

这三点就已经能够满足我们的需求了,但是它还提供了另外三个功能:

通过调研确定功能满足我们的需求以后,我们使用它进行了模型的上线。

1、模型读取加速场景

第一个场景,模型读取加速场景,接下来将从客户端的选择、性能测试、部署与调优,以及上线效果这四方面来进行介绍。

我们选择Alluxio S3 Proxy进行模型读取场景的加速,原因有以下几点:

我们对Alluxio S3 Proxy进行了一系列的性能测试,对比了HDFS、UnionStore以及Alluxio,发现Alluxio在热读文件的时候,其性能远超另外两个组件,100GB文件热读的时间只有UnionStore的1/7,这个加速效果是非常明显的。

部署时我们选择了裸金属机部署,为什么没有选择K8S部署,原因有以下几点:

这里我们的部署方式是S3 proxy,最后通过DNS代理域名,供用户的访问。

模型读取场景的调优,需要结合模型读取场景的特点来进行。模型读取场景有以下三个特点:

我们针对这三个特点进行了针对性的调优:

接下来详细说明各个调优策略。

左边的图是没有短路读的时候,用户在请求S3 Proxy读取文件的时候,会经过两层网络,第一层网络是用户到S3 Proxy,第二层网络是S3 Proxy到Worker,最后由Worker读取磁盘上的文件,这种情况下网卡的消耗非常大。

右边的图是短路读的情况,用户在请求了S3 Proxy以后,S3 Proxy会直接读取磁盘上的数据,无需经过Worker,这样相当于省下了S3 Proxy到Worker之间的流量。据我们线上的测试,大概能够节省30%到50%的流量。

文件实时预热策略,通俗的讲,就是把Distributed Load的功能做到了S3 Proxy里面去。S3 Proxy接受下载请求时,会将文件分块,把每一个文件块提交到不同的Worker进行并发缓存。这样做的好处在于,下载文件时,前面可能没缓存,下载得很慢,但是读到后面文件的时候,因为其他的Worker可能已经把文件缓存完了,所以能够达到跟命中缓存几乎一样的速度。这种加速策略是文件越大,效果越明显。在读取大文件的时候,比如文件有10GB,这时读的速度比冷读提升到2-5倍;如果是100GB,基本上和热读没有区别。

第二个好处是顺序靠后的文件块,因为已经提前缓存了,能够节省UFS的流量,据线上数据验证,能够节省2-3倍的UFS流量。

再来看一下实时预热策略的效果,下图是线上的真实截图,里面的每一条线段都代表模型读取的一个请求,线段越长代表读模型花费的时间越长,读取速度越慢。

阶段一是用UnionStore读取的效果,阶段二是直接上线S3 Proxy读取的效果。可以看到整体的读取耗时下降了大概一半,但是出现了一些尖刺,说明有些请求可能会读得特别慢,这是因为Alluxio在冷读文件的时候性能下降得十分明显。

阶段三是上线了实时预热策略后读取的效果,可以看到所有的尖刺基本上消失了,而且文件整体的读取速度也有所提升,预热的效果是非常好的。

第三个优化策略是做了一定的元数据缓存,分为三个阶段。上图也是线上的真实截图。阶段一是用UnionStore读取,速度非常慢;阶段二是直接上线S3 Proxy读取,可以看到时间降了一大截,速度几乎提升了一倍;阶段三是上线了一分钟的元数据缓存以后的情况,对比最开始UnionStore,速度提升了几十倍。

元数据缓存开启以后需要特别注意元数据同步,因为它可能会造成文件的不一致,所以我们也制定了一些文件的使用规范。比如新增文件,我们让用户尽量去写入新目录,以版本号的形式管理,尽量不要追加或覆盖旧文件。如果对于一些业务历史遗留的任务,实在需要对旧文件进行修改,我们也提供了一些比较特殊的方式。我们在S3 Proxy上改了一些代码,增加了特殊的命令,供用户来刷新元数据。

S3 Proxy限速的目的主要是为了保护Worker和业务容器,防止网卡打满。因为S3 Proxy的速度非常快,最高能够达到1.6GB的速度,对网卡的消耗非常大,所以要保护Worker的网卡和业务容器的网卡。这里我们做了两个限速,第一个是进行S3 Proxy进程的全局限速,这样可以保护Worker网卡。第二个是进行了单连接限速,保护业务所在容器的K8S节点,防止这个节点整体的网卡被打满。这个功能已经贡献给了社区,2.9.0以后的版本也都已经上线。

下图是模型读取加速的整体效果,可以看到速度提高了大概几十倍。当然这里的几十倍是因为我们的Alluxio集群是非常空闲的,真实的上线结果是UnionStore和Alluxio的速度一样,但是Alluxio用的资源只有UnionStore的一半,相当于是节省了50%的成本。

2、模型训练加速场景

第二个场景是模型训练加速场景,也从四个方面来介绍:客户端的选择、性能测试、部署与调优、上线效果。

客户端选择了Alluxio Fuse,原因有以下几点:

选择了客户端以后,我们对它进行性能测试。测试选用官方的默认配置,这里有两个跟官方默认配置不同的点,一个是开启了一定的内核元数据缓存,另一个是容器的总内存非常大,原因是我们想用内核元数据缓存。

我们以本地磁盘作为测试基准,测试的结果如下。本地磁盘的顺序读是1800 MB/S,随机读是1000 MB/S,fuse 1G实际文件顺序读的时候,达到了1700 MB/S的速度,基本达到本地磁盘90%的性能,这是非常高的性能了。fuse 100G文件顺序读的时候,性能急速下降,这是因为我们之前容器的内存是40GB,它没有充足的page cache来缓存100GB文件,而对于1GB和10GB的文件是有充足的缓存命中的,所以它的性能会降低一半。

fuse随机读的性能相对较差,只有450 MB/S,但也能满足我们的模型训练的需求,整体上符合预期。

模型训练场景的调优需要结合它的特点进行。模型训练场景也有3个特点:

我们采用DeamonSet的形式来部署fuse进程。我们用host path一层一层地挂载缓存数据的目录,然后提供给模型训练容器来使用。

接下来我们结合fuse,看一下整个Alluxio集群的部署方式。我们采取小集群重客户端的方式,顾名思义,Alluxio集群其实是非常小的,它只有3个支持Raft协议的master节点以及3个Worker节点,但是它支撑了上百台GPU机器,这里大概是100-300台GPU机器,包括几PB的NVME存储。有数百个fuse进程部署在GPU机器上。每个fuse进程都有10TB的NVME做本地缓存。这样相当于Alluxio集群其实只做了一件事情,就是数据的分发,其他的如性能保障之类的事情就完全交给fuse进程本地完成了。

最后是Alluxio的调优。它的调优项非常简单,我们仅做了少许改造,其他都是官方配置。

从实际加速效果来看,模型训练整体提速60%,本来需要训练10天的模型,现在只需要6天就可以训练完毕。另外,训练模型时读取数据的速度也提升了2.5倍。

3、补充场景

我们内部还有一个比较有意思的场景,就是大数据运维场景,这也是我们的补充场景。

(1)大数据组件发布与上线(优化前)

首先介绍一下我们大数据组件的发布与上线流程。比如上线一个大数据组件,用户开发者首先提交他的任务到GitLab,GitLab在收到合并代码请求以后,会调用CI的Web Hook,自动帮用户构建打包,然后把二进制包上传到Kosmos。这里的Kosmos是我们内部的包管理服务,Kosmos在收到二进制包后,会转存到对象存储,这是发布过程。

再看上线过程。开发者在大数据运维平台点击新版本上线,然后大数据运维平台会把部署逻辑分发到生产环境服务器。生产环境服务器运行部署逻辑,如果中途要下载包,它会请求Kosmos进行下载。Kosmos在接收下载请求以后,会将请求重定向到对象存储,这个时候生产环境服务器直接从对象存储拉取二进制包,整个流程是非常完美的。唯一的瑕疵出现在对象存储下载二进制包的时候,它会有以下两个问题:

(2)大数据组件发布与上线(优化后)

我们用Alluxio对这个流程进行了一些优化,过程很简单。我们把Kosmos用的对象存储直接挂载到Alluxio上,因为Alluxio不仅支持HDFS的挂载,还支持对象存储的挂载。生产环境服务器在下载包的时候,会直接向S3 Proxy请求二进制包。由于是在Alluxio下载的,它的速度非常快,如下图所示,这是一个对比图,展示了最后上线后的效果。

图中的红圈是从对象存储下载的速度,大概是十几MB/S,从Alluxio下载大概是600 MB/S。这里的600 MB/S,是压制下的情况,考虑到前述提及的优化方案,即S3 Proxy进行限速,我们限速为600 MB/S,它其实最高能够达到1600 MB/S。

最后进行一个技术总结。回顾我们多云缓存的发展历程,从最开始的暴力读取,到后来的多HDFS集群,再到自研组件UnionStore,都不能满足我们的需求。最后我们上线了Alluxio,才满足需求。

Alluxio为我们带来了哪些提升?首先是性能方面,整体上有2-5倍的性能提升。另外是稳定性方面,它解除了HDFS的强依赖。最后是成本方面,它为我们节省了大约一半的成本。

未来我们计划在数据编排领域以及OLAP加速的场景来使用Alluxio。因为我们有一些人工智能的场景需要用到小文件,所以我们比较期待它的新一代架构,Dora架构。

1.Hive使用Alluxio怎么让用户历史创建Hive表尽量少的改动?

答:这个问题我猜可能是不想改Hive表的location,不想让它从HDFS的开头改成Alluxio开头。我们现在还没做OLAP引擎的加速,但是我们目前有一个备选的方案。我们可能会对Hive的MetaStore做一些改造,在计算引擎读取HDFS上面的分区时,如果已经缓存到Alluxio,我们会直接在Hive MetaStore内进行修改,然后把HDFS前缀直接修改成Alluxio前缀。这样就不用改Hive的location。

多云缓存在知乎的演进

2.刚刚提到那个页的大小,调优从1MB变成了16MB,这是怎么调出来的?为什么不是32MB?

答:业务读取数据的时候,它不仅有大文件,也有小文件,如果这个值太大的话,对小文件支持不好,太小的话又对大文件支持不好。所以我们根据实验经验,选了一个相对折中的值。

3.Alluxio在冷读的时候性能下降得比较明显,然后通过预热的方式来解决这个问题。请问是怎么做预热的?

答:比如我们现在有一个用户向S3 Proxy请求512 MB的文件,然后S3 Proxy从master拉取到这个文件的元信息,可以看到它有四个块,每个块是128 MB大小。对这四个块,我们会通过一个特殊的算法,可以是哈希也可以是别的,分别打到不同的worker进行缓存。S3 Proxy在读取的时候可能会先下载,比如说下载块1,但块1可能还没缓存,所以它是直接从UFS读取再返回给用户,可能会很慢。在读块2的时候,它可能已经被缓存完了,这种情况下读取是非常快的。然后在读块3、块4的时候可能也都缓存完了,也读取的很快。我们是这样来做的。这里要求文件的 block数要大于1,否则就没有必要去进行加速,因为文件本身比较小,就算性能差,它也能很快地读完。

4.刚刚提到利用Alluxio做元数据缓存,元数据到底里面有哪些东西?

答:元数据缓存在Alluxio里面分为三块,第一块是UFS的元数据,比如对象存储的元数据,它会在master里面进行缓存。第二块是fuse,就是客户端本地的元数据缓存。这个比较常见,fuse会用内存来缓存一次master的元数据。第三块是内核元数据,这个也是fuse里面比较常见的,它是操作系统层面的缓存,缓存操作系统本地的目录情况。

元数据缓存对性能有很大的影响。不开启元数据缓存的时候,比如我们不缓存UFS的元数据,那么客户端的每一次请求都会穿透到UFS上面去,性能会非常差。特别是在对象存储的时候,比如要list一个目录,对象存储list目录的性能是非常差的,有时候可能要花好几秒。

多云缓存在知乎的演进 我们这里设置了1分钟的缓存超时时间。1分钟的元数据缓存其实也是一个折中的做法,就是要尽可能的让用户很快地感受到他的文件有变更,同时也要做一定程度的缓存。如果对元数据一致性要求不是那么的严格的话,其实也可以调成1小时、几小时或者几天都行,或者手动刷新都可以。这个只能根据场景来调优。

5.模型上线和模型训练场景里边都有对象存储,它具体是用的云上的对象存储,还是本地的对象存储?它的连接接口都是用标准S3协议连接的吗?

答:我们直接买的云厂商的对象存储服务。因为自己搞一套对象存储,这个成本太高了。

这里涉及到两种S3协议。一方面UnionStore本身对外提供S3协议,这个组件是我们自研的;另一方面UnionStore利用S3协议与对象存储交互,对象存储是从云厂商买的。

6.模型训练场景中,GPU集群刚开始是几百个节点,但是Alluxio用的是一个小集群的部署,3个master加3个worker的部署,这个小集群架构能满足整个热数据的拉取容量以及并发访问需求吗?

答:这个需要结合Alluxio自己目前有的一个问题来解决。目前fuse从集群读数据的时候是非常慢的,这是Alluxio的一个缺陷,它最高只能达到200MB/S左右的速度,所以其实它怎么读也读不满Worker的网卡。这个我们已经和Alluxio社区沟通过好多次了,Alluxio下一个版本会解决掉这个问题,我们也非常期待,到时我们可能也会做一些版本升级和架构升级,比如会把Worker扩一下,或者把Worker直接和业务部到一起。


鄄城到青岛的火车票多少钱?

5028/5025 详情 鄄城 – 青岛 21:51 06:48(第2天) 8小时57分钟 普快45 2010年08月15日 01:50 更新

沙特北部气温

沙特近一周气温02月25日 (今天)白天:晴夜间:晴12~24℃ 东北风 3级02月26日 (周五)白天:小雨夜间:小雨12~26℃ 东北风 2级02月27日 (周六)白天:多云夜间:多云16~25℃ 东南风 3级02月28日 (周日)白天:多云夜间:多云17~28℃ 东南风 3级02月29日 (周一)白天:晴夜间:晴16~29℃ 东南风 3级03月01日 (周二)白天:晴夜间:晴14~25℃ 北风 3级03月02日 (周三)白天:晴夜间:晴15~25℃ 西北风 3级沙特阿拉伯西部高原属地中海气候,其他地区属热带沙漠气候。 夏季炎热干燥,最高气温可达50℃以上;冬季气候温和。 年平均降雨不超过200毫米。

4月15号准备去深圳,请问这个季节在那边穿什么服装比较合适?

中午穿半袖, 晚上要有一件薄外套, 单裤单鞋即可周末会有阵雨, 要带伞, 最好有一件薄的毛外套4月15日 21-29℃, 多云, 微风4月16日, 19-28℃, 多云, 微风4月17日, 18-26℃, 阵雨, 微风4月18日, 24℃, 阵雨, 微风

本文版权声明本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,请联系本站客服,一经查实,本站将立刻删除。

发表评论

热门推荐