zoukankan      html  css  js  c++  java
  • Hbase读写流程

    注意:首先声明一点的是Hbase是一个读数据比写数据复杂(慢)的框架,所以先来看下写数据流程(以下为Hbase1.3.1版本)

               另外:读写数据均与master无关

    Hbase写数据流程

    1. Client 先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server(保存在了zookeeper的/hbase/meta-region-server中)。
    2. 访问对应的 Region Server,获取 hbase:meta 表,根据读请求的 namespace:table/rowkey,查询出目标表位于哪个 Region Server 中的哪个 Region 中。并将该 table 的 region 信息以及 meta 表的位置信息缓存在客户端的 meta cache,方便下次访问。 
    3. 与table所在的 Region Server 进行通讯。
    4. 将数据顺序写入(追加)到 WAL(预写入日志)以便在服务器没有flush到storefile时宕机通过wal进行数据重建。
    5. 将数据写入对应的 MemStore,数据会在 MemStore 进行排序。
    6. 向客户端发送 ack。
    7. 等达到 MemStore 的刷写时机后,将数据刷写到 StoreFile。

            如果是以前0.9x版本的时候,hbase还维护了一个叫做-ROOT-的表,用来存储meta的位置,然后meta表中存储实际表的位置。基于考虑到将来由于meta表过大而进行split,也会形成多个Region,然而在zookeeper中就不能用一条数据存储多个Region形成的meta表的信息。经过长期生产上的测试,发现meta表一般不会由于数据量大而进行split,假如meta表的数据量确实很大了,在做校验进行split时,如果是meta表,就不进行split,所以meta表就会一直在一个Region上,最终舍弃了-ROOT-表。

    解读步骤4:(具体源码中是这样的)在HRegion类中

    1. 上锁,读写分离(java.util.concurrent.locks.Lock)
    2. 传入数据添加一个时间戳
    3. 内存构建WAL
    4. 向WAL中写日志,并不同步到磁盘
    5. 数据写入memstore
    6. 释放锁
    7. 同步wal
    8. 如果同步wal失败(指的是数据在wal在写到hdfs时失败),事务回滚,从内存中将数据remove

    Hbase读数据流程

    Block Cache:读缓存(如果是从StoreFile里面读取的数据,不是直接返回给客户端,而是先写入BlockCache,再返回给客户端。)

    作用是:读数据是会扫描磁盘的,本身很慢。所以用一个读缓存来加速查询。当读缓存中的数据量很大的时候会根据LRU算法删除一些数据。

    LRU:最近最少使用

    1. Client 先访问 zookeeper,获取 hbase:meta 表位于哪个 Region Server。
    2. 访问对应的 Region Server,获取 hbase:meta 表,根据读请求的 namespace:table/rowkey,查询出目标数据位于哪个 Region Server 中的哪个 Region 中。并将该 table 的 region 信息以及 meta 表的位置信息缓存在客户端的 meta cache,方便下次访问。
    3. 与目标 Region Server 进行通讯。
    4. 分别在 Block Cache(读缓存),MemStore 和 Store File中查询目标数据,并将查到的所有数据进行合并(marge)。此处所有数据是指同一条数据的不同版本(time stamp)或者不同的类型(Put/Delete),然后返回时间戳大的一条数据。
    5. 将从文件中查询到的数据块缓存到Block Cache。
    6. 将合并后的最终结果返回给客户端。

    问题:

    为什么不直接先读写缓存的数据然后直接返回?

            举例:先写一条数据到table1里面,不加时间戳,系统默认。并手动将数据flush到hdfs

                       put table1  1001 ‘info:name’ zhangsan

                       再添加一条比上一条数据时间戳小的数据

                       put table1 1001 'info:name' lisi 1503268558890

                       此时按理来说是不是应该返回 zhangsan?

                       如果读数据的时候不读storefile,只读写缓存。那么读出来的lisi就是错误的数据。

    为什么读了读缓存还要再读storefile和写缓存?

                  首先,一个表上面的数据是当memstore达到一定大小或者一定时间默认flush到hdfs上面的(或者手动flush)形成一个一个的文件。

                   此时去table1上面读取一条数据,并将数据缓存到BlockCache中,和memStore中的marge后返回。此时的BlockCache中有了当前时间StoreFile中的数据,如果没有新添加,不用读取StoreFile。

                   此时,再添加一条数据,并flush到StoreFile中,形成一个文件。

                   那么,接下来再读取数据的时候,还会去磁盘扫描BlockCache没有扫描过的新文件,并加载到blockcache中,再和memstore中的数据进行marge返回。

    综上:hbase是一个读比写复杂的一个框架。

                  

            

  • 相关阅读:
    linux安装oracle
    echarts柱状图,改变柱状颜色
    JS实现键盘监听(包括组合键)
    css根据屏幕大小切换样式
    (转)Win10下PostgreSQL10与PostGIS安装
    navicat连接PostgreSQL报:column “rolcatupdate” does not exist ...错误的解决办法
    大屏FAQ
    大屏介绍
    大屏模板制作
    大屏做成这样,领导不重用你都难
  • 原文地址:https://www.cnblogs.com/Rabcheng/p/12795413.html
Copyright © 2011-2022 走看看