GooDs: Organizing Google’s Datasets
<阅读笔记>
参与了dantezhao的一个论文阅读计划 paper-notes
将阅读成果分享到博客
Google Dataset Search (GooDs)是一个以元数据的形式管理数据集的企业内部系统
这篇论文介绍了GooDs的设计和用途
带着问题阅读:
1. what: GooDs系统是做什么的
2. why: 为什么需要GooDs系统
3. how: GooDs系统是如何设计的
0. 摘要
0.1 文章目标
- 探讨实现数据管理所面临的技术挑战 (Challenges)
从亿万级数据源爬取和推断元数据
维持大规模元数据目录的一致性
使用元数据为用户提供服务
- 对于打造大规模企业级数据管理系统的借鉴意义
1. 引言
1.1 企业数据管理的两种形式
- Enterprise Data Management (EDM)
生成数据集和管理数据集都在一套系统内
系统本身限制了数据的生产和流转
- Data Lake
与EDM不同的是,Data Lake采取事后(post-hoc)模式
不介入数据的生产和使用
只为已经生成的数据提供一套有效的管理工具
所以这是一种事后(post-hoc)行为
lake的比喻很形象,数据不断生成和累积汇聚成湖,查找数据就像从湖中钓鱼("fish the right data")
1.2 Google Dataset Search (GooDs)
- GooDs是一个静默的服务者
GooDs的全称是Google Dataset Search,但它的功能不限于search
GooDs采用了类似Data Lake的形式,对数据进行事后(post-hoc)管理
post-hoc将在文中多次出现,强调GooDs是静默的辅助工具
作者还用非侵扰(non-intrusive)表明GooDs既不影响数据本身,也不影响数据的生产者和使用者
1.3 GooDs的运作机制
[站外图片上传中...(image-d1e2c9-1561642798984)]
图:GooDs设计概览
- 分层介绍
1) GooDs持续地爬取(crawls)各类存储系统和业务线,
从中发现数据集(datasets)并收集数据集的元数据(datasets)信息和使用情况(usage)
(见图最底层)
2) GooDs将元数据聚合为一个中央目录(central catalog),同时把特定数据集的元数据与其他数据集的信息相互关联
(见图中间层)
3) GooDs用这套目录的信息构建搜索、监控和数据流可视化等工具,
从而为Google工程师提供数据管理服务
(见图最上层)
- 关于元数据(metadata)
1) 元数据信息的一个来源是直接从数据源收集
2) 元数据的另一个来源是对数据内容的推断(inference):
a. 处理附加的数据源,如日志、数据集所有者和项目信息等
c. 分析数据集的内容
d. 收集GooDs使用者输入
3) GooDs收集的元数据可能包括:
a. 数据所有者 (owners)
b. 访问时间 (time of access)
c. 内容特征 (content features)
d. 生产管线的访问记录 (accesses by production pipelines)
1.4 GooDs提供的一些工具
- dashboard 仪表板
展示所有数据集
提供多条件检索
可以横跨不同的存储系统
可以获得数据集和所有依赖的数据集
- monitor 监控
监控内容特征:如大小、数值的分布、是否可用
在特征发生意外改变时通知数据所有者
- provenance 数据血缘关系
生成某个数据集的上游数据
依赖某个数据集的下游数据
- search engine 搜索引擎
缩小搜索范围
- GooDs API
通过暴露接口,所有的团队都能为元数据目录做贡献,形成一种crowd-sourced(众包)的方式
数据使用者能够共享和交换数据集的信息
2. GooDs系统的技术挑战
2.1 天量数据规模
GooDs系统为超过260亿个数据集建立了索引
260亿这个数字仅包括对全体google员工开放权限的数据集
如果GooDs为更高级别权限的数据集建立索引,同时支持更多存储系统,规模可能在260亿的基础上翻倍
(double in the number of datasets)
即使每秒处理一个数据集,260亿也需要一千台并行的机器运转300天
对元数据的推断(inference)也因为计算量呈指数级增长而完全不可行
2.2 多样性
数据集以各种格式存储,来自各式存储系统,多样性成为数据统一管理问题之一
GooDs需要将各种格式的数据以同一种形式展示给用户
数据集的类型和大小不同或者元数据的类型不同,抽离元数据的成本也会不同
GooDs系统在推断元数据的时候,需要考量元数据的成本和收益
多样性也体现在数据集的相互关系中,而数据集的相互关系反过来影响元数据在GooDs目录的计算和存储
2.3 目录条目(Catalog Entries)的变动
GooDs目录条目中,每天约有5%左右的数据集被删除
优先计算哪些数据集的元数据,将哪些数据集加入目录,都会受到新旧数据集交替的影响
生存周期time-to-live(TTL)长的数据集相对比较重要
短周期数据集可能关联长周期数据集,所以GooDs系统不可能排除短周期数据集
2.4 元数据的不确定性
GooDs系统采取事后(post-hoc)非侵入(non-invasive)的方式,无法全程把握数据集的产生
GooDs根据已有数据推断和计算出的元数据,在一定程度并不精准
2.5 计算数据集重要性
推算数据集对使用者的重要性和在网页检索中推算网页的重要性不同
网页用于排序和检索的许多特性(如锚文本anchor text),数据集并不具备
不过数据集可以提供结构性的上下文,这是网页所没有的
数据集之间的唯一联系就是来源关联,而这种关联并不能完全决定数据集的重要性
为哪些数据集优先计算元数据,也可以作为数据集重要性的一项参考
2.6 复原数据集语义
数据集的语义可以通俗地理解为数据集的某项内容代表了什么
文中举的例子是,从一个数据集中推断出一批整型数值代表了地理坐标的ID
这样的数据集语义,在用户检索地理数据时就能排上用场
将无意义的原始数据升华为包含意义的内容对推断元数据非常有用
但是发现数据集语义本身也是一项非常困难的工作
3. GooDs系统的目录(Catalog)
Google内部每个存储系统都可能维护着自己的catalog,每个catalog还会有自己的metadata
数据在不同的数据集和存储系统之间自由流转是常态
GooDs所做的就是为所有存储系统和数据集建立统一的目录
Catalog上的一条记录称之为条目(entry),原则上每个entry对应一个数据集(dataset)的元数据
当出现一些特征相似度高的集群时,GooDs会将它们归并为一个集群(cluster),建立单个条目(entry)
集群的一个典型例子就是相同数据集的不同版本
3.1 元数据(Metadata)
- 概要
终于讲到了GooDs系统的关键要素————元数据(metadata)
元数据(metadata)包含很多信息,总结起来就是用于描述数据集的信息,即"数据的数据"
- 元数据的来源
元数据的途径有两种:
第一种可以通过直接访问获取:
GooDs系统在爬取数据集的时候,会顺带获取一些元数据,如数据集的大小、所有者、访问权限等
但是数据集并没有保存所有的元数据信息,比如生成数据集的作业(jobs),数据集的访问者等
不能从数据集直接获取的元数据往往存在于日志中
第二种通过GooDs系统计算得出:
GooDs除了爬取获得元数据外,还会通过推断(inference)获取元数据
[站外图片上传中...(image-774b58-1561642798984)]
Table2: 元数据(Metadata)和元数据组(Metadata Group)
- 基础元数据(Basic Metadata)
包括时间戳、文件格式、所有者、访问权限等
基础元数据一般由GooDs系统爬取存储系统直接获得,无需推断
GooDs的其他模块通常将基础元数据作为行为依据之一
- 数据血缘/数据谱系(Provenance)
GooDs中的元数据血缘关系来自数据集的生产和消费过程、数据集上下游依赖
GooDs通过分析生产日志来确定元数据的血缘信息
GooDs用时间顺序决定依赖关系,即晚发生的依赖于早发生的
在计算血缘关系时,GooDs为了效率可能会牺牲信息的完整性
- 结构信息(Schema)
Google内几乎所有结构化数据集都是基于serialized protocol buffer编码的
推断数据集使用了哪种形式的protocol buffer编码会产生多个结论
GooDs系统把所有可能的protocol buffer形式都记录在元数据中
- Content summary
Content summary按照字面直译为内容摘要反而不容易理解
实际上,元数据记录的content summary可以看成一套数据的关键字合集
文中举了三个summary的例子:
a) 抽样(sampling)产生的frequent token
b) 分析字段(fields)得出的键(key for data)
c) 有校验和(checksums)的fingerprints
GooDs通过summary来判断来自不同数据集的内容或者字段是否相似和相等,
- 用户注释(User-provided annotations)
一般用户做注释都是为了明确告知数据集的使用者有必要知晓的信息
GooDs的元数据通过分析注释来优化排序或者规避数据隐私
- 语义学信息(Semantics)
数据集的语义学信息可以帮助理解数据集
如果数据集使用了特定的protocol buffer,GooDs可以分析源码提取有用的备注(comment)信息
本段中举了个例子,比如数据集中一个名为"mpn"的字段,通过分析备注,发现mpn是"//Model Product Number"的缩写
这就是获取备注(comment)信息在语义学方面的作用
Google的知识图谱可以作为一个资源库,GooDs系统将数据集内容与知识图谱匹配,识别不同字段中包含什么样的条目信息(如位置信息,业务信息)
- 其他
除上述类型的元数据外,GooDs系统还会将以下信息作为元数据的内容:
a) 获取一个标识,通过该标识可以确认拥有数据集的团队(team)
b) 数据集所属项目的描述
c) 数据集元数据的变更历史
此外,GooDs允许团队在目录添加自定义的元数据,从而为所有使用者提供统一管理元数据的平台
3.2 数据集群(cluster)
- 数据集重复问题
GooDs目录上的260亿个数据集并非完全独立,很多数据集存在内容重复,比如:
a) 相同数据集的不同版本
b) 相同数据集复制到不同的数据中心
c) 大数据集被切分为小数据集
...
- 数据集集群化的好处
针对上述问题,将类似数据集归纳为集群有如下好处:
a) 为用户提供合乎逻辑的数据集分组
b) 只需计算集群中的少量数据集的元数据,节约计算成本
- 集群化的技术考量
将数据集集群化的计算成本要足够低,才值得使用
生成集群的计算成本不能高于重复计算相似数据集的成本
- 根据路径(path)层级(hierarchies)生成集群
数据集的路径可以提供划分集群的思路
某个数据集路径
dataset/2015-10-10/daily_scan
按天分类
dataset/2015-10-<day>/daily_scan
按月份和日期分类
dataset/2015-<month>-<day>/daily_scan
- 多粒度的半网格结构(granularity semi-lattice)
[站外图片上传中...(image-484ea3-1561642798984)]
Figure 2展示了两种层次的集群划分:按天划分和按版本号划分
[站外图片上传中...(image-45cada-1561642798984)]
Table 3展示了构建集群所依赖的数据集维度
从数据集的路径抽离出不同维度(dimensions,如日期、版本号)
为每个数据集构建一个半网格(semi-lattice)结构
在Figure 2所示的半网格结构中,非叶子节点代表了数据集的分组依据
- 集群的日常更新和重复映射问题
如果分组情况每天计算和更新,可能造成用户每天都看到不同的集群
为了解决这个问题,GooDs只为每个半网格的顶层元素创建条目(entry)
如Figure 2,目录将只有顶层的条目/dataset/<date>/<version>,
对应网格底层的三个数据集
采用这种方式可以保证每个数据集只映射到一个集群,
总的集群条目数量也会下降
- 集群的元数据
[站外图片上传中...(image-d42c85-1561642798984)]
Figure 4 将3个数据集的元数据汇总成集群元数据
GooDs系统通过汇总集群中各个数据集的元数据,生成该集群的元数据
集群的元数据以实时计算的方式产生,用于区分通过分析推断得出的元数据
- 数据集在集群中的分布
[站外图片上传中...(image-4268a3-1561642798984)]
Figure 3 用柱状图的方式展示了数据集在集群中的分布情况
集群化可以将"物理"集群压缩为"逻辑"集群
极大地降低了元数据的计算成本
用户可以通过集群更方便地查阅GooDs系统的目录
4 后端实现(Backend Implementation)
本节主要讨论:
GooDs系统目录(catalog)的物理结构
向目录中不断增加新模块的方法
目录数据的一致性
目录的容错机制
4.1 目录存储(Catalog storage)
- Bigtable的行存储
a) 目录使用Bigtable作为存储中介
Bigtable是一种可伸缩的,键值对存储系统
在目录中,Bigtable中的一行代表一个数据集或一个集群
Bigtable提供了单行事务一致性(per-row transactional consistency)
数据集路径或者集群路径作为这一行的键
通过这种方式,数据集对应单行,无需查找多余信息
b) GooDs系统中与单行单个数据集处理方式相左的特性
数据集提取半网格结构时,将多行信息整合到逻辑数据集中
累计同个集群中不同数据集的元数据
不过这种元数据累加并不需要强一致性
- Bigtable的列族(column families)
一张Bigtable表格包含多个独立的列族
GooDs的Bigtable中还设置了一些独立列族专门进行批量处理(高压缩率,非内存驻留)
只能通过批处理任务访问的数据就存在这些列族中
比如GooDs系统中最大的列族,就包含了用于计算血缘图谱的原始血缘数据
这些血缘数据内容不直接面向前端,仅为部分集群提供服务,因而可以高度压缩
- 元数据在Bigtable中的存储
在目录的Bigtable中,每行存储两种元数据信息:
a) 数据集的元数据
b) 状态元数据(status metadata):对某个数据集处理后生成的结果
- 状态元数据(status metadata)
状态元数据列出了用于处理条目的(entry)每一个模块
状态元数据可能包含时间戳,成功状态,错误信息等内容
GooDs使用状态元数据协调模块的执行
状态元数据也可以检测系统,比如通过成功状态观察数据集,收集出现次数最多的错误码
与Bigtable的临时数据模型配合,状态元数据还能用于调试(debugging)
通过配置Bigtable,保留若干代的状态元数据
这些代际数据能够揭示模块的历史表现
4.2 批量任务的性能和调度(Batch job performance and scheduling)
- 任务分类和系统可扩展性
GooDs系统的任务可以分为两大类
1) 数量庞大的各类批处理任务
2) 少数为前端和API提供服务的任务
GooDs系统具有可扩展性,为爬取新增资源提供了便利,如:
a) 新增的数据源
b) 血缘信息和其他元数据信息
c) 新的分析模块
- GooDs系统对任务的安排
运行时间长达几天的任务会被分配到距离数据集最近的地理位置
所有任务都独立运行,不限制先后顺序或是否并发
如果任务中断,系统可以将其临时下线
- 任务中的模块(modules)
每个任务都可能包括一个或多个模块,如爬虫或分析器
模块通常会依赖其他模块,如等待其他模块的计算结果
模块之间通过状态元数据协调执行顺序,粒度精确到Bigtable中的一行
如果模块A必须在模块B之前处理某行数据,
模块B会检查该行的状态元数据,是否标记为被模块A成功处理
如果模块A尚未处理,模块B会跳过该行,在下次运行时再重新检查,
如果模块A重新处理了该行,模块B也会重新处理,以保证元数据最新
模块也会使用自身的状态元数据以避免在设定时间窗口内重复处理数据
大多数任务每天运行,并在24小时候内完工
GooDs会优化超时运行的任务,或者使用并行任务分摊工作量
这些额外添加的任务,以24小时为周期处理,
专门处理新增目录行或者重新处理超出时间窗口的数据
- 重要数据集优先处理
在大量新数据集涌入系统的时候,
系统分析器(Schema Analyzer)作为最重量级的任务,
往往需要几天甚至几周才能跟上进度,
为了保证最重要的数据集不被忽略,
那些用户加注释或者血缘集中度高的数据集标注被标注为"重要"
每个任务将分成两个实例,
一个实例只处理重要数据集,
另一个实例处理所有数据集,并在一天的末尾处理一小部分重要数据集
实践中,通过网络爬取,保证最重要的那部分数据被充分覆盖率并且持续更新,
足以应对大多数的用户场景
- 数据盲写
负责爬取数据的任务通常使用盲写(blind write)的方式向目录添加数据
Bigtable不区分插入和更新
这种无指令(no-op)方式比读取目录后再进行反连接(anti-join)操作更高效
某些情形应当禁用无指令存储,否则会导致依赖的模块重新运行或者阻塞垃圾回收
4.3 容错机制(Fault tolerance)
因为数据集数量庞大种类繁多,GooDs系统遇到了各种问题
- 独立数据集和相互依赖的数据集
模块处理相互独立的数据集时:
错误信息会记录在单个数据集的状态元数据上;
如果状态元数据显示某个模块错误终止,将触发一定次数的重试
模块处理相互依赖的数据集时:
错误信息会记录在任务(job)的状态元数据上
例如:
有血缘关联的模块,
将一个数据集任务链接(dataset-job link)纳入血缘图谱前,
首先会查看这个任务链接的时间戳(timestamp),
只有时间戳比模块的最近成功执行时间(last successful execution)更晚,
模块才会整合该任务链接
上述方法有些保守,如果模块的最近一次执行有部分失败,
系统可能会重复执行一些Bigtable的录入;
但是这种方法能够保证血缘图谱的正确性,
因为Bigtable的录入是幂等的;
同时这种方法允许系统将任务血缘信息记录为"已消费",
"已消费"属性在垃圾回收中非常重要
- 模块依赖库依赖造成的问题
一些用于检测数据集内容的模块会使用各种库(libraries)
每个库都有可能专门用于处理特定的文件类型
库有时会崩溃或者陷入死循环
但是由库带来的问题并不能彻底消除,
因为系统不允许长时间运行的分析任务崩溃或挂起
一些危险的任务会被沙盒封装到单独的进程中,
看门狗线程会将长期停滞的任务转为崩溃状态,
这样管线上的其他任务能够继续运转
- 目录(catalog)的多地冗余
系统会在不同的地理位置冗余多份目录(catalog)
在master节点进行录入时,会同步在其他地方复制
4.4 元数据的垃圾回收(metadata)
- 垃圾回收策略的演进
GooDs系统每天都会吸收和生产大量数据,
其中相当一部分是临时数据
只要模块已经消费了数据集关联的元数据并更新了目录,
系统就可以删除目录上那些对应数据集已经被删除的条目
系统初始阶段,系统使用了简单保守的垃圾回收策略,
一条数据记录一周不再更新才会被删除
这种保守策略导致了若干起目录严重臃肿的问题,
使我们意识到有必要采取激进的垃圾回收策略
早期曾有两次,系统被迫中止了所有的爬虫和垃圾回收无关的分析模块,
直到数天后才从故障中恢复
- 垃圾回收机制的三大约束条件(constraints)
在实践中,GooDs系统垃圾回收系统的使用总结了一些实用经验
1) 对Bigtable中一行数据做删除时,删除条件最好的表达方式是说明性的断言,
断言中使用其他模块对该行数据访问和更新时记录的元数据和状态信息;
如:该数据集已从存储系统中删除,
血缘相关的另一个模块(已成功结束)对其最近更新的血缘信息进行过处理。
2) 因为Bigtable不区分插入和更新,从目录中删除一条记录时,
必须保证其他正在运行的模块没有将这条数据的部分信息重新插入目录,
这种情况被称为"dangling rows"
3) 所有其他模块都必须独立于垃圾回收模块,并和垃圾回收同时运行
- 垃圾回收的非事务性(non-transactional)
Bigtable支持"conditional mutation",
即根据指定的条件断言删除或更新一条数据,遵循事务原则
所有模块的更新都要依赖未被删除的单条记录,
Bigtable的conditional mutation带来了极大的日志结构读取开销
GooDs系统优化了设计,允许所有垃圾回收以外的模块进行非事务(non-transactional)的更新
垃圾回收在两阶段发生:
a) 第一阶段,垃圾回收使用声明断言的方式删除一条数据,
此时数据并没有真正删除,而是被标记了一个墓碑(tombstone)
b) 第二阶段,24小时之后,如果该行数据仍然符合删除标准,
垃圾回收会真正删除这行数据,否则将墓碑移除
与此同时,其他模块遵从下列规则:
a) 可以进行非事务更新
b) 更新时忽略标记了墓碑的数据
c) 模块的单次迭代不能存活超过24小时
这种设计在保证了系统高效的同时,也能够满足垃圾回收的三大约束条件
5 GooDs系统的前端,为目录服务(Front end: serving the catalog)
前几节内容主要关注了GooDs系统目录的创建和维护,
本节主要讲述与元数据相关的服务
5.1 数据集基本信息页(Dataset profile pages)
- 展示
输入路径,得到数据集或集群的元数据展示在HTML页面
在本文第三节介绍的大部分元数据信息都会被展示
用户可以通过编辑元数据的特定部分,讨论或修改目录中的元数据信息
- 信息量
展示在页面的元数据信息必须兼顾完整性和合理的信息含量
为了不让用户被信息淹没,同时避免大量数据的传输,
GooDs系统使用本文3.2节介绍的机制,将血缘元数据离线压缩
如果血缘数据的压缩版本仍然很大,系统只能保留最新的记录
- 与各类的工具的交叉关联
数据集的信息页会将元数据与其他工具交叉关联
比如某个数据集的信息页,会将血缘元数据,
和任务中心(job-centric tools)的任务详情页相关联,
这些任务生产了当前数据集,
任务中心就是管理任务的工具
又如架构(schema)元数据会和代码管理工具连接,
代码管理工具中有当前架构的定义
同时,这些工具又回链到GooDs系统,帮助用户获取数据集的更多信息
- 代码段工具(access snippets)
信息页同时提供了多语言的代码段工具(access snippets)来访问数据集的内容
GooDs为特定数据集定制代码段,
用户可以复制粘贴代码段到特定的开发环境
代码段的目标是补充信息页的元数据内容:
元数据提供了数据集内容的架构级信息,
而代码段提供了通过代码快速访问和分析数据集实际内容的途径
5.2 数据集搜索(Dataset search)
- 关键字查询和索引
数据集检索允许用户通过简单的关键字查询找到数据集
搜索服务依赖常规的倒排索引实现文件检索
每个数据集都被视为一个文件(document),
系统从数据集的元数据子集中提取索引令牌(index token),
每个令牌都会关联索引的特定部分,
如path开头关联的是索引的路径
索引令牌的提取视查询类型而定
以路径为例,
数据集的路径按分隔符拆分,每个令牌对应它在路径中的位置,
如"a/x/y/b"会映射到索引令牌"a","x","y","b",并且顺序不变
protocol buffer的名称也用相同的方式索引,
用户可以搜索到schema匹配特定protocol buffer命名空间的所有数据集
- 打分函数(scoring function)
关键字搜索到数据集是第一步骤,
第二步骤是生成一个打分函数来为匹配的数据集排序
GooDs系统会根据用户的使用经验不断调整打分函数
打分函数的几个设计经验:
a) 数据集的重要性依赖于它的类型:
比如打分系统认为Dremel Table比file dataset重要,
因为Dremel Table需要用户注册,使其对更多用户可见
b) 关键字匹配的重要性依赖于索引的位置
比如匹配数据集路径的关键字,
比匹配读写数据集任务的关键字重要性更强
c) 血缘谱系(lineage fan-out)是数据集重要性的重要指标
数据集的读取任务越多,下游数据集越多,则数据集越重要;
这个准则有时会给一些数据集打出不合理的高分,
这些数据集可能只是被大量的内部管线间接访问,
但是对大多数用户没用,比如Google的网页爬取信息
d) 带有用户描述信息的数据集重要性更高
除了上述几点,打分函数还会参考其他信号作为打分依据
- facet
在关键字检索之外,GooDs系统还会展示元数据的facets
如数据集的所有者,数据集的文件类型等
这些facet能帮助用户构建更好的搜索关键词
5.3 团队仪表板(Team dashboards)
GooDs系统的仪表板是一个可配置的一站式数据集展示窗口,
能够显示某个团队生成的所有数据集和每个数据集的元数据
GooDs系统自动更新仪表板的内容
用户可以将仪表板页面嵌入其他文件并将仪表板与他人共享
GooDs系统还提供了监控数据集特定属性并警示的功能
用户可以通过极少的操作自行设置需要监控的属性
除了预设的监控属性,GooDs系统还能够通过分析趋势,
自动监控数据集的一些公共属性
6 经验总结(lessons learned)
- 随着使用不断演进(evolve as you go)
GooDs系统期初的设计只是为数据集提供一个目录,
随着不断使用,GooDs系统也演化出各种用途:
1) 监测protocol buffer
protocol buffer可能包含隐私信息
使用GooDs系统,工程师可以找到所有符合敏感protocol buffer的数据集
一旦有违规,GooDs系统会提醒数据集所有者
2) 重新查找数据集(re-find datasets)
工程师经常会生成一些测试数据集,但是事后忘记了数据集路径,
通过GooDs系统的关键字查询,能够找回这些数据集
3) 读懂老代码(understand legacy code)
老代码因缺乏最新的文档而难读
工程师通过GooDs系统提供的血缘图谱,
能够找到老代码之前的执行过程以及输入输出数据集,
从而帮助理解老代码的逻辑
4) 标注数据集(bookmark datasets)
数据集的信息页可以作为数据集天然的信息展示窗口
用户可以标注信息页并将数据集与其他用户共享
5) 注释数据集(annotate datasets)
GooDs目录类似中转枢纽,数据集注释得以在不同的团队之间共享
- 在排序中使用某个领域特有的信号(use domain-specific signals for ranking)
本文第二节中提到,数据集排序问题有自己的特性,
与其他领域的排序不同(如网页排序)
根据GooDs系统的使用经验,
不同数据集之间的血缘关系就为排序提供了领域特有的信号
比如很多团队会为主数据集(master dataset)生成多个非规范化(denomalized)的版本
这些非规范化版本的数据集和主数据集匹配相同的关键字
但是显而易见,GooDs系统会在常规查询或者元数据提取中给主数据集更高的排序
- 预见并处理非常规数据集(expect and handle unusual datasets)
目录中庞大的数据集数量在GooDs系统早期产生了许多意外场景
在经验中GooDs系统形成了处理非常规数据集的策略:
首先提供最简单的特定问题解决方案,
接着在必要时归纳出同一类问题的总体解决方案
- 按需导出数据(export data as required)
GooDs目录的存储中介是键值对存储系统,
搜索服务依赖的是传统倒排索引,
二者均不适合对血缘图谱可视化或者执行复杂的路径查询
为了满足上述需求,
GooDs系统会将目录数据按主谓宾的三元组结构(subject-predicate-object triples)导出
GooDs系统会将这项元组数据导入到一个基于图形的存储系统,
支持路径查询并暴露更适合可视化的API
如果用户需要更强大的查询能力,现有存储系统无法支持,
最简单的方式就是将目录数据导出到一个合适的专门引擎中
- 保证可恢复性(ensure recoverability)
从数以十亿计的数据集提取元数据的计算成本非常高
稳定状态下,GooDs系统在单日内处理一天量的新数据集
丢失或损毁目录的重要部分可能需要数周恢复,
而且部分元数据在数据丢失后无法重现计算
为了保证可恢复性,GooDs系统将Bigtable设置为保留若干天内的滚动窗口快照
GooDs系统自身也有有量身定制的恢复方案:
a) 新设一个进程,在独立的目录,专门为重要的数据集拍摄快照
b) 另一个进程则备份目录中提供信息页的子集,
在主目录掉线时数据集信息页服务仍然可用
c) 此外,GooDs自身也启用了数据集监控服务,
保证尽早检测到数据损毁或丢失
上述措施都是在修复目录的经验中总结出的方案,
其中有一些曾导致用户交互服务出现严重中断事故
7 相关研究(related work)
这一节列举了一些类似的数据管理系统
这些系统中的某些用途和GooDs系统差不多,
但是GooDs系统还需要从各方面解决自身面临的需求痛点
- 数据湖(data lake)
GooDs系统可以看做一个数据湖,一种用于存储海量数据且访问便捷的仓库,
数据在生成的时候无需重新分类
GooDs是用于组织和索引数据湖的系统,这个数据湖包含了Google内部所有的数据集
其他公司也有类似的系统,
Google与之不同的地方在于数据湖的规模和post-hoc的元数据推断方式
- 元数据的生成方式不同
DataHub, Microsoft Azure Marketplace等数据集版本管理系统中,
数据集所有者可以选择主动参与元数据的生成
GooDs系统采用了post-hoc方式生成目录,
工程师在生成和维护数据集的时候无需考虑GooDs系统的存在
- 数据集与网页表格的不同
有一些系统可以从html页面中提取表格
GooDs系统处理的数据集和这些表格中的数据结构不同
这些表格数据没有元数据,而元数据对于数据集又想当重要
- 快速和高效的搜索
Spyglass等系统提供了强大的基于元数据的搜索功能
GooDs系统处理的数据集不在一个存储系统中,
没有足够多的现成元数据,
而且GooDs系统旨在提供比搜索更丰富的功能
- 对超大数据集进行索引和搜索
已经有研究在探索对超大数据集进行索引和搜索
GooDs系统需要解决本文第二节中列举的各类问题
如果GooDs要搜索数据集的实际内容而不是元数据时,
这些研究或许相关性更大
- 血缘关系管理
PASS和Trio等系统也会维护文件的血缘关系,
但是前提是这些血缘信息都是已知的或者能够从访问数据的进程中获得
GooDs系统需要依赖一些微弱的信号推断血缘信息,
但是却将血缘信息当做数据集排序的强信号
8 结论和展望(conclusions and future work)
- 总结
本文介绍的数据管理系统,可访问企业内部数以十亿计的数据集的元数据
- 挑战
1) 对数据集全排列,鉴别重要数据集,数据集的排序方法是否和网页排序方法类似
2) 完善元数据需要依赖各种资源和信息
3) 理解隐含在数据集中的语义信息能为用户提供更有效的搜索服务,
而对语义的理解也需要借助其他资源比如Google的知识图谱(Knowledge Graph)
4) 数据集产生的时候就在GooDs上注册能够保持目录更新,
而这种方式需要修改现有的存储系统,与GooDs非侵入式的理念冲突,
如何结合非侵入式和侵入式仍然有待解决
- 期望
希望类似GooDs的数据管理系统能够助推数据导向型公司培养一种数据文化
企业将数据当作企业核心资产,发展出类似"代码规约"的"数据规约(data discipline)"