hbase读写流程

时间:2023-03-09 19:40:57
hbase读写流程

一. Hbase读流程

  1. META表记录着表的原信息,根据rowkey查询META表,获取所在region信息
  2. 客户端去相应的regionServer查询数据,先查询memStore(memstore是一个按key排序的树形结构缓冲区),有就返回,没有继续查找
  3. 查询regionServer的读缓存BlockCache是否存在rowkey的对应数据,有就返回,没有就继续查询。每次get一次时,hbase把相邻的一段数据也放到内存中缓存起来,方便顺序读
  4. 查询HFile中是否有相应记录
    (1)hfile的block索引会放在内存中,block是一段氛围内的键值对,通过rowkey找到block
    (2)下载hfile查找记录

二. 写流程

  1. client向region server提交写请求
  2. region server找到目标region
  3. region检查数据是否与schema一致
  4. 如果客户端没有指定版本,则获取当前系统时间作为数据版本
  5. 将更新写入WAL log (hlog)
  6. 将更新写入Memstore
  7. 判断Memstore的是否需要flush为Store文件。

    每 一个put的操作实际上是RPC的操作,它将客户端的数据传送到服务器然后返回,这只适合小数据量的操作,如果有个应用程序需要每秒存储上千行数据到 HBase表中,这样处理就不太合适了。HBase的API配备了一个客户端的写缓冲区,缓冲区负责收集put操作,然后调用RPC操作一次性将put送 往服务器。默认情况下,客户端缓冲区是禁止的。可以通过自动刷写设置为FALSE来激活缓冲区。 table.setAutoFlush(false);void flushCommits () throws IOException这个方法是强制 将数据写到服务器。用户还可以根据下面的方法来配置客户端写缓冲区的大小。 void setWritaeBufferSize(long writeBufferSize) throws IOException;默认大小是 2MB,这个也是适中的,一般用户插入的数据不大,不过如果你插入的数据大的话,可能要考虑增大这个值。从而允许客户端更高效地一定数量的数据组成一组通 过一次RPC请求来执行。给每个用户的HTable设置一个写缓冲区也是一件麻烦的事,为了避免麻烦,用户可以在

三.Hbase优化

  1. 行健设计
    (1)使用复合行健 (使用更多的条件查询) eg: 上述问题采用( 手机号倒置 : 时间戳倒置 )
    (2)行健要尽量离散而不是连续 , 使得连续插入的记录分散到多个HregionServer中 , 查询时达到并发查
    (3)尽量保证行健的数据长度短 , 减少Hfile加载到内存的内存空间

    表存储数据,按照行健存储,划分region时,也是按照region划分
    热点问题 : hbase的查询插入集中在某几个region中,不能分散.
    (时间戳 手机号) 存储
    eg: 不能用时间戳作为行健, 时间戳单调递增, 添加数据时会全部写在一个region, 降低并发查询添加效率
    可以把手机号倒置作为行健, 因为手机号末尾数字1-9等概率,可以做到分散存储

  2. 布隆过滤器
    (用一个数组,数组的每个元素的值是0或1,表示该位置是否存在数据, 数组角标是被判断集合元素值的hash值与数组长度取模)
    用极小的空间判断一个元素不在一个集合中
    (1)极小空间 : 一个位数组
    (2)判断不在一个集合 : 这个位数组, 元素值只是0/1表示该位是否有元素; 元素哈希值对维数组长度取模
    (3)把位数组模位置上的元素置1 . 当查询时发现该位置为0说明元素不在集合中 . 这种过滤器不能100%确定元素的存在, 但是能发现元素不在集合中

    【注】:客户端查数据,先查到数据属于哪个region,根据region找到hfile ,结合block的索引和hfile在磁盘中找到block块, 再根据行健,列祖,列标识符找到block中的kv键值对. hbase把查到的数据缓存在内存中. 使用bloom过滤器. 在查找结果缓存阶段,可以快速判断要查找的键值对是否已经在内存中
    可以设置对每个行健设置bloom过滤器. 也可以对每个列设置bloom过滤器

  3. 列族的块
    (1)HFile读取数据的最小单位是block , 这个block默认大小是64k , 查找某一个值时 , 要遍历这个块中的所有
    (2)如果存在大量随机读 , block块小一点好
    (3)如果存在大量顺序读 , block块大一点好

  4. 设置autoFlush=false