opentsdb 简易生动讲解
摘要
OpenTSDB是一个分布式的、可伸缩的时间序列数据库,在DB-engines的时间序列数据库排行榜上排名第五。它的特点是能够提供最高毫秒级精度的时间序列数据存储,能够长久保存原始数据并且不失精度。它拥有很强的数据写入能力,支持大并发的数据写入,并且拥有可无限水平扩展的存储容量。
它的强大的数据写入能力与存储能力得益于它底层依赖的HBase数据库,也得益于它在表结构设计上做的大量的存储优化。
本篇文章会详细讲解其表结构设计,在理解它的表结构设计的同时,分析其采取该设计的深层次原因以及优缺点。它的表结构设计完全贴合HBase的存储模型,而表格存储(TableStore、原OTS)与HBase有类似的存储模型,理解透OpenTSDB的表结构设计后,我们也能够对这类数据库的存储模型有一个更深的理解。
存储模型
在解析OpenTSDB的表结构设计前,我们需要先对其底层的HBase的存储模型有一个理解。
表分区
HBase会按Rowkey的范围,将一张大表切成多个region,每个region会由一个region server加载并提供服务。Rowkey的切分与表格存储的分区类似,一个良好设计的表,需要保证读写压力能够均匀的分散到表的各个region,这样才能充分发挥分布式集群的能力。
存储结构
如图所示为表结构以及对应的存储结构示例,在HBase或表格存储这类底层采用LSM-tree的数据库中,表数据会按列存储。每行中的每一列在存储文件中都会以Key-value的形式存在于文件中。其中Key的结构为:行主键 + 列名,Value为列的值。该种存储结构的特点是:
a. 每行主键会重复存储,取决于列的个数
b. 列名会重复存储,每一列的存储都会携带列名
c. 存储数据按row-key排序,相邻的row-key会存储在相邻的块中
OpenTSDB的基本概念
OpenTSDB定义每个时间序列数据需要包含以下属性:
1. 指标名称(metric name)
2. 时间戳(UNIX timestamp,毫秒或者秒精度)
3. 值(64位整数或者单精度浮点数)
4. 一组标签(tags,用于描述数据属性,至少包含一个或多个标签,每个标签由tagKey和tagValue组成,tagKey和tagValue均为字符串)
举个例子,在监控场景中,我们可以这样定义一个监控指标:
- 指标名称:
- sys.cpu.user
- 标签:
- host = 10.101.168.111
- cpu = 0
- 指标值:
- 0.5
指标名称代表这个监控指标是对用户态CPU的使用监控,引入了两个标签,分别标识该监控位于哪台机器的哪个核。
OpenTSDB支持的查询场景为:指定指标名称和时间范围,给定一个或多个标签名称和标签的值作为条件,查询出所有的数据。
以上面那个例子举例,我们可以查询:
a. sys.cpu.user (host=*,cpu=*)(1465920000 <= timestamp < 1465923600):查询凌晨0点到1点之间,所有机器的所有CPU核上的用户态CPU消耗。
b. sys.cpu.user (host=10.101.168.111,cpu=*)(1465920000 <= timestamp < 1465923600):查询凌晨0点到1点之间,某台机器的所有CPU核上的用户态CPU消耗。
c. sys.cpu.user (host=10.101.168.111,cpu=0)(1465920000 <= timestamp < 1465923600):查询凌晨0点到1点之间,某台机器的第0个CPU核上的用户态CPU消耗。
OpenTSDB的存储优化
了解了OpenTSDB的基本概念后,我们来尝试设计一下表结构。
如上图是一个简单的表结构设计,rowkey采用metric name + timestamp + tags的组合,因为这几个元素才能唯一确定一个指标值。
这张表已经能满足我们的写入和查询的业务需求,但是OpenTSDB采用的表结构设计远没有这么简单,我们接下来一项一项看它对表结构做的一些优化。
优化一:缩短row key
观察这张表内存储的数据,在rowkey的组成部分内,其实有很大一部分的重复数据,重复的指标名称,重复的标签。以上图为例,如果每秒采集一次监控指标,cpu为2核,host规模为100台,则一天时间内sys.cpu.user这个监控指标就会产生17280000行数据,而这些行中,监控指标名称均是重复的。如果能将这部分重复数据的长度尽可能的缩短,则能带来非常大的存储空间的节省。
OpenTSDB采用的策略是,为每个metric、tag key和tag value都分配一个UID,UID为固定长度三个字节。
上图为优化后的存储结构,可以看出,rowkey的长度大大的缩短了。rowkey的缩短,带来了很多好处:
a. 节省存储空间
b. 提高查询效率:减少key匹配查找的时间
c. 提高传输效率:不光节省了从文件系统读取的带宽,也节省了数据返回占用的带宽,提高了数据写入和读取的速度。
d. 缓解Java程序内存压力:Java程序,GC是老大难的问题,能节省内存的地方尽量节省。原先用String存储的metric name、tag key或tag value,现在均可以用3个字节的byte array替换,大大节省了内存占用。
优化二:减少Key-Value数
优化一是OpenTSDB做的最核心的一个优化,很直观的可以看到存储的数据量被大大的节省了。原理也很简单,将长的变短。但是是否还可以进一步优化呢?
在上面的存储模型章节中,我们了解到。HBase在底层存储结构中,每一列都会以Key-Value的形式存储,每一列都会包含一个rowkey。如果要进一步缩短存储量,那就得想办法减少Key-Value的个数。
OpenTSDB分了几个步骤来减少Key-Value的个数:
1. 将多行合并为一行,多行单列变为单行多列。
2. 将多列合并为一列,单行多列变为单行单列。
多行单列合并为单行单列
OpenTSDB将同属于一个时间周期内的具有相同TSUID(相同的metric name,以及相同的tags)的数据合并为一行存储。OpenTSDB内默认的时间周期是一个小时,也就是说同属于这一个小时的所有数据点,会合并到一行内存储,如图上所示。合并为一行后,该行的rowkey中的timestamp会指定为该小时的起始时间(所属时间周期的base时间),而每一列的列名,则记录真实数据点的时间戳与该时间周期起始时间(base)的差值。
这里列名采用差值而不是真实值也是一个有特殊考虑的设计,如存储模型章节所述,列名也是会存在于每个Key-Value中,占用一定的存储空间。如果是秒精度的时间戳,需要4个字节,如果是毫秒精度的时间戳,则需要8个字节。但是如果列名只存差值且时间周期为一个小时的话,则如果是秒精度,则差值取值范围是0-3600,只需要2个字节;如果是毫秒精度,则差值取值范围是0-360000,只需要4个字节;所以相比存真实时间戳,这个设计是能节省不少空间的。
单行多列合并为单行单列
多行合并为单行后,并不能真实的减少Key-Value个数,因为总的列数并没有减少。所以要达到真实的节省存储的目的,还需要将一行的列变少,才能真正的将Key-Value数变少。
OpenTSDB采取的做法是,会在后台定期的将一行的多列合并为一列,称之为『compaction』,合并完之后效果如下。
同一行中的所有列被合并为一列,如果是秒精度的数据,则一行中的3600列会合并为1列,Key-Value数从3600个降低到只有1个。
优化三:并发写优化
上面两个优化主要是OpenTSDB对存储的优化,存储量下降以及Key-Value个数下降后,除了直观的存储量上的缩减,对读和写的效率都是有一定提升的。
时间序列数据的写入,有一个不可规避的问题是写热点问题,当某一个metric下数据点很多时,则该metric很容易造成写入热点。OpenTSDB采取了和这篇文章中介绍的一样的方法,允许将metric预分桶,可通过『tsd.storage.salt.buckets』配置项来配置。
如上图所示,预分桶后的变化就是在rowkey前会拼上一个桶编号(bucket index)。预分桶后,可将某个热点metric的写压力分散到多个桶中,避免了写热点的产生。
总结
OpenTSDB作为一个应用广泛的时间序列数据库,在存储上做了大量的优化,优化的选择也是完全契合其底层依赖的HBase数据库的存储模型。表格存储拥有和HBase一样的存储模型,这部分优化经验可以直接借鉴使用到表格存储的应用场景中,值得我们好好学习。有问题欢迎大家一起探讨。
opentsdb 简易生动讲解相关推荐
- SVM算法的生动讲解
版权声明: 本文由LeftNotEasy发布于http://leftnoteasy.cnblogs.com, 本文可以被全部的转载或者部分使用,但请注明出处,如果有问题,请联系wheeleast@gm ...
- python面向对象生动讲解_Python面向对象语法精讲
本专题的内容结构: 第一部分主要是:面向对象基础 第二部分主要是:面向对象进阶 第一部分的结构: unit1:面向对象编程模式: (1),面向对象编程思想 (2),面向对象的三个特征 (3),Pyth ...
- Elasticsearch简易入门讲解
PDF版下载链接:https://download.csdn.net/download/taoruicheng1/85047119 1. Elasticsearch初识 1.1. Elasticsea ...
- “生动”讲解——矩阵的空间变换
转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 几何图形的矩阵表示: 我们把每个顶点坐标看成一个行向量,采用齐次坐标法,即每个顶点坐标增加 ...
- FPGA数字IC刷题58道Verilog题解代码及视频讲解【FPGA探索者】【同步/异步FIFO】【跨时钟】
牛客 Verilog 刷题入门篇1~24 + 进阶篇1~34 题解代码,所有代码均能通过测试,配合视频讲解效果更佳.为避免内容冗余,本文只给出代码,部分题目给出必要说明. 很多题目本身出题有些问题,着 ...
- Type-C PD快充基础讲解 + 实例(开源)
现阶段快充的技术应用非常广泛,快充适配器在我们身边也随处可见,那快充是如何实现的呢?是不是有很多小伙伴存在这类的疑惑.那我们今天就一起来会会它,看一看快充是不是如我们想的那般神秘. 另外,我们身边有各 ...
- 疫情当下,你是在家里躺着刷抖音?还是在做这些?
2020年本来可以是很开心的一年 没想到一开头就给了我们一个重重的一击 疫情的出现让我们非常的恐慌 新型病毒肺炎让我们无处可躲 原来热闹的新年因为疫情让我们逼不得已只能待在家里 走亲访友更是不可能的 ...
- 大厂「offer 收割机」修炼记
大家好,我是木叶,现在正值秋招前奏,木叶决定分享一下面试经历,希望对找工作的球友有点帮助,以拿到 offer 的公司为主,搭配败北的公司. 回顾 2020 年 3 月到 10 月的面试经历,也想通过木 ...
- 只有学霸才懂的学习技巧,看完脑洞大开,绝对涨姿势!
▲ 点击查看 法国生物学家乔治.居维叶曾说:"天才,首先是注意力." 事实上,除开那些逆天的天才之外,大部分人的智商,在先天因素的决定下,都是差不多的.但是专注力却可以因为后天的刻 ...
最新文章
- Jboot v2.0-rc.12 发布,优化细节问题
- 显示屏连接控制卡超时_小间距led显示屏的安装步骤
- LeetCode 2019 力扣杯全国秋季编程大赛
- mysql8事务级别_Mysql几种事务隔离级别
- 先序abdfcegh 中序bfdagehc 后序线索二叉树_二叉树的遍历(先序、中序、后序、层序)...
- elastic-job 新手指南
- linux用户个人的环境变量,linux下的变量以及系统和个人环境变量的配置文件
- Gitlab项目迁移
- 【作业锦集】机器人学导论-空间变换及Matlab实现(part-2)
- CAD工具——批量打印
- 论文阅读笔记-场景图谱-图谱生成:Scene Graph Generation from Objects, Phrases and Region Captions
- R_Studio(学生成绩)对数据缺失值md.pattern()、异常值分析(箱线图)
- LeetCode 区间子数组个数
- java狗具有特别的接飞盘的方法_java第七章 多态 课堂笔记/作业
- Web3中文|USDC的“脱锚”是稳定币稳定性的终结吗?
- 广东首例!涉“人脸识别”公民个人信息保护民事公益诉讼案宣判
- 事业单位笔试:《综合知识》大纲
- Ubuntu 升级 kernel 至 5.13.11(5.15.10)
- 如何使用sharemouse共享鼠标
- 大数据改变小生活,政务大数据能为我们带来什么?
热门文章
- 远程计算机已加入AAD凭据不工作
- SuperMap iDesktop地质体模型匹配地形——精修地质体模型路线
- 西安交通大学计算机专业考试科目,西安交通大学(专业学位)计算机技术研究生考试科目和考研参考书目...
- 为什么杜蕾斯的文案工资月薪5万?
- Trajectory Generation of a Quadrotor Transporting a Bulky Payload in the Cluttered Environments 论文解析
- 如何使用 R 从 Internet 下载文件
- 区块链学习笔记15——ETH状态树
- 如何用公式编辑器快速打五角星符号
- iOS-常见三种加密(MD5、非对称加密,对称加密)
- 为什么现在很多人特别排斥用微信打电话