导读: 随着大数据技术的进步,各种计算框架的涌现,数据仓库相关技术难题已经从离线数仓逐渐过渡到实时数仓,越来越多的企业对数据的实时性提出了严格的要求,如何满足企业的低延时的数据需求,如何看待批量处理和实时处理的关系,实时数仓应该如何分级,各家可能都有自己的理解,本文主要介绍网易的实时计算平台的建设实践以及网易对于实时数仓方面的一些规划及展望,希望能够起到抛砖引玉的作用。
01 实时计算平台实践
1. 网易实时计算平台:Sloth
网易的实时计算平台 Sloth 译成中文是树懒的意思,继承了网易喜欢用动物系命名大数据组件的风格,如果你看过《疯狂动物城》,一定会对剧中的 flash 印象深刻。Sloth 平台的建设始于 2017 年 12 月份,至今已有 3 年的时间,期间平台的弹性计算单元(ECU)规模一直呈现指数级增长,目前 ECU 已经突破 50000 个,运行的 CPU 数量已经达到 15110 核,内存超过了 34T。
2. 平台架构
从功能的角度来看,Sloth 平台主要分成两大块:
Admin:主要负责一些异步的服务,比如说任务的监控,告警,恢复和诊断。
Server:主要完成一些应用层面的服务,同时它也是一个无状态的PAAS服务,既面向我们web的终端用户,也面向大数据平台内部的其他模块。从功能上来看,它负责资源的管理,任务的开发及运维,同步事件的管理等任务。
从数据层面来看,我们实时数仓的架构主要分为四个层面:
① Source 层
关系型数据:NDC 是公司专门处理关系型数据的组件,它会将 mysql 等关系型数据库的 binlog 日志解析成特殊的数据格式然后插入到我们的 kafka 消息队列。
日志型数据:datastream 是公司的专门负责日志收集的平台,它会将收集的日志信息插入到我们的消息队列。
② 消息队列
目前我们选用的是 kafka。
③ 计算层
目前我们选用的是 flink 来完成数据的清洗,转换及聚合。
④ Sink 层
kudu 是我们主推的存储格式,kudu 不仅可以提供一个高效的用于数据分析的列存格式,同时也支持数据实时的 upsert 及 delete。当体量比较小的时候,也可以选用 mysql 或者 redis 这种可以实时变更的存储组件。
3. 一站式实时计算开发 IDE
我们主推的开发模式是 sql 模式,同时我们也支持 jar 包模式。
我们提供高度集成的 IDE,支持代码的离线调试,线上调试,版本管理,版本比对及配置管理。
4. 一站式实时任务运维
运维我们主要分为三大版块,分别是任务的运维,服务器监控及异常告警,下面我们分别看一下:
① 任务的运维
我们提供丰富的界面和菜单来支持任务的运维工作,通过页面的菜单点击我们可以轻松的查看任务信息,运行时的参数,高级的配置,运行记录,操作记录及运行日志。
② 服务器压力的监控
我们在 grafana 的基础上进行了二次开发,图形化的展示平台的吞吐量,延迟,IO,QPS 等关键信息。
③ 告警的设置
在 Sloth 平台设置告警非常简单,你可以在界面上配置多个规则,比如说任务失败次数,数据延迟超多少阀值,报警间隔,告警的接收人,发送方式等。
5. 统一元数据中心
无论是离线数仓还是实时数仓,都需要做好元数据的管理工作,Sloth 平台也有统一的元数据中心,下面简单介绍一下我们的元数据管理方式,元数据登记以及统一元数据所带来的好处。
元数据管理:
Hive metastore 元数据管理体系是业界公认的标准,包括 flink 在 1.10 版本之后也开始打造自己的 catalog 机制,网易也遵循了这套逻辑,将数据统一分成了 instance-> database -> table 的层级。
数据源登记:
对于关系型数据库,本身就有schema信息,比如说mysql本身就有schema,database和table的概念,那么我们只需要把mysql登记进来,赋予一个instance_name,那么以后就可以通过instance_name.database.table 的方式来访问。
对于NOSQL类的数据源,有些数据源没有database的概念,比如说hbase,我们可以指定一个default的database。
对于消息队列,本身没有元数据,平台本身提供一个default的catalog可以直接使用,同时用户需要自定义database和table。
统一元数据所带来的好处:
简化了开发流程,节省了代码量,规避了先定义DDL然后在定义DML的开发流程
一次登记,多处复用
允许字段发生变更,通过set设置属性,可以实现相同的元数据在不同的任务中具有一定的多样性
6. 其他工作
混合部署,开展基于yarn和k8s的混合部署实践,改善资源利用率
上游整合:对上游的数据库,只需要对数据库地址做一次性登记,就可以将数据库的表作为批表和流表source和flink实现无缝接合。省去用户在不同系统之间的跳转
自动伸缩:根据业务流量,数据量自动调整内存和并发度,以适配业务流量的峰谷模型。
增强诊断功能,提升运维效率,减小运维压力
02 实时数仓规划与展望
1. 现状及痛点分析
下面我们以一个百度热词统计案例来分析一下流式处理与批量处理的成本消耗及网易目前遇到的一个存储痛点。
① 流式处理与批量处理
熟悉大数据的人都知道统计百度热词的过程相当于一个 wordcount + topn 操作,这个任务既可以用 spark 跑批模式实现,也可以用 flink 流式计算实现,下面我们来分析一下跑批模式和流式计算模式完成这个统计的消耗情况。
跑批模式:
流式计算模式:
结果对比:
② Kudu 痛点
目前市面上的支持实时读写的大数据存储基本上采用的都是 PDT tree 或者 LSM tree 这种数据结构,这种数据结构主要采用的是写优化策略,首先数据会有一个基线版本,当对数据进行修改时,不会立即修改基线版本的数据,而是写入一个新版本的数据,这种写入是采用 append 的模式实现的,所以写延迟非常低,那么读取的时候我们就需要合并多个版本的数据返回最新版本的数据,它的读延迟就会比较高。所以为了照顾到读延迟问题,隔一段时间就需要执行一次合并版本的操作形成一个新的基线版本,这个过程叫 compaction。这种机制会带来一个问题,就是当一秒钟之内发生大量的修改时,这时数据就会有很多个版本,compaction 的过程就会带来大量的 cpu 和内存消耗,这个问题我们称之为写放大问题。
因为 compaction 的存在,kudu 成了一个存算不分离的存储系统,它需要去综合考虑写延迟,读延迟和 compaction 的性能,虽然他可以实时 upsert 或者 delete,但是极端情况下它会遇到写放大的问题,而且网易线上也确实经历过这样的事故。
③ 实时规模与成本的负相关
根据前面的分析,我们得到了一个结论:
批计算的成本和数据体量是呈现线性关系的,因为数据体量大的情况下,由于是顺序IO,我们只需要增加机器就可以解决。
而流计算的成本却随着数据体量的增长呈现指数级增长,原因是流式计算过程中会遇到随机IO的问题,流式计算框架的checkpoint的瓶颈,存储组件的写放大问题,存算不分离的问题,以及小文件问题等等。
2. 展望:流批一体的配套存储
基于之前的提出的这些问题,我们展望一下如何实现一个流批一体的配套存储:
首先,我们需要实现存算分离,核心思路是:
把kudu的compaction操作从存储端剥离出来。
把compaction操作交给外部的定时调度来完成,比如说我们正在做的arctic服务,提供分钟级甚至是小时级的调度,牺牲掉一部分的实时性,但是提高了服务的稳定性。拿百度热词这个例子,我们可以看出热词每秒钟都在更新,但是我们没有必要每秒钟更新一下数据,我一分钟更新一下数据完全是可以的。
对于一些数据准确性特别高的,我们应该提供一种同步的compaction机制,在读取数据的时候执行,比如说用flink读取数据的时候执行compaction后再返回,这种情况我们称之为merge on read。
同时也可以提供一个异步的compaction机制,这种情况下,你读取的时候,读取到的是上一次compaction执行完成之后的结果,这种情况我们称之为copy on write。
其次,我们应该提供一个流批一体的 API:
批量读取的 api 其实很好解决,我们的 hdfs 上的存储结构像 parquet,kudu 本身就是可以批量读取的,那么什么是流式读取的 api 呢?试想一下我们的消息队列,像 kafka 提供了一个时间戳,我可以随时回到这个时间戳对应的偏移,然后消费之后的数据,所以我们的想法是只要我们给定一个起始时间就能增量的读取某个时间点之后的数据就可以了,这个也类似 mysql 的 binlog。
无论是批量的读取还是流式的读取,它们的存储应该是同一套。
3. 数仓分级
我认为数仓可以根据实时性的要求分成不同的等级:
毫秒-秒级:实时性要求最高的等级,没有调度延迟,我们把这种场景比喻成私家车,这种情况下,道路治理是最关键的,要避免堵车,结合我们的实时计算来讲的话,私家车就是一个单独的事件,处理过程中要防止产生数据堆积,该级别更加注重端到端的情况,通常是一个特定的任务或者路线。
分钟级:实时性高,有一定的调度延迟,我们把这种场景比喻成地铁,吞吐量比私家车交通要更高,是一种小批量运输,地铁交通注重的是换乘和复用,注重优化线路和站点,就和我们的workflow比较类似。
小时-天级:实时性要求低,调度延迟高,我们把这种场景比喻成高铁,吞吐量大,执行速度最快的交通工具,你准备数据的时间可能超过真正执行的时间,这种就是我们传统的离线数仓的模式。
最后概括一下,如果把数仓比喻成交通的话,实时数仓就好比是城市交通,离线数仓就好比是城际交通。
4. 实时数仓 trade off
在构建实时数仓时,我们通常需要考虑三个重要的环节:
实时性,这个需要根据业务来确定延迟的等级,是秒级呢?还是分钟级?
可用性,因为越高的实时性意味着对可用性的要求越高,对异常恢复的时间要求更短,比如说百度词条的案例,你的实时性要求如果是分钟级的,那么你发生故障了,一分钟内恢复不会产生太大的问题,但是如果是秒级的话,一分钟可能就会酿成事故。同时低延迟的这种随机IO更容易造成文件碎片化的问题,所以我们需要对小文件进行一个治理;在可用性方面,缓冲能力也尤为重要,我们的系统总会出现一定的峰值,比如说双十一0点的时候,流量可能是一年的峰值,但是出于成本考虑,我们不可能根据峰值无限的扩容,因此我们要具备很强大的消息缓冲能力。
成本,实时计算的成本与数据体量是呈指数级增长的,其中一个主要的原因就是写放大问题,为了解决写放大问题,我们展望了一个存算分离的存储体系,降低compaction的频率,并提供流批一体的API来提升效能。
03 总结
本文主要讲述了网易的实时数仓的产品形态,并结合实际的案例分析了网易实时数仓目前面临的难点,一方面剖析了批计算与流计算各自的消耗情况,一方面剖析了现有存储体系的存算不分离问题,从而得出流计算的成本随数据体量呈指数级增长的结论,紧接着我们提出了一种存算分离且批流一体的存储架构,通过剥离 compaction,把 compaction 交给外部服务或者计算框架来实现存算分离,以及提供统一的 API 来同时支持批计算和流计算,最后我们浅谈了数据仓库的等级划分以及建设实时数仓时需要考量的三个重要环节。
今天的分享就到这里,谢谢大家。
作者介绍:
马进,网易杭研技术专家
马进,网易杭研技术专家、网易流计算团队负责人。负责网易数据库中间件、数仓团队,主导数据库中间件的各类项目研发,曾先后参与分布式数据库 DDB,缓存 NKV,分布式事务协调器 TCC,数据运河 NDC 等项目。专注于分布式系统架构与数据库技术,热衷于构建高效的,高性能的分布式后台系统。
本文来自 DataFunTalk
原文链接:
评论