滴滴自成立以来,有海量的数据存储在离线平台,离线数据虽然存储便宜,压缩比高,但不适用于线上使用。为此,我们提供了一键式 DTS 平台——FastLoad,帮助业务往在线存储系统搬运离线数据,目前主要针对滴滴自研分布式存储 Fusion,Fusion 以 RocksDB 为存储引擎,服务线上集群 500+,承载业务数据 1600TB+,总 QPS 峰值 1200W+,是一个成熟稳定的分布式 NoSQL/NewSQL 解决方案。
FastLoad 致力于离线数据在线化,服务业务 300+,单日运行次数 1000+,在线搬运 30TB+的数据,提供数百亿次高效查询,服务稳定性达到 99.99%。
业务背景——雄关漫道真如铁
在没有 FastLoad 以前,业务一般都会自己维护读离线数据,写在线存储引擎的业务逻辑。比如,滴滴有两个重要的业务:标签平台和特征平台。标签平台是指对每个乘客和司机,都打上 N 个标签,然后后续的打车流程会依赖这部分标签,比如优惠券的发放;特征平台,会收集创建各类特征,对每个对象用某个特征库做一次判断,即可确定某种行为。两个业务都需要定时更新在线数据、线上使用最新数据,下面我们对需求进行提取:
定时更新。像特征数据,一般需要小时级别甚至天级别的更新,所以业务需要有快捷的定时更新功能。
快速更新。特征数据还有一个特点,就是数据量特别大,以乘客特征为例,动辄上亿条数据,约 TB 级别数据量。这么大的数据量通过 SDK 写入肯定是不行的。刚开始业务方也确实是这么玩的,直接通过 Hadoop 任务调用 Redis SDK,然后一条条的写入 Fusion,一般是每天凌晨开始写数据,等到早高峰 8 点时大量读取。但是这种方法实践下来,经常导致 Fusion 各类超时,在早高峰打车已经来临时还在写凌晨的数据,非常影响稳定性。因此第 3 个需求是必须快速更新。
稳定性。这个是毋容置疑的。
多表隔离。有些业务有很多类特征数据,他们有隔离存储的需求,也有分类更新、分类查找的需求,因此需要多表来支持逻辑到物理的隔离。
下面我们看下用户正常写存储的流程,如图展示了以 RocksDB 为引擎的存储的写入过程。
正常灌库流程
如图,从 Hive 写到最终存储的链路比较长,数据要经过几次中转才能最终落盘。我们做一个公式换算,1TB 的数据,以 5w 的 QPS 写入存储,每个请求写 512B,需要大约 12 个小时,也就是半天的时间才能将数据完全写入。要是每天更新的任务,在早高峰之前根本不能取到最新的数据,是不满足业务场景的。
为了满足上述提及的 4 点需求,我们需要转换思维,不能拘泥于传统的数据灌入方式。我们萌生了一个快速导入的想法,如果将文件直接拷贝到存储中,就可以避免上图中的 1/2/3/4,直接对外开放读。
技术探讨——工欲善其事必先利其器
Ingest SST
我们需要以文件方式导入到存储引擎中,借助了 RocksDB 提供的 IngestFile 接口,通过用户预先创建好的 SST 文件,直接加载到硬盘的 LSM 结构中,已达到快速导入的目的。直接构造 SST 文件并导入的方式,绕开了上图正常灌库的流程,避免了写 WAL 日志、写内存、刷盘等操作,同时 RocksDB 的 Ingest 能够尽可能地将数据放在 LSM 结构中最底层的位置,减少 L0 到 Ln 层不断 Compact 带来的写放大。
Ingest SST 文件
Ingest SST 文件流程为:
检查需要导入的 SST 是否合法,包括文件之间 Key 值是否有重叠,文件是否为空,ColumnFamilyID 是否合法等等。
阻塞 DB 实例的写入操作,对可能与 Ingest 文件有重叠的 MemTable 进行刷盘操作。阻止 RocksDB 执行新的 Compact 任务导致 LSM 结构更新。
确定 Ingest 的文件应该在磁盘 LSM 结构中的哪一层,RocksDB 会尽可能地将文件放在 Key 值不重叠的最底层。如上图所示,Key 值范围为[E, F]的 SST 文件将 Ingest 导入到了 L1 层;随后,根据当前存在的快照、LSM 组织形式等设置 SST 文件的元信息。
将之前设置的阻塞标记全部删除。
总的来说,Ingest 导入是 RocksDB 的一个很关键的功能特性,适合用户数据的大批量写入。上述描述了一个将新文件 Ingest 到已存在的 DB 实例中的流程,可以看出是比较重的操作,除了会导致停写停 Compact,还会导致 MemTable 强制刷盘。所以对于每天更新的任务,我们完全可以每天往新的 DB 实例里导文件,这样就能避免很多的阻塞。
Map/Reduce 产出全局有序文件
从上述的 Ingest 文件可以看出,导入文件的堵塞需要付出比较大的代价,堵塞在线写和增大系统 Compact。我们可以通过往新 DB 实例中导文件避免堵塞写,通过保证 SST 全局有序避免系统 Compact。从 Hive 到 SST 这一步,我们依赖了大数据引擎进行 Map/Reduce,将原始数据作为输入,按照用户提交的拼接 Key 的方式,启动 Map/Reduce 任务直接构造最终 DB 需要的 SST 文件。
系统架构——千磨万击还坚劲
经过上面的背景和技术细节,我们最终完成了如下图的系统架构。
一键式 DTS 平台——FastLoad 系统架构
整个系统分为以下几个模块:
控制台服务:对外提供控制台表单和 OpenAPI 方式接入,提供创建任务、Schema 转换规则等服务。
大数据调度模块:依赖 Hadoop 的计算资源,将 Hive 数据导出为我们需要的中间文件,在经过 Map/Reduce 的构建,生成全局有序的 SST 文件。
文件下载模块:根据分布式存储的路由表,将 SST 文件下载到不同的存储节点。
文件导入和 DB 切换:依赖上文提及的 Ingest SST 的方式,将文件一次性导入 DB 实例。为了避免上述提及的堵塞,我们提供往新 DB 实例导数据的选项,这样就可以避免因线上写而导致的堵塞,空数据也可以避免 Compact。假如选择了新 DB 导入的选项,最后还会有一次 DB 新旧实例的切换,相当于一次链接映射。
总结与展望——直挂云帆济沧海
基于 FastLoad 的数据传输给业务带来的收益:
大大缩短业务导数据耗时,1TB 数据平均导入时间为 1 小时;
线上服务业务 300+,每天运行次数 1000+,每天导数据量 30TB+;
服务稳定性达到 99.99%,上线运行 2 年无任何重大事故;
高频运维操作一键自助完成,90% 的问题,5 分钟完成定位;
发展规划
架构优化,整体架构目前依赖 Hadoop,可以考虑迁移到 Spark,提升运行效率;
管控优化,提供更细致更全面的 FastLoad 监控和报表;
多产品应用,目前 FastLoad 主要针对 NoSQL 和 NewSQL 两种场景,同比可以应用在 ES、MQ 等场景;
新场景支持,离线数据的实时读取不仅对 OLTP 场景提供了更好的支持,也为接下来大热的 HTAP 场景提供了无限的可能。
嘉宾介绍:
赵锐,滴滴出行高级工程师,从事分布式存储 NoSQL/NewSQL 的相关研发,参与从零开始构建滴滴分布式存储 Fusion,有 PB 级别存储、千万 QPS 的存储经验。
活动推荐:
12 月 6 日北京ArchSummit全球架构师峰会上,设置实时计算平台话实践专题,届时会邀请专家来分享大数据处理引擎、实时流数据平台、实时 Query 技术、实时存储、ES、Spark 等技术话题。感兴趣可以点击链接查看官网。
评论