某团面试题①—kudu读写流程

devtools/2025/2/8 8:32:37/

kudu 读写流程

前言

为什么会有kudu?先贴一个经典的图。
在这里插入图片描述
kudu诞生之前大数据的主要2种方式存储

  • 静态数据
    以hdfs引擎作为存储引擎,适用于高吞吐量的离线大数据分析场景,缺点是实现随机读写性能差,更新数据难

  • 动态数据
    以Hbase为代表作为存储引擎,适用于大数据随机读写的场景,缺点是大批量读取吞吐量远不如hdfs,不适用批量数据分析的场景。

要实现大批量的读写,随机读写有比较弱,要随机读写+更新,吞吐量有不行,当时的处理策略是,使用两套集群来使用兼顾。
类似架构
在这里插入图片描述
如上图所示:
数据实时写入Hbase,实时的数据更新也在Hbase完成,为了应对OLAP的场景需求,通常使用定时(T+1、T+H)将hbase数据写成静态文件(parquet)导入到OLAP引擎(HDFS)
这一架构技能够实现随机读写,又可以支持OLAP分析的场景
但存在弊端:

  • 架构复杂,设计环节较多,运维成本很高,还需要考虑高可用,多副本,资源层面也比较浪费,数据安全、监控都比较困难
  • 时效性低,从hbase写入到hdfs需要同步加工时间

为了解决上述种种问题,诞生了一个”中流砥柱“ kudu
kudu:定位是Fast Analytics on Fast Data, 是一个既支持随机读写,又支持OLAP分析的大数据引擎。
在这里插入图片描述
KUDU 是一个折中的产品,在 HDFS 和 HBase 这两个偏科生中平衡了随机读写和批量分析的性能。从 KUDU 的诞生可以说明一个观点:底层的技术发展很多时候都是上层的业务推动的,脱离业务的技术很可能是空中楼阁。

Kudu是什么 Apache
Kudu是由Cloudera开源的存储引擎,可以同时提供低延迟的随机读写和高效的数据分析能力。它是一个融合HDFS和HBase的功能的新组件,具备介于两者之间的新存储组件。

Kudu支持水平扩展,并且与Cloudera Impala和Apache Spark等当前流行的大数据查询和分析工具结合紧密。

kudu架构

在这里插入图片描述
名词说明

角色作用
Master Server集群中的老大,负责集群管理、元数据管理等功能【为实现高可用,存在lead-follower节点】
Tablet Server集群中的小弟,负责数据存储,并提供数据读写服务 一个 tablet server 存储了table表的tablet 和为 tablet 向 client 提供服务。对于给定的 tablet,一个tablet server 充当 leader,其他 tablet server 充当该 tablet 的 follower 副本。 只有 leader服务写请求,然而 leader 或 followers 为每个服务提供读请求 。一个 tablet server 可以服务多个 tablets ,并且一个 tablet 可以被多个 tablet servers 服务着。 【 tablet server—leader提供读写服务,follower只提供读服务】
Table(表)一张table是数据存储在Kudu的tablet server中。表具有 schema 和全局有序的primary key(主键)。table 被分成称为 tablets 的 segments。
Tablet一个 tablet 是一张 table连续的segment,tablet是kudu表的水平分区,类似于google Bigtable的tablet,或者HBase的region。每个tablet存储着一定连续range的数据(key),且tablet两两间的range不会重叠。一张表的所有tablet包含了这张表的所有key空间。与其它数据存储引擎或关系型数据库中的 partition(分区)相似。给定的tablet 冗余到多个 tablet 服务器上,并且在任何给定的时间点,其中一个副本被认为是leader tablet。任何副本都可以对读取进行服务,并且写入时需要在为 tablet 服务的一组 tablet server之间达成一致性。

kudu的工作模式

在这里插入图片描述

说明:

  • 每个kudu table 按照hash或range分为多个tablet
  • 每个tablet中包含一个MemRowSet以及多个DiskRowSet
  • 每个DiskRowSet包含BaseData以及DeltaStores
  • DeltaStores由多个DeltaFile和一个DeltaMemStore组成
  • insert 请求的新增数据以及对MemRowSet中数据的Update操作(新增的数据还没来得及触发compaction操作,再次进行更新操作的新数据)会先进入到MemRowSet
  • 当触发flush条件时将新增数据真正的持久化到磁盘的DiskRowSet内
  • 对老数据的update和delete操作是提交到内存中的DeltaMemStore
  • 当触发flush条件时会将更新和删除操作持久化到磁盘DiskRowSet中的DeltaFile内,此时老数据还在BaseData【逻辑删除】,新数据已在DeltaFile内
  • 当触发compaction条件时,将DeltaFile和BaseData进行合并,DiskRowSet将进行合并,此时老数据才真正的从磁盘移除掉【物理删除】,只留下更新后的数据记录

正文来了

前置补充说明下名词

  1. 1个Table包含多个Tablet,其中Tablet的数量是根据hash或者是range进行设置的
  2. 1个Tablet中包含MetaData信息和多个RowSet信息 //MetaData就是保存的Tablet Server上的位置信息等
  3. 1个RowSet包含一个MemRowSet和多个DiskRowSet
    • 其中MemRowSet用于存储insert数据和update后的数据,写满后会刷新到磁盘中也就是多个DiskRowSet中**,默认是1G刷新一次或者是2分钟** //1G数据刷新到众多的DiskRowSet
    • DiskRowSet会定期的刷新,进行合并操作,删除更新数据之前的历史数据
  4. 1个DiskRowSet包含1个BloomFilter,1个Ad_hoc Index,一个BaseData,多个Delta file文件(UndoFile、RedoFile),一个Delta MemStore
    • BloomFile:根据DiskRowSet中key生成一个bloom filter,用于快速模糊的定位某一个key是否在DiskRowSet中
    • Ad_hoc Index:是主键的索引,用于定位key在DiskRowSet中具体哪个偏移位置
    • BaseData:是MemRowSet flush下来的数据,按照列存储,按照主键有序 //也就是CFile文件
    • Deltafile:
      UndoFile:是BaseData之前的数据历史数据 //更新数据之前的数据
      RedoFile:是BaseData之后的mutation记录,可以获得较新的数据 //最新的更新数据
    • DeltaMemStore:Delta Memstore达到一定程度后会在内存中合并数据,然后生成Redo data到磁盘
      合并策略:
      ①多个DeltaFile进行合并生成一个大的DeltaFile。默认是1000个DeltaFile进行合并一次
      ②DeltaFile文件的大小和Base data的文件的比例为0.1的时候,会进行合并操作,生成Undo data

kudu的读流程

在这里插入图片描述

  • 客户端向kudu Master 请求tablet的所在位置
  • kudu Master返回tablet的所在位置
  • 为了优化读取和写入,客户端会将元数据进行缓存
  • 根据主键范围过滤目标的tablet,请求tablet follower
  • 根据主键过滤Scan范围,定位DataRowSets
  • 加载BaseData,并与DeltaStores合并
  • 拼接上一步骤得到的老数据与MemRowSet数据,得到所需数据
  • 将数据返回到客户端

kudu的写流程

在这里插入图片描述

  • 客户端向kudu Master请求tablet所在的位置
  • kudu Master返回tablet所在的位置
  • 为了优化读取和写入,客户端会将元数据进行缓存
  • 根据分区策略,路由到对应Tablet,请求Tablet Leader
  • 根据RowSet【memrowset,diskrowset】记录的主键范围过滤掉不包含新增数据主键的RowSet
  • 根据RowSet【memrowset,diskrowset】布隆过滤器再进行一次过滤,过滤掉不包含新数据主键的RowSet
  • 查询RowSet【memrowset,diskrowset】中的B树索引判断命中新数据的主键,若命中则报错主键冲突,否则新数据写入MemRowSet(写入操作先被提交到tablet的预写日志(WAL),并根据Raft一致性算法取得追随节点的同意,然后才会被添加到其中一个tablet的内存中)「①插入会被添加到tablet的MemRowSet中 ② 更新和删除操作将被追加到MemRowSet中的原始行之后以生成redo记录的列表」
  • 返回响应给客户端

  • Kudu在MemRowset中写入一行新数据,在MemRowset(1G或者是120s)数据达到一定大小时
  • MemRowset将数据落盘,并生成一个diskrowset用于持久化数据还生成一个memrowset继续接收新数据的请求

kudu更新流程

在这里插入图片描述
更新删除流程与写入流程类似,区别就是最后判断是否存在主键时候的操作,若存在才能更新,不存在才能插入新数据。

  • 客户端向kudu Master请求tablet所在位置
  • kudu Master 返回tablet所在位置
  • 为了优化读取和写入,客户端将元数据进行缓存
  • 根据分区策略,路由到对应的Tablet,请求Tablet Leader
  • 根据RowSet【memrowset,diskrowset】记录的主键范围过滤掉不包含新增数据主键的RowSet
  • 根据RowSet【memrowset,diskrowset】布隆过滤器再进行一次过滤,过滤掉不包含新数据主键的RowSet
  • 查询RowSet【memrowset,diskrowset】中的B树索引判断是否命中修改的数据主键,若命中则修改至DeltaStores,否则报错数据不存在
  • 返回响应给客户端

补充说明:RowSet包含memrowset,diskrowset

  • 当待更新数据位于memrowset时:找到待更新数据所在行,然后将更新操作记录在所在行中一个mutation链表中,与插入数据不同的位置上,在memrowset将数据落盘时,Kudu会将更新合并到base data,并生成UNDO records用于查看历史版本的数据
  • 当待更新数据位于DiskRowset时:找到待更新数据所在的DiskRowset,每个DiskRowset都会在内存中设置一个DeltaMemStore,将更新操作记录在DeltaMemStore中,在DeltaMemStore达到一定大小时,flush在磁盘,形成DeltaFile中
  • 注意:wal日志的作用是如果我们在做真正的操作之前,先将这件事记录下来,持久化到可靠存储中(因为日志一般很小,并且是顺序写,效率很高),然后再去执行真正的操作。这样执行真正操作的时候也就不需要等待执行结果flush到磁盘再执行下一步,因为无论在哪一步出错,我们都能够根据备忘录重做一遍,得到正确的结果。

这一篇感觉也比较清晰,也可参考:

https://cloud.tencent.com/developer/article/2187652
贴几个图吧

写入数据

在这里插入图片描述
当 Client 请求写数据时,先根据主键从 Mater Server 中获取要访问的目标 Tablets,然后到对应的 Tablet 获取数据。因为 KUDU 表存在主键约束,所以需要进行主键是否已经存在的判断。一个 Tablet 中存在很多个 RowSets,为了提升性能,我们要尽可能地减少要扫描的 RowSets 数量。首先,我们先通过每个 RowSet 中记录的主键的(最大最小)范围,过滤掉一批不存在目标主键的 RowSets,然后在根据 RowSet 中的布隆过滤器,过滤掉确定不存在目标主键的 RowSets,最后再通过 RowSets 中主键索引,精确定位目标主键是否存在,如果主键已经存在,则报错:主键重复,否则就进行写 MemRowSet。写入操作先被提交到tablet的预写日志(WAL)目录,并根据Raft一致性算法取得follow节点的同意,然后才会被添加到其中一个tablet的内存中,插入会被添加到tablet的MemRowSet中。

读取数据

在这里插入图片描述
数据读取过程大致如下:先根据要扫描数据的主键范围,定位到目标的Tablets,然后读取Tablets中的 RowSets。在读取每个RowSet时,先根据主键过滤要scan范围,然后加载范围内的base data,再找到对应的delta stores,应用所有变更,最后union上MenRowSet中的内容,返回数据给 Client。

更新数据

在这里插入图片描述
数据更新的核心是定位到待更新数据的位置,这块与写入的时候类似,就不展开了,等定位到具体位置后,然后将变更写到对应的delta store中。


http://www.ppmy.cn/devtools/157052.html

相关文章

利用真值表法求取主析取范式及主合取范式

利用真值表法求取主析取范式及主合取范式 程序结构 ├─ code │ ├─logical_operation │ │ ├─__init__.py │ │ ├─Algorithm.py │ │ └─operator.py │ └─main.pycode:主程序文件夹 logical_operation:定义与逻辑运算有关的符号…

零基础Vue入门6——Vue router

本节重点: 路由定义路由跳转 前面几节学习的都是单页面的功能(都在专栏里面https://blog.csdn.net/zhanggongzichu/category_12883540.html),涉及到项目研发都是有很多页面的,这里就需要用到路由(vue route…

【高级架构师】计算机网络基础:第二章 计算机网络体系结构(上)

文章目录 第二章 计算机网络体系结构2.1 常用的计算机网络体系结构2.1.1 OSI体系结构2.1.2 具有五层协议的体系结构 2.2 物理层2.2.1 物理层的基本概念2.2.2 传输媒体 2.3 数据链路层2.3.1 数据链路层概述2.3.2 封装成帧2.3.3 透明传输2.3.4 差错校验2.3.4 以太网2.3.5 以太网的…

StarSpider 星蛛 爬虫 Java框架 可以实现 lazy爬取 实现 HTML 文件的编译,子标签缓存等操作

StarSpider 星蛛 爬虫 Java框架 开源技术栏 StarSpider 能够实现 针对 HTML XSS SQL 数学表达式等杂乱数据的 爬取 解析 提取 需求! 目录 文章目录 StarSpider 星蛛 爬虫 Java框架目录介绍如何获取?maven配置 架构是什么样的?结果对象的类…

MATLAB | 基于Theil-Sen斜率和Mann-Kendall检验的栅格数据趋势分析

最近看到一些博主分享关于 SenMK 检验的代码,对于新手来说可能有点复杂。我们编写了一段 MATLAB 代码,能够一次性解决这些问题,简化操作流程。我们还准备了几个关于趋势检验的空间分布图,供大家参考。 一、Sens Slope和Mann-Kenda…

【STM32系列】利用MATLAB配合ARM-DSP库设计IIR数字滤波器(保姆级教程)

ps.源码放在最后面 设计FIR数字滤波器可以看这里:利用MATLAB配合ARM-DSP库设计FIR数字滤波器(保姆级教程) 设计IIR滤波器 MATLAB配置 设计步骤 首先在命令行窗口输入"filterDesigner",接着就会跳出以下界面&#xf…

【论文投稿】Python 网络爬虫:探秘网页数据抓取的奇妙世界

目录 前言 一、Python—— 网络爬虫的绝佳拍档 二、网络爬虫基础:揭开神秘面纱 (一)工作原理:步步为营的数据狩猎 (二)分类:各显神通的爬虫家族 三、Python 网络爬虫核心库深度剖析 &…

Spring 中的设计模式

控制反转(IoC)和依赖注入(DI) IoC(Inversion of Control,控制反转) 是 Spring 中一个非常非常重要的概念,它不是什么技术,而是一种解耦的设计思想。IoC 的主要目的是借助于“第三方”(Spring 中的 IoC 容器) 实现具有依赖关系的对象之间的解耦(IOC 容器…