TDengine 深入解析缓存技术

news2024/9/29 9:27:59

        TDengine是一款高性能的物联网大数据平台。为了高效处理时序数据,TDengine中大量用到了缓存技术,自己实现了哈希表、缓存池等技术。本文会为大家讲解TDengine中用到的这些缓存技术。

        首先会介绍一下什么是缓存,常用的缓存技术,最后重点分享TDengine中的相关技术,最好讲一下改进和优化的方向。下面我们正式开始。

        什么是缓存

        凡是位于速度相差较大的两种硬件之间,用于协调两者数据传输速度差异的结构,均可称之为缓存。

  1. 缓存最早是用来协调CPU和主内存之间的速度差异,进化出了目前的L1/L2/L3三层CPU内部的高速缓存;
  2. 在内存和硬盘之间也有Cache,每次写磁盘时并没有立即刷到磁盘上,而是写入到磁盘缓存中,由操作系统负责flush到磁盘;
  3. 此外,硬盘与网络之间也有某种意义上的Cache,比如CDN缓存,代理服务器的缓存等等。

缓存工作的原则主要是引用的局部性,包括空间局部性和时间局部性。

  1. 空间局部性是指CPU在某一时刻需要某个数据,那么很可能下一步就需要其附近的数据,例如加载读磁盘数据的时候,虽然只需要一部分数据,但是每次都加载一个块,那么当需要附近数据的时候就可以直接从内存获取,避免再读取磁盘。
  2. 时间局部性是指当某个数据被访问过一次之后,过不了多久时间就会被再一次访问。例如我们手机后台运行程序,会把最近打开的应用缓存在后台,很可能一会儿还会访问相同的应用,这种情况下直接将其从后台调到前台即可。

        在使用缓存时要根据系统的架构、性能的要求以及要解决的问题选择合适的缓存位置,比如内存缓存、 磁盘缓存、分布式缓存等。

        使用缓存有很多优点:

  1. 提高性能,将相应数据存储起来以避免数据的重复创建、处理和传输,可有效提高性能。
  2. 提高稳定性,同一个应用中,对同一数据、逻辑功能的多次请求是经常发生的。当请求量很大时,如果每次请求都进行处理,消耗的资源是很大的浪费,也同时造成系统的不稳定。
  3. 提高可用性,有时,提供数据信息的服务可能会意外停止,如果使用了缓存技术,可以在一定时间内仍正常提供对最终用户的支持,提高了系统的可用性。

        缓存是有状态的,包括时间状态和空间状态。

  1. 时间状态:应用程序使用的永久数据; 只在进程周期内有效;和特定的用户会话有关; 处理某个消息的时间内有效。
  2. 空间状态:应用程序/进程/线程/单机/分布式/用户/角色。

        使用缓存时需要考虑的问题:

  1. 安全性:线程安全/权限安全
  2. 序列化
  3. 缓存数据优化
  4. 提前加载/动态加载
  5. 过期策略:FIFO/LRU/LFU
  6. 管理:效率监控,大小限制

        缓存一致性问题:

  1. 当使用分布式的缓存时,需要考虑多个缓存的一致性问题,防止由于不一致出现问题。
  2. 处理一致性问题时需要根据实际的应用场景兼顾CAP原则。根据问题的场景不同,一致性要求也不同,可以强一致性或者弱一致性(最终一致性)。
    1. 比如银行转账场景需要强一致性,数据没统一之前,不允许用户进行操作,防止金额出错。
    2. 大多数互联网产品为了保证可用性和分区容错性,通常采用弱一致性,比如不同地区的用户看到的同一个排行榜可能有非常短暂的不同,但数据同步成功后,排行榜就相同了,这个延迟通常在几十ms,对于用户来说是可以接受的。

        常用的缓存技术

  1. 使用硬件缓存 (CPU Cache)
  2. 使用本地内存缓存(双缓冲/环形缓冲/缓冲池)
  3. 使用内存映射文件 (mmap)
  4. 使用数据库缓存 (Redis/MySQL)

        TDengine中的缓存方案

        首先我们来复习一下TDengine的整体架构。

  1. 数据节点(dnode):服务进程,可以包括多个vnode和mnode,查询数据时需要dnode的网络位置来获取数据。
  2. 虚拟节点(vnode):存储、查询的基本单位。多个vnode组成一个虚拟节点组(VGroup),分布在不同的机器上,起到备份的效果。同时vnode也便于水平扩展。
  3. 管理节点(mnode):存储数据库的元数据,起到管理集群的功能。

         再来看一下TDengine的数据模型。

  1. 一个采集点一张表(时间戳作为主键,顺序存储)
  2. 一张表的数据在文件中以块的形式连续存放
  3. 文件中的数据块大小可配
  4. 采用Block Range Index(BRIN)索引块数据

         TDengine中都有哪些数据需要缓存呢?具体可以分为如下几类:

  1. 元数据 (table meta/stable vgroup)
  2. 连接数据 (rpc/http session)
  3. 查询缓存 (qinfo handle/ show info)
  4. 最新数据 (last和last_row)
  5. 时序数据 (buffer pool/ multilevel storage)

        接下来我们就具体看一下TDengine中的缓存方案。 首先是通用的哈希缓存 (meta data/ rpcObj/ qinfo)。

  • 哈希缓存,通过一个列表来管理,每个元素是一个缓存结构,里面包括缓存信息、 哈希表 、垃圾回收链表、统计信息、更新频率、锁等信息。此外,有一个刷新线程定时检测缓存列表中过期的数据,将其删除。

  • 查询计划id (query handle)
    • query handle 是数据库查询时,server先生产一个执行计划,返回给client,然后client拿着这个计划id,分多次去server取数据,直到数据查询完。这个缓存是消息时间范围,整个进程内有效的,不需要更新,使用完即释放。

  • 元数据缓存(meta data)
    • meta data数据主要记录数据表的scheme,所在的节点地址。通过客户端缓存meta data可以避免频繁的向mnode取数据。但是meta数据需要考虑更新一致性问题。通过版本号来控制。

 

        其次是TSDB内存块缓存 (double buffer/buffer pool)。

  1. TDengine 提供双缓存/缓存池来优化数据写入查询的性能。预分配16M*6的buffer pool,使用超过1/3容量落地,落地时mem转化为imei(不可变更),负责写入磁盘。
  2. 直接将最近到达的数据保存在缓存中,可以更加快速地响应用户针对最近数据的查询分析,整体上提供更快的数据库查询响应能力。
  3. TDengine重启以后系统的缓存将被清空,之前缓存的数据均会被批量写入磁盘,之前缓存的数据不会重新加载到缓存中。
  4. 数据查询时首先通过time range定位数据所在的位置,因为MEM 和 IMEM中都记录有最新、最旧数据的时间戳。然后如果在MEM中,通过跳表来快速查询数据位置。在磁盘中,通过磁盘块文件索引查找数据,最后做结果融合返回。

         再来看last和last_row缓存 (local storage)。

  1. 时序数据库总是有对最新一行数据或者某列最新一条数据查询的需求,因此设计了last和last_row缓存来快速响应用户需求。防止每次都去磁盘查询数据。
  2. 每个表开辟缓存区缓存该数据,服务启动时会全量加载,插入时会更新,此外在配置更新的时候,也会更新缓存数据。比如,默认是关闭的。用户使用命令开启缓存功能时,就会加载数据,同理关闭开关时,会释放之前的缓存区。

         最后我们再来看一下多级存储 (ssd/hdd/cloud)。

        由于物联网的数据量是巨大的,为了很好的平衡性能和成本,TDengine还采用了分级存储的思想,不同热度数据存储在不同的地方。分级存储的这一思想也体现在计算机的体系结构里(寄存器、L1/L2 Cache、内存、硬盘)。

        缓存对性能提升举例

  • 测试环境: 12核 i7 3.2GHz 64GB 4T HDD
  • last_row缓存性能对比 (select last_row(*) from stable查询语句1000次,统计查询时间)
  • last缓存性能对比 (select last(*) from stable和select last_row(*) from stable查询语句1000次,统计查询时间)
  • 开启缓存性能比不开启缓存提升将近1个数量级。缓存对系统性能提升还是很大的,所以,在使用TDengine时,可以根据自己的需求,打开或关闭开关

        问题及改进优化方向

        先来看问题,主要是两点:

  1. mnode的meta数据全量加载,表数量很大时,内存占用大,启动慢;
  2. last和last_row缓存启动全量加载。

        最后我们再来看一下优化方向:

  1. 全量加载改为动态加载;
  2. 预分配缓存大小,通过LRU等策略来更新数据;
  3. qhandle 通过对象池管理,避免频繁calloc。

        如果想了解更具体的实现细节,可以在GitHub上查看相关源代码,也期待大家加入进来,一起改进TDengine Database!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/586531.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

想知道怎么翻译多个文本?我教你三个好方法吧

随着电子商务的全球化发展,越来越多的企业意识到将产品推向全球市场的重要性。在全球市场中,各种语言和文化的消费者都存在着巨大的潜在需求。为了吸引和服务这些不同语言的客户,企业需要采取一系列的措施,其中翻译是至关重要的一…

科技发展的那些事儿

近30年来,科技发展取得了惊人的成就,涉及范围广泛,包括计算机科学、通讯技术、生物医学、能源等多个领域。本文将列举近30年来科技发展的重要事件,并探讨这些事件对我们的生活、工作和社会产生的影响。 1991年,Linux操…

chatgpt赋能python:Python中可以用八进制表示整数吗?

Python中可以用八进制表示整数吗? Python是一种流行的动态编程语言,它支持许多整数表示方法。八进制是一种表示整数的方法,那么Python中可以使用八进制表示整数吗?本文将探讨这个问题。 什么是八进制? 在计算机科学…

基于SSM的服装设计供需系统设计与实现

摘 要:作为服装设计的重要形式之一,服装具有显著的审美性,是人类情感表达不可忽视的代表形态。但在新时期背景下,随着服装设计的进一步优化,服装设计创新融合强度也随之增强。本文就服装设计供需系统进行深入探究。 服…

chatgpt赋能python:如何在Python中去掉逗号

如何在Python中去掉逗号 在Python编程中,逗号是一个非常常见的符号,它通常用于分隔多个变量或值。然而,有时候我们需要从文本中去掉逗号,以便更好地处理数据。那么在Python中,如何去掉逗号呢?接下来&#…

华为OD机试真题B卷 Java 实现【停车场车辆统计】,附详细解题思路

一、题目描述 特定大小的停车场,数组cars[]表示,其中1表示有车,0表示没车。 车辆大小不一,小车占一个车位(长度1),货车占两个车位(长度2),卡车占三个车位&a…

idea使用Alibaba Cloud Toolkit插件远程操作Docker

idea使用Alibaba Cloud Toolkit插件远程操作Docker 前言 从github下载的开源项目源码,你基本上都能在项目根目录下发现会有个Dockerfile文件,Dockerfile文件是记录构建docker容器的构建命令,用途:一般用来将本地的jar包远程传输到…

内存对齐原则

struct (1)结构体第一个数据成员放在offset为0的地方,后面每个成员相对于结构体首地址的偏移量(offset)都是成员大小(该变量类型所占字节)的整数倍,如有需要编译器会在成员之间加上填…

中国人工智能学会主办!真实AIGC业务数据驱动,欢迎全球开发者参加

近期,由百度商业联合中国人工智能学会举办、NVIDIA提供战略支持,百度飞桨承办的“百度商业AI技术创新大赛”正式启动,启动会现场,中国工程院院士、中国人工智能学会理事长、清华大学信息科学技术学院院长戴琼海院士通过视频方式对…

chatgpt赋能python:在Python中一行书写两条语句:提高代码效率的好策略

在Python中一行书写两条语句:提高代码效率的好策略 从一开始Python就是因为简单易用、快速开发、名字有趣等因素而受到开发者的喜爱。当然,解释型语言也是Python深受欢迎的原因之一,你可以在Linux、Windows、Mac等各种平台上运行Python脚本&…

基于SSM的图书借阅管理系统

1.项目介绍 本项目是一款基于SpringSpring MVCMybatis的图书借阅管理系统,主要针对计算机相关主页的正在做课程设计的学生与需要项目实战学习、练习的Java学生人群。 该系统基于B/S架构,采用SpringSpring MVCMybatis框架技术,并结合主流的轻…

一起了解AJAX

注册账号的时候账号不能重复,通过AJAX实现实时验证当前注册的账号是否存在。 1.1register.jsp. 1.2HomeRegisterServlet. 2.JSON概述. 2.1何为JSON. JSON即 JavaScript Object Notation (js对象标记) ,是一种轻量级的数据交换格式&#xf…

Eclipse教程 Ⅷ

Eclipse Debug 配置 创建和使用 Debug 配置 Eclipse Debug 配置类似于运行配置但它是用于在调试模式下开启应用。 打开 Debug 配置对话框步骤为:Run > Debug Configurations 。 从左侧列表中选择 "Java Application" 选项来选择要调试的 Java 代码。…

使用KubeSphere3.3在Ubuntu20.04的Kubernetes1.24上部署Word Press

使用KubeSphere3.3在Ubuntu20.04的Kubernetes1.24上部署Word Press 前言 之前已经部署了KubeSphere和K8S的基础环境:https://lizhiyong.blog.csdn.net/article/details/126236516 部署了大数据统一文件编排层Alluxio:https://lizhiyong.blog.csdn.net…

抖音seo源码开发开源--MySQL语言

源码开发是指基于开放源代码的软件或应用程序进行开发和定制。开放源代码是指软件或应用程序的源代码是公开的,任何人都可以查看、修改和分享。源码开发者可以从开放的源代码中学习和了解软件的工作原理,并基于自己的需求进行修改、定制和扩展。开放源代…

chatgpt赋能python:Python字符串首字母大写的方法

Python字符串首字母大写的方法 Python是一种高级编程语言,广泛用于科学计算、Web开发和网络编程等多个领域。在Python编程中,我们常常需要将字符串首字母大写,以符合一些规范或要求。在本文中,我们将介绍Python中将字符串首字母大…

效率至少提升数倍的office技巧

在现代办公室,WPS Office已成为无可替代的工具之一。然而,许多办公室员工却未能充分发掘WPS Office的强大功能和技巧。在快节奏的工作环境中,掌握一些WPS Office的技巧,将帮助员工们提高工作效率、改善文件处理和团队协作能力。下…

用CSS来做一个动画案例

今天来做这么一个案例 添加一个动画实现上下渐变滚动的效果 首先还是我们HTML部分&#xff0c;一个大盒子装着五个子元素 下面别在意&#xff0c;之前写的时候看到有个网站有这么个注解我就复制了下来哈哈哈 <div class"loader"><div class"slider&…

【SpringCloud——Docker】

一、什么是Docker 二、Docker的基本操作 1、Docker操作镜像 镜像名称一般由两部分组成&#xff1a;[repository]:[tag] 在没有指定tag时&#xff0c;默认是latest&#xff0c;代表最新版本的镜像。 1.1、启动Docker服务 systemctl start docker1.2、查看Docker运行状态 syst…

34.序列中删除指定数组以及编写代码过程中遇到的问题

描述 有一个整数序列&#xff08;可能有重复的整数&#xff09;&#xff0c;现删除指定的某一个整数&#xff0c;输出删除指定数字之后的序列&#xff0c;序列中未被删除数字的前后位置没有发生改变。 数据范围&#xff1a;序列长度和序列中的值都满足 1≤&#xfffd;≤501≤…