美文网首页
Kudu快速入门与原理介绍

Kudu快速入门与原理介绍

作者: 小驴小驴 | 来源:发表于2021-02-17 00:43 被阅读0次

    Kudu

    简介

    kudu简单来说与结构化数据库非常相似,kudu中定义表时与结构化数据库相似,需要定义Schema信息,并且需要且必须要定义primary key,primary key可以定义在一列或多列。kudu是介于Hive、Hbase之间的数据存储引擎。Kudu可以作为数仓的选型记录,存储海量数据并提供较为优秀的海量数据随机读写能力,这主要得益于kudu底层的数据存储模型。

    架构

    Kudu架构师分布式的主从架构,分为Master与Tablet两部分组件。


    kudu架构.jpg
    • 架构
      • Master Server
        集群中的老大,负责集群管理、元数据管理等功能,当Kudu需要对数据CRUD时,Master Server可以根据SQL中的表信息等初步定为到数据变更会在哪些Tablets中,确保某Table中的数据记录不会落到其他Table的Tablet中,这点非常重要。架构上Master为了避免单点故障,也可以部署成集群做主备方案,产生leader、follower两个角色,只有leader对外提供服务。
      • Tablet Server
        集群中的小弟,负责数据存储,并提供数据读写服务。其中Tablet服务中也是分布式架构,针对每一个tablet有leader与followers角色,与redis的主从架构相似,leader、followers都可以进行读操作,但是事务操作(写)只能在leader中进行。每一个tablet server中存储的是一个个tablet
    • kudu tablet
      • tablet是kudu表中数据水平分区(避免原始表数据量太大,只在一个tablet server),一个表可以划分成多个tablet(类似于hbase的region)
      • tablet中主键是不重复且连续的 所有tabler加起来就是一个原始table的所有数据
      • tabler在存储的时候 会进行冗余存放,设置多个副本
      • 在一个tablet的所有冗余中, 任意时刻 只有一个是leader,其他冗余都是follower,但只有tablet leader才可以进行事务操作。

    Quick Start

    kudu官网中有quick start安装教程:https://kudu.apache.org/docs/quickstart.html,在此不做详细描述。
    在centos /etc/profile.d目录中编写开机自启的脚本:kudu-docker.sh脚本,用于linux启动自动拉起kudu docker,脚本如下:

    #!/bin/sh
    
    MASTER1=` docker inspect --format '{{.State.Running}}'  docker_kudu-master-1_1 `
    MASTER2=` docker inspect --format '{{.State.Running}}'  docker_kudu-master-2_1 `
    
    TSERVER1=` docker inspect --format '{{.State.Running}}'  docker_kudu-tserver-1_1 `
    TSERVER2=` docker inspect --format '{{.State.Running}}'  docker_kudu-tserver-2_1 `
    
    if ( $MASTER1 == "true" );
            then
                    echo "docker_kudu-master-1_1 had started"
            else
                    docker start docker_kudu-master-1_1
    fi
    
    if ( $MASTER2 == "true" );
            then
                    echo "docker_kudu-master-2_1 had started"
            else
                    docker start docker_kudu-master-2_1
    fi
    
    if ( $TSERVER1 == "true" );
            then
                    echo "docker_kudu-tserver-1_1 had started"
            else
                    docker start docker_kudu-tserver-1_1
    fi
    
    if ( $TSERVER2 == "true" );
            then
                    echo "docker_kudu-tserver-2_1 had started"
            else
                    docker start docker_kudu-tserver-2_1
    fi
    

    数据分区策略

    TODO

    原理简说

    底层数据模型

    kudu的底层数据文件的存储,自行开发了一套可基于Table/Tablet/Replica(冗余)视图级别的底层存储系统。
    这一套底层存储的优点:

    • 可提供快速的列式查询
    • 可支持快速的随机更新
    • 可提供更为稳定的查询性能保障
      底层架构如下:


      kudu底层存储.jpg

      一张table按照分区策略分成若干个tablet,每个tablet包括MetaData元信息及若干个Rowset;

    • RowSet包含一个MemRowSet以及若干个DiskRowSet,DiskRowSet中包含一个BloomFile、AdhocIndex、UndoFile、RedoFile、BaseData、DeltaMem。
    • MemRowSet:
      用于新数据 insert 以及已经在 MemRowSet 中的数据的更新,一个MemRowSet 写满后悔将数据刷到磁盘形成若干个DiskRowSet,默认是1G或者120S。
    • DiskRow:
      用于老数据的变更,后台定期uiDiskRowSet做compaction,已删除没用的数据以及合并历史数据,减少查询过程中的IO开销。
      • BloomFile:
        根据一个DiskRowSet中的key生成一个Bloom Filter,用于快速模块定位某个key(这个key是根据分区策略流入该Tablet的record primary key,因此这就是为什么kudu的record一定要有primary key的原因)是否存在于该 DiskRowSet中。
      • Ad_hocIndex:
        是record主键的索引,用于定位key在DiskRowSet中具体的偏移位置。
      • BaseData
        是MemRowSer Flush下来的数据,按列存储,按主键有序,简而言之,该文件中才是存放真正的Table数据。
      • UndoFile
        是基于BaseData之前时间的历史数据,通过在BaseData上apply UndoFile中的记录,可以获得历史数据。
      • RedoFile
        是基于BaseData之后时间的变更记录,通过在BaseData上apply RedoFile中的记录,可获得较新的数据。
      • DeltaFile
        DiskRowSet中BaseData不会直接接受数据变更,而是先将变更写到内存中,写满后flush到磁盘形成RedoFile。

    工作流程

    整体工作流

    在了解了上述的底层数据模型之后,当一次MemRowSet达到规定的体量之后刷新到磁盘进行持久化成DiskRowSet。于此同时基础数据会进入DiskRowSet中的BaseData中存储,与此同时,每份DiskRowSet都会在内存中有一个对应的DeltaMemStore,负责记录该DiskRowSet后续的数据变更(更新、删除)。DeltaMenStore内部维护一个B-树索引映射到每个row_offset对应的数据变更。DeltaMenStore数据增长到一定程度后转换成二进制文件存储到磁盘形成DeltaFile文件。随着BaseData对应数据的不断变更,DeltaFile会慢慢增长。


    数据变更流程.jpg

    数据写入流程

    数据写入流程,有两个主要的步骤:

    • Tablet按对应策略路由
    • 判断当前record主键是否已经存在于路由的tablet中
      流程图:
      kudu数据写入流程.jpg
      流程梳理
    1. 对于分区策略路由没有太多好说的,kudu中记录进入tablet的分区路由策略有三种,range、hash、混合,master只需要根据记录的primary key进行计算得出tablet即可。
    2. 因为主键的唯一性,kudu有严格的要求,因此在记录写入之前先判断主键是否存在尤为的关键,在熟悉了kudu底层数据模型之后,会发现路由到的tablet中有很多的RowSet,这些RowSet中有大量的数据,因此当插入一条记录就需要对比所有的RowSet中所有的记录就显得非常的“吃力”。因此在判重时,尽量减少RowSet文件的扫描就成了首要因素,步骤如下:
    • 每个RowSet的Primary Key都有各自区间,先判断新Record的Primary Key符合哪些区间,筛选出区间对应的RowSet准备进行后续操作判断,若没有符合的RowSet则说明不会有Primary Key冲突,放心写入MemRowSet即可。
    • 若第一步筛选出RowSet,则说明,新Record的Primary Key可能与这些RowSet中记录有冲突需要进一步筛选,在熟悉了kudu底层数据模型之后,知道在每个RowSet中都有BloomFile,拿着Primary Key进行Bloom之后去判断key是否存在于Bloom Filter中,若不存在,则说明数据一定不存在与Bloom Filter中,则可以大胆的写入MemRow中,若有些RowSet的BloomFile中存在新纪录的Primary Key,则需要筛选出这些RowSet进行后一步的筛选,因为BloomFilter存在,不一定数据一定存在,这一点不熟悉的伙伴可以看一下Bloom Filter。
    • 若上一步某些RowSet依然被命中,那就需要针对这些RowSet进行最后一步判断,因为每个RowSet中都有Ad_hoxIndex文件,拿着新Primary Key进行索引查询,查看是否能找到具体记录,若索引中未命中Primary Key,则说明该记录可以写入MemRowSet中,若命中了,则说明经过这三步的判断,可以判定出新记录以及存在,无法插入,对外报错即可。

    数据查询流程

    数据查询流程响应比较简单一些,但是kudu中数据变更并不会直接应用到数据落到磁盘,因此某一时刻的数据其实是DiskRowSet中的BaseData记录与变更文件记录的应用。


    kudu数据读取流程.jpg
    • 读请求进入kudu
    • Master Server根据SQL中的信息初步筛选出符合记录的Tablets
    • 每个Tablet都有若干个RowSet,将所有Tablet中的所有RowSet筛选出来之后,进行主键范围判断,找出符合primary key范围的RowSet,读取这些RowSet中的BaseData。
    • 加载对应RowSet的delta stores与已经在磁盘的delta file,两者合并,应用所有变更。
    • 拿到上述两个步骤的数据之后,再与内存中MemRowSet数据进行Union合并返回给Client。

    数据更新流程

    数据更新流程比较重要的一步与数据写入流程相似,都是要先判断record的primary key,唯一不同的是,更新流程更希望数据已经存在及希望primary key命中。


    kudu数据更新流程.jpg
    • Master Server根据SQL中的信息初步筛选出符合记录的Tablets
    • 数据写入流程类似进行筛选出命中record primary key的RowSet
    • 若不存在对应的RowSet则说明需要更新的记录不存在并报错,若RowSet存在,则根据kudu底层数据模型,拿到RowSet中的AdhocFile索引文件获取记录的偏移row_offset
    • 最后将变更写到delta Store中

    相关文章

      网友评论

          本文标题:Kudu快速入门与原理介绍

          本文链接:https://www.haomeiwen.com/subject/flzbxltx.html