Mesa是Google用于广告的数据仓库系统, 拥有准实时的数据更新能力, 和低延迟的数据查询性能。 系统高可用性、可靠性、扩展性都非常优秀, 数据规模可达PB级别, 支持每秒数百万行写入。 每天数十亿查询请求 。
Mesa的数据模型是数据立方体, 表包含多个维度属性(keys), 和多个度量属性(values)。 表上可定义物化视图, 譬如表C是定义在表B上的物化视图, 其定义查询为SELECT SUM(Clicks), SUM(Cost) GROUP BY AdvertiserId, Country。 物化视图可以提高查询效率, 当然也放大了数据更新量, 因为系统必须维护父表和物化视图的数据一致性 。
多版本机制
更新采用批量方式。 一段时间内(通常是几分钟)的更新操作累积在一起, 批量更新入库。 与关系数据库MVCC机制类似, 一批更新操作产生一个新版本(版本号从0开始连续编号), 查询都是针对一个特定版本的数据快照, 所以更新操作不会影响到查询一致性。
物理存储和索引结构
Mesa底层是一个KV存储结构, 所有维度属性作为key, 度量属性作为Value。 如下图所示, Mesa使用与Leveldb类似的两层delta结构存储KV。 singleton代表一次update操作产生的delta, cumulatives代表多个版本的累计delta, base是所有历史更新积累而成的基础数据。多个singleton定期合并形成cumulatives, cumulatives定期合并到base。 通过这种方式, mesa支持到分钟级(5分钟)的数据更新延迟,且保证了查询性能。
Mesa表和索引采用相同的存储方式, 各自有各自的两层delta结构。 base/cumulative/singleton按照索引key顺序组织成多个数据文件, 存储于Colossus。 每个索引都会存储完整的记录, 所以查询时不存在回表操作。数据文件分为多个大小相近的row blocks, row block内部按照列存来组织并压缩, 以获得较高的压缩比。 提取row block首key的固定长度前缀构成数据文件摘要索引。查找记录时先从摘要索引定位row block, 解压缩row block相关列,进一步在row block中定位记录。
查询
Mesa查询通过查询服务器来实现, 没有实现类似Google兄弟产品powerdrill或者dremel类似的多层树状查询执行模型, 如果查询涉及的数据量较大时,性能会有瓶颈。 Mesa提供的查询能力也比较有限, 只是一些简单的条件过滤和group by, 高层数据库引擎比如MySQL,F1,Dremel可基于mesa的查询能力提供更强大的SQL能力,比如join query。 Mesa通过查询的标签区分在线查询和离线批量查询, 避免这两者相互干扰,能同时满足两种类型查询需求。
Mesa实现了一些基本的查询优化措施: 1) delta pruning。 根据delta的key范围跳过一些不命中的delta。理论上mesa也可以利用row block的统计调过一些不满足的block, 但是文章没有提到这种优化措施。 2) scan-to-seek优化, (A,B)两列索引,如果查询只指定了B上条件, 也尽量利用索引调过不必要的数据访问。( 这种优化常见于MySQL等关系数据库)。
除了基本查询之外, 针对一些离线分析业务, Mesa也支持Map Reduce框架。
总体看来Mesa支持的SQL能力比较有限, 查询的效率比较依赖于索引或者物化视图定义。
异地复制
全局唯一的无状态committer赋予更新唯一版本号, 并提交到异地高可用(paxo协议实现)的Global update storage中。 各数据中心的mesa实例从Global Update storage拉取更新,应用到本地, 等到所有数据中心都应用 成功时候, committer才增加commit version, 此时更新才对查询可见。 committer本身是无状态的, 所以自身高可用不成问题。
总结
Mesa是能同时满足准实时数据更新, 低延迟查询, 且可用性、扩展性都表现不错的数据库仓库系统。 Google内部类似的系统有PowerDrill,Dremel, 虽然有些不同的地方, 但是应用场景上也略有重叠, 很好奇Google内部是如何定位这些系统的。
文献
Mesa: GeoReplicated, Near RealTime, Scalable Data Warehousing