写点什么

一文看懂 Pinterest 如何构建时间序列数据库系统 Goku

  • 2018-10-14
  • 本文字数:2900 字

    阅读完需:约 10 分钟

导读:在 Pinterest,开发人员依靠 Statsboard 来监控系统并发现问题,因此,可靠有效的监控系统对于开发速度来说非常重要。之前,Pinterest 使用 OpenTSDB 来提取和提供指标数据。然而,随着 Pinterest 的发展,服务器也从数百个增加到数千个,每秒产生数百万个数据点,而且这个数字还在继续增长。

虽然 OpenTSDB 在功能上运行良好,但其性能随着 Pinterest 的增长而降低,导致运营开销(例如严重的 GC 问题和 HBase 经常崩溃)。为了解决这个问题,Pinterest 开发了自己的内部时间序列数据库——Goku,其中包含用 C ++ 编写的 OpenTSDB 兼容 API,以支持高效的数据提取和成本昂贵的时间序列查询。

正文:

(使用 Goku 进行两级分片)

时间序列数据模型

时间序列数据

Goku 遵循 OpenTSDB 的时间序列数据模型。时间序列由一个键和一系列时间数字数据点组成。key = metric name + 一组标记键值对。例如,“tc.proc.stat.cpu.total.infra-goku-a-prod {host = infra-goku-a-prod-001,cell_id = aws-us-east-1}”。数据点 = 键 + 值。值是时间戳和值对。例如,(1525724520,174706.61),(1525724580,173456.08)。

时间序列查询

除了开始时间和结束时间之外,每个查询都由以下部分或全部组成:度量标准名称、过滤器、聚合器、降采样器、速率选项。

1)度量名称示例:“tc.proc.stat.cpu.total.infra-goku-a-prod”。

2)对标记值应用过滤器,以减少在查询或组中拾取系列的次数,并在各种标记上聚合。Goku 支持的过滤器示例包括:完全匹配、通配符、Or、Not 或 Regex。

3)聚合器规定将多个时间序列合并为单个时间序列的数学方法。Goku 支持的聚合器示例包括:Sum、Max / Min、Avg、Zimsum、Count、Dev。

4)降采样器需要一个时间间隔和一个聚合器。聚合器用于计算指定时间间隔内所有数据点的新数据点。

5)速率选项可选择计算变化率。有关详细信息,请参阅 OpenTSDB 数据模型( http://opentsdb.net/docs/build/html/user_guide/query/index.html )。

挑战

Goku 解决了 OpenTSDB 中的许多限制,包括:

1)不必要的扫描:Goku 用倒排索引引擎取代了 OpenTSDB 的低效扫描。

2)数据大小:OpenTSDB 中的数据点是 20 字节。Pinterest 采用 Gorilla 压缩来实现 12 倍压缩。

3)单机聚合:OpenTSDB 将数据读取到一个服务器上并进行聚合,而 Goku 的新查询引擎是将计算迁移到更接近存储层的位置,该存储层在叶节点上进行并行处理,然后在根节点上聚合部分结果。

4)序列化:OpenTSDB 使用 JSON,当有太多数据点要返回时,JSON 会很慢;Goku 使用 thrift 二进制代替。

架构

存储引擎

Goku 在内存存储引擎中使用了 Facebook Gorilla 来存储过去 24 小时内的最新数据。

(存储引擎简介。请查看 Gorilla论文及其 GitHub存储库来了解详细信息)

如上所述,在存储引擎中,时间序列被分成称为 BucketMap 的不同分片。对于一个时间序列,也被分为可以调整时长的  bucket(Pinterest 内部以每 2 小时为一个  bucket)。在每个 BucketMap 中,每个时间序列都被分配一个唯一的 ID 并链接到一个 BucketTimeSeries 对象。BucketTimeSeries 将最新的可修改缓冲区存储区和存储 ID 保存到 BucketStorage 中的不可变数据存储区。在配置存储  bucket 时间之后,BucketTimeSeries 中的数据将被写入 BucketStorage,变为不可变数据。

为了实现持久性,BucketData 也会写入磁盘。当 Goku 重新启动时,它会将数据从磁盘读入内存。Pinterest 使用 NFS 来存储数据,从而实现简单的分片迁移。

分片和路由

我们使用两层分片策略。首先,我们对度量名称进行散列,以确定某一时间序列属于哪个分片组。我们在度量名称 + 标记键值集上进行散列,以确定时间序列在所在组中的哪个分片。此策略可确保数据在分片之间保持平衡。同时,由于每个查询仅进入一个组,因此扇出保持较低水平,以减少网络开销和尾部延迟。另外,我们可以独立地扩展每个分片组。

查询引擎

倒排索引

Goku 通过指定标记键和标记值来支持查询。例如,如果我们想知道一个主机host1的 CPU 使用率,我们可以进行查询cpu.usage {host = host1}。为了支持这种查询,Pinterest 实现了倒排索引。(在 Pinterest 内部,它是从搜索项到位集的散列映射。)搜索项可以是像cpu.usage这样的度量名称,也可以是像host = host1这样的标记键值对。使用这个倒排索引引擎,我们可以快速执行ANDORNOTWILDCARDREGEX操作,与原始的基于 OpenTSDB 扫描的查询相比,这也减少了许多不必要的查找。

聚合

从存储引擎检索数据后,开始进行聚合和构建最终结果的步骤。

Pinterest 最初尝试了 OpenTSDB 的内置查询引擎。结果发现,由于所有原始数据都需要在网络上运行,性能会严重下降,而且这些短期对象也会导致很多 GC。

因此,Pinterest 在 Goku 中复制了 OpenTSDB 的聚合层,并尽可能地早地进行计算,以尽量减少线上的数据。

典型的查询流程如下:

  • 用 Statsboard 客户端查询(Pinterest 的内部度量监控 UI)任何代理 goku 实例
  • 代理 goku 基于分片配置将查询扇出到同一组内的相关 goku 实例
  • 每个 goku 读取倒排索引以获取相关的时间序列 ID 并获取其数据
  • 每个 goku 基于查询聚合数据,如聚合器、降采样器等
  • 代理 goku 在收集每个 goku 的结果并返回客户端后进行第二轮聚合

性能

与之前使用的 OpenTSDB / HBase 解决方案相比,Goku 在几乎所有方面都表现更好。

另一个在使用 Goku 前后高基数查询延迟对比图,如下图所示:

下一步

基于磁盘的长期数据存储

Goku 最终将支持超过一天时间数据的查询。对于像一年这样的时长查询,Pinterest 将不会过分强调一秒钟内发生的事情,而是关注整体趋势。因此,Pinterest 将进行降采样和压缩,把以小时计的 bucket 合并为更长期的时长,从而减小数据量并提高查询性能。

(Goku 阶段#2——基于磁盘:数据包括索引数据和时间序列数据)

复制

目前,Pinterest 有两个 goku 集群进行双行写入。此设置提高了可用性:当一个集群中存在问题时,可以轻松地将流量切换到另一个集群。但是,由于这两个集群是独立的,因此很难确保数据的一致性。例如,如果写入一个集群成功而另一个未成功时,则数据写入失败,数据由此变得不一致。另一个缺点是故障转移总是在集群层面发生。为此,Pinterest 正在开发基于日志的集群内复制,以支持主从分片。这将提高读取可用性,保持数据一致性,并支持分片级的故障转移。

分析用例

所有行业都需要广泛的分析,Pinterest 也不例外,例如面临询问实验和广告推广效果等问题。目前,Pinterest 主要采用离线作业和 HBase 进行分析,这意味着不会有实时数据产生,并避免大量不必要的预聚合。由于时间序列数据的性质,Goku 可以很容易地适应它,不仅可以提供实时数据,还可以提供按需聚合。

Pinterest 表示将继续探索 Goku 的用例,如果你对此类项目感兴趣,请查看 https://careers.pinterest.com/careers/engineering

原文链接:

https://medium.com/@Pinterest_Engineering/goku-building-a-scalable-and-high-performant-time-series-database-system-a8ff5758a181

感谢刘志勇对本文的审校。

2018-10-14 18:121515
用户头像

发布了 42 篇内容, 共 12.9 次阅读, 收获喜欢 53 次。

关注

评论

发布
暂无评论
发现更多内容

AngularJS进阶(四十)创建模块、服务

No Silver Bullet

服务 模块 AngularJS 12月月更

openGemini v0.2.0版本正式发布:5大特性全面增强

华为云开发者联盟

数据库 后端 华为云 12 月 PK 榜

Kerberos 身份验证在 ChunJun 中的落地实践

袋鼠云数栈

数据集成 kerberos 大数据 开源

cdr2023断网离线激活下载教程

茶色酒

cdr2023

震惊,WSL2居然可以挂载USB

DisonTangor

WSL2 usb

如何删除数据并刷新列表

Towify

微信小程序 无代码 触发器

spring高级源码笔记:深入理解阿里spring源码核心思想及框架应用

钟奕礼

Java 程序员 java面试 java编程

FinClip 手把手教学:如何将小程序游戏引入自有APP?(Android篇)

FinClip

如何制作一个实时在线显示评论?

Towify

微信小程序 无代码

直播 | 数据智能大咖在线研讨,带你找到适合自己的企业级方法论!

StarRocks

数据库 物流

什么是制造业数字化转型?制造业数字化转型的核心与意义

优秀

数字化转型 制造业

马斯克都不懂的 GraphQL,API 网关又能对其如何理解?

API7.ai 技术团队

api 网关 graphql APISIX

版本更新 | Towify V1.23.1 有哪些实用新功能?汇总来了!

Towify

微信小程序 无代码平台

公司刚来的京东架构师:看完我写的spring笔记,甩给了我一份文档

钟奕礼

Java 程序员 Java 面试 java编程

系统的混乱并非业务本身之复杂,我们并不擅长处理『简单』

阿里技术

软件工程 复杂度

聚焦技术,锐意创新,GaussDB给世界一个更优选择

华为云开发者联盟

数据库 后端 华为云 12 月 PK 榜

哪篇论文宣布了 HTAP 数据库的诞生?解读《A Common Database Approach for OLTP and OLAP Using an In-Memory Column DataBase》

StoneDB

MySQL HTAP 数据库· StoneDB 12 月 PK 榜

PreSTU:一个专门为场景文本理解而设计的简单预训练模型

华为云开发者联盟

人工智能 华为云 OCR 12 月 PK 榜

Sovit3D引擎快速构建智慧变电站三维可视化系统

2D3D前端可视化开发

物联网 智慧变电站 智能变电站 数字孪生变电站 变电站可视化

银斯微与大敦科技签署MOU,推动UI开发工具在中国的落地应用

科技热闻

骨灰级精品,京东百万架构师亲码的MySQL内部笔记太硬核了

小小怪下士

Java MySQL 程序员

AngularJS进阶(三十九)基于项目实战解析ng启动加载过程

No Silver Bullet

项目实战 AngularJS 12月月更 启动加载

AngularJS进阶(四十一)AngularJS中使用Chart.js制折线图与饼图实例

No Silver Bullet

AngularJS 12月月更 Chart.js 折线图与饼图

手把手系列:如何将小程序游戏引入自有APP?(iOS篇)

FinClip

guitar pro2023下载官方版app

茶色酒

Guitar Pro guitar pro2023

如何合并Excel文档

Geek_249eec

C# Excel VB.NET

介绍四大并发集合类并结合单例模式下的队列来说明线程安全和非安全的场景及补充性能调优问题。

C++后台开发

多线程 并发 后端开发 异步 linux开发

一文看懂Pinterest如何构建时间序列数据库系统Goku_语言 & 开发_陈利鑫_InfoQ精选文章