Facebook TSDB论文Gorilla分析
Facebook TSDB论文Gorilla分析
背景
TSDB时序数据库用于存储时间相关的数据,常用于监控系统的数据存储,分布式的TSDB提供了海量的数据存储能力,如InfluxDB、OpenTSDB等。关于TSDB更多详情,可以参考该系列博客:时间序列数据的存储和计算。
随着监控数据量增长,对TSDB查询性能的要求越来越高,尤其是自动化运维系统,大量的查询操作让基于磁盘的TSDB系统难以满足。
Facebook基于此需求推出了TSDB论文,设计了一个基于内存的TSDB:Gorilla。并开源了Gorilla的原型项目beringei。
本文主要基于Facebook官方论文和相关解读分析Gorilla的架构和数据结构。
Gorilla架构
Gorilla是一个内存TSDB。它在监控数据写入HBase存储之前,起到一个write-through cache的作用。Gorilla的数据模型是一个简单的3元组,包括一个string类型的key、一个64-bit整型timestamp和一个双精度浮点类型value。Gorilla使用一种新的timeseries压缩算法,可以按照时间顺序将单条数据从16字节压缩到平均1.37字节,缩小12倍。Gorilla的内存数据结构设计使得在保持对单个时间序列进行时间段查找的同时也能快速和高效的进行全数据扫描。
Gorilla无状态的架构支持非常好的水平扩展能力。监控数据中定义的key用来唯一标识一个timeseries。根据key将timeseries数据进行shard(分片),每个timeseries数据集会被映射到一台单独的Gorilla主机上。因此扩展Gorilla主机时,可以通过调整分片算法将新的timeseries数据映射到新的主机上。
Gorilla支持高可用,通过将同一个timeseries数据写到2个不同地域的主机中,来应对单节点故障、网络切换、甚至是整个数据中心故障。在检测到故障时,所有读取操作会failed over到可用区域的主机,以确保用户不会感知到任何中断。
压缩算法
Gorilla引入了对timestamp和value的高压缩比算法,可大幅降低数据存储的大小。Timestamp根据时间关联的条目进行差值计算、以及差值的差值计算得到占用字节数非常小的数值并进行保存。同样Value使用XOR算法进行计算得到占用存储更小的数值进行保存。该算法在论文里描述的非常清楚,此处不再详述。
内存数据结构
TSmap
Timeseries Map (TSmap)是Gorilla实现的主要数据结构。如上图所示,TSmap包括一个C++ Vector和一个map(unordered_map)。Vector里保存指向timeseries的指针(shared_ptr)。Map里保存timeseries name(key)到timeseries指针(value)的映射,该map大小写不敏感并保留原有大小写。
Vector用于高效的分页扫描所有数据(根据vector下标)。Map用于特定时间的timeseries查询。该设计既满足快速按时间查询的需求,又能提供高效的数据扫描。
C++的shared-pointers可以在几毫秒时间内扫描拷贝整个vector(或者几个pages),可以有效避免对新写入数据流的影响。删除的timeseries会将对应的vector设置为“墓碑状态”,即对应的内存不释放,而是标记为dead,并用于新的timeseries重复使用。
Map和vector的并行访问使用一个简单的读写spin lock进行保护。每个timeseries上使用一个1-byte的spin lock实行互斥。单个timeseries相关很少的写流量,因此读写的锁争用较少。
ShardMap
如上图所示,还有一个ShardMap用于保存shardId(分片ID)到TSmap的映射。Timeseries在保存的时候根据timeseries name哈希散列到不同shardId(0 ~ NumberOfShard)。该map也是使用大小写不敏感hash算法。系统中的Shard总数几千以内,因此存储空指针的额外开销可以忽略。同样ShardMap也使用一个读写spin lock实现并行。
由于数据根据shard进行了分区,单个map变得足够小(大约100万个条目),C++的unordered-map有足够的性能,没有锁争用的问题。
Timeseries data block
最终保存的Timeseries数据结构(图中TS)由一系列closed data blocks和一个open data block组成。每个data block保存2小时的数据,Closed data block用于保存2小时以前的数据,Open data block用于保存2小时内最近的数据。Open data block是一个append-only的string,新的压缩后的timestamps和values追加到该string后面。一旦Open data block写满2小时,则将其close。Closed data block不允许修改,直到将其从内存里删除。在closing过程中,数据将被拷贝到从large slabs里分配的内存以减少内存碎片。拷贝之后open data block可以直接用于新的数据写入,避免open data block经常改变size导致reallocate内存从而导致内存碎片。
根据时间范围查询时,将拷贝关联的data blocks数据给远程调用者。整个data block直接返回给Client,并由Client完成timestamp和value的解压缩。
Timeseries key string
一般TSDB的数据模型里通常有一个Metric(如CPU使用率)和一些TAG(如host=10.10.10.10,cluster=A),并提供针对Metric和TAG的查询、聚合等功能。而Gorilla每个timeseries都有一个key string字符串作为其唯一标识。论文中没有太多描述,只是提了一下依赖更高层的工具去抽象和定义这个key string。简单的实现可能就是MetricName+TAG1(key=value)+TAG2..组成一个string。
磁盘数据结构
Gorilla使用GlusterFS存储持久化数据,以应对单机故障。GlusterFS是一个兼容POSIX的3副本分布式文件系统。之所以没有选择MySQL或者RocksDB,是因为Gorilla不需要提供一种数据库查询语言。
一个Gorilla主机上有多个shards的数据,每个shard有一个单独的目录,目录下包括4中类型的文件:Key list、append-only log、complete block files、checkpoint files。
- Key list是一个map用于保存timeseries string key到内存数据结构vector的ID的映射,新的key会被追加到当前key list文件尾,Gorilla会定期扫描每个shard里所有的keys并重写key list文件(猜测是为了保证一致性)。
- log file用于存储最新的数据流,包括压缩后的timestamps和values。每个shard只有一个log file,所以交替保存了多个timeseries的值。它和内存中的数据结构不同点在于每个timestamp-value pair都有一个32-bit整型ID标记,该ID应该就是key list里的vectorID,标记它属于哪个timeseries。log file并不是write-ahead-log(WAL),数据写入磁盘前会缓存64KB,因此宕机会导致几秒数据的丢失。不过Gorilla不需要提供ACID特性,相比WAL日志带来的收益,提供了更好的数据写入效率。
- complete block file存储压缩后的整个block数据,每隔2小时从内存中拷贝block数据并进行压缩,所以它比log file小了很多。该文件包含两个部分:一组连续的64KB slabs大小的block data;一个timeseriesID->data block指针pair的列表,用于标记block data属于哪个timeseries。这里timeseriesID应该和key list的vectorID是一个概念。
- checkpoint file用于标记某个时间的complete block file已经flush到磁盘。此时,对应的log file将被删除,数据流写入新的log file。宕机后接管该Shard的主机根据checkpoint file来确定从log file还是complete block file里读取数据。
总结
综上,Gorilla提供了一个对26小时内监控数据内存级分布式水平扩展的TSDB,在long-term分布式TSDB基础上提供了短时间(也是大部分查询需求时间段)内秒级快速查询的能力。
Facebook TSDB论文Gorilla分析的更多相关文章
- CVPR2018 关于视频目标跟踪(Object Tracking)的论文简要分析与总结
本文转自:https://blog.csdn.net/weixin_40645129/article/details/81173088 CVPR2018已公布关于视频目标跟踪的论文简要分析与总结 一, ...
- AlphaTensor论文阅读分析
AlphaTensor论文阅读分析 目前只是大概了解了AlphaTensor的思路和效果,完善ing deepmind博客在 https://www.deepmind.com/blog/discove ...
- Practical Lessons from Predicting Clicks on Ads at Facebook (2014)论文阅读
文章链接: https://quinonero.net/Publications/predicting-clicks-facebook.pdf abstract Facebook日活跃度7.5亿,活跃 ...
- [源码分析] Facebook如何训练超大模型---(1)
[源码分析] Facebook如何训练超大模型---(1) 目录 [源码分析] Facebook如何训练超大模型---(1) 0x00 摘要 0x01 简介 1.1 FAIR & FSDP 1 ...
- [源码分析] Facebook如何训练超大模型 --- (2)
[源码分析] Facebook如何训练超大模型 --- (2) 目录 [源码分析] Facebook如何训练超大模型 --- (2) 0x00 摘要 0x01 回顾 1.1 ZeRO 1.1.1 Ze ...
- [源码分析] Facebook如何训练超大模型 --- (3)
[源码分析] Facebook如何训练超大模型 --- (3) 目录 [源码分析] Facebook如何训练超大模型 --- (3) 0x00 摘要 0x01 ZeRO-Offload 1.1 设计原 ...
- 计算广告CTR预估系列(七)--Facebook经典模型LR+GBDT理论与实践
计算广告CTR预估系列(七)--Facebook经典模型LR+GBDT理论与实践 2018年06月13日 16:38:11 轻春 阅读数 6004更多 分类专栏: 机器学习 机器学习荐货情报局 版 ...
- [论文翻译] 分布式训练 Parameter sharding 之 ZeRO
[论文翻译] 分布式训练 Parameter sharding 之 ZeRO 目录 [论文翻译] 分布式训练 Parameter sharding 之 ZeRO 0x00 摘要 0x01 综述 1.1 ...
- [论文翻译] 分布式训练 Parameter Sharding 之 Google Weight Sharding
[论文翻译] 分布式训练 Parameter sharding 之 Google Weight Sharding 目录 [论文翻译] 分布式训练 Parameter sharding 之 Google ...
随机推荐
- 在GridView控件FooterTemplate内添加记录
在GridView控件FooterTemplate内添加记录,想实现这个功能,有几点要清楚的,这个添加铵钮是在FooterTemplate内,还是在GridView控件外部,位置不同,某些处理逻辑会有 ...
- charles 抓取app https 请求
测试需要抓取app的https请求链接,百度了一下教程,能设置的都设置成功了,但就是抓取不成功,显示如下图 无奈之下还是用谷歌搜索了下(网速极慢),但是庆幸的找到了问题的答案,原因还是手机设置的问 打 ...
- c# 大文件分割 复制 Filestream 进度条
大文件分割复制,每次复制100M 也可以复制别的较大数值. 小于1G的小文件就直接复制得了.代码里没写 ,但是很简单 直接写进去就好了,难得是分割复制 所以没写. 好吧 我还是改了 改成小文件也可以复 ...
- netty下载源码并导入idea
netty源码导入eclipse会有一些兼容性问题,网上有解决方案,官方推荐idea,故此用idea. 拷贝git地址:https://github.com/netty/netty.git 使用git ...
- 2019-RHCSA-红帽题库(稳定)
RHCSA考题 Hostname:station.rhce.ccIP address:192.168.122.100Netmask:255.255.255.0Gateway:192.168.122.1 ...
- [SinGuLaRiTy] NOIP膜你赛-Day 1
[SinGuLRiTy-1022] Copyright (c) SinGuLaRITy 2017. All Rights Reserved. 对于所有题目:Time Limit:1s || Memo ...
- Node JS后端项目开发与生产环境总结
原文地址:Node JS后端项目开发与生产环境总结 Node JS常用后端框架有express.koa.sails.国产框架有个egg js,已经在cnode投入生产了,还有个think js,类似t ...
- web flash推流h264视频取消cbr
flash as3.0 推视频H264关于视频质量 初次设置代码如下: h264Setting.setProfileLevel(H264Profile.BASELINE, H264Level.LEVE ...
- linux页表机制
每个进程都拥有一个自己的页表,在linux中,有一个页目录数组,这是分页机制的最高层,每个进程的页表对应其中的一个页目录项,通过cr3寄存器可以访问. 一个进程的页表,对应的页表项中对应页的物理地址. ...
- HDU - 6416 :Rikka with Seam(DP & 前缀和 & 数学)
pro:给定N*M的矩阵,现在让你在每一行删去一个位置,然后形成新N*(M-1)的矩阵,问有多少种不同的新的矩阵.需要满足相邻行删去的位置不大于K. (题目是01矩阵,其实任意矩阵都可以做,本题算法里 ...