精华内容
下载资源
问答
  • Hbase快速入门

    千次阅读 2018-04-06 23:45:07
    【1,hbase是什么?】答:hbase是一个开源的然后非关系分布式数据库,【2,hbase是数据保存在哪里?】答:hbase的数据保存在hdfs上,但还有少量...hdfs中数据通常是顺序读取,原因就是吞吐能力,hbase是随机写入和访问

    【1,hbase是什么?】

    答:hbase是一个开源的然后非关系分布式数据库,

    【2,hbase是数据保存在哪里?】

    答:hbase的数据保存在hdfs上,但还有少量数据是保存在内存中的。

    【3,hbase有哪些特性?】

    答:高可靠,高并发读写,面向列,可伸缩,易构建.

    优势:

    • 海量数据存储。hdfs分布式文件系统存储数据
    • 快速随机访问。hdfs中数据通常是顺序读取,原因就是吞吐能力,hbase是随机写入和访问。
    • 大量写操作的应用。

    【4,hbase中什么叫面向列?】

    答:数据存储有两种,一种是面向行存储(关系型数据库),一种是面向列存储。

    面向行存储特点:

    1.优点:就是写入的时候一次性要完成,并且它是保证你数据的完整性.每一列都必须有值,而且必须保证其完整性。

    2.缺点:读数据的时候会产生很多冗余的数据。

    • select name from user ;
    • 内部在读取数据的时候是把整条记录都读取出来

    面向列的特点:

    1.优点:读取数据的时候不会产生冗余的数据。

    • select name from user ;
    • 内部在读取数据的时候是只把列存储的name直接读取出来,其他字段不会去查。

    2.缺点:写入数据的效率差,不能保证数据的完整性。

    【5,列存储的具体内容】

    假设说它分了四列(如下图8所示),列存储它就是分了四个不同的文件,每一个文件它的存储是这样存的,比如说你列字段里面都有值了,我们只做A和B和C和name和zhangsan和list做例子,其中第一个文件应该是这么存的: A \tzhangsan,B \t lisi,因为c没有name,所以就不存了

    图8:

    **NOTE:**Nosql里面它不是要求你所有的字段都是要有值的,因为是稀疏存储.

    【6,Hbase主要应用在哪些领域? 】

    • 互联网搜索引擎数据存储
    • 海量数据写入
    • 消息中心
    • 内容服务系统(schema-freee)
    • 大表复杂&多维度索引
    • 大批量数据读取

    【7,Hbase的数据模型? 】

    图12

    rowkey在整个的hbase表里面一定是按照你的字节去排序.行键其实就是hbase表的主键。

    • 什么是Column Family?

      每一条记录里面或者是在你去建Hbase的Schema设计的时候要指定好Column Family,那什么是Column Family呢?你可以认为就是一个列族,但是它这个列你可以在列族里面又可以细分出多个列出来,就是Column Family下面可以细分出多个子列,那这些子列称为Column qualifiar。

    • 什么是时间戳?

      简单点说就是版本号,需要注意的是时间戳是按照倒序排序的。每次修改列族的值, 不是在原来的基础上修改,而是帮你去重新复制一份记录出来,然后再复制出来的记录上去修改名字,原来这个名字这个记录,它会以某一种版本的形式给你记录起来明白了把?就是通过一个时间戳给你记录起来。

    下面看两外一个例子

    1. 当我们去读数据的时候默认是将最新的时间戳这个记录读取出来,不是把所有时间戳的数据都读出来。
    2. a这个columnqualifier它这里面是包含了很多的一些列的名字,但是b里面就包含了一个,那这个columnqualifier这个设计就可以允许,就是hbase设计表的时候就非常的灵活。

    Hbase你的检索能够更快速并且你的数据的维护更合理,那它这里面会体现了一个三维有序的这么一个特点

    什么叫做三维有序

    第一个纬度就是你的rowkey
    第二个纬度就是它的列(cf和cq)
    第三维就是version-value

    【8,Hbase的物理模型? 】

    数据模型和物理模型这两个是有什么差异,这个大家应该是没有什么问题了,就是物理模型是称数据模型的实现。

    Hbase的一张表其实它是由一个或多个Hreging来组成的,那什么叫做Hreging呢?那在Hreging大家可以暂时先认为它就是一个区域或者分区,所以认为一个Hbase一张表它是由一个或多个分区组成,然后并且这张表的数据是按照rowkey进行字典排序的,我们看上图23图中的图,相当于就是一张用户表,就类似于刚才那张一样。

    每一个region的内部他们这个rowkey按照顺序排序的,而且region与region之间也是按照这种全局排序的,这是一个整体的一个物理的逻辑图。


    那这个region呢因为是有大小概念的,有的region包含的记录多也有的region包含的记录少,那什么时候会region会变多有时候会变少?因为你这个数据是随着你的插入,使这个region是不断的增大。

    如果数据是稀疏的:

    如果要插入88,在第2个region中,那么会在99的位置开个口子,将88填充进去。随着不断的插入,第2个region不断增大,region就应该一分为二,变成76~100。

    【9,什么情况下region会自动分裂?】

    这个Region他有一个默认配置可以配,默认是10G。一个region里面它所管辖的数据里面超过了10个G的话,它会自动的去切分,region你可以认为是在Hbase整个集群里面是数据分布的一个最小的单位。

    region它仅只能是属于某一个机器的,那这个机器的名字叫做regionService,一个region它只属于一个regionService,但是不允许一个region它既属于regionService又属于另外一个regionService。

    总结:
    1,一个region只能属于一个regionService.
    2,一个regionServer可以包含多个region(不同表的region)。
    3,region代表一个区域,是一个逻辑概念。

    【10,如果在列族中既有写又有读,hbase是怎么处理的?】

    只修改里面其中一个字段,其他字段不修改,把整行记录加锁明白这意思把?所以Hbase它是按行锁定的

    【11,regionService用来干什么的?】

    主要是负责用户的IO请求.

    • 什么是IO请求

      就是读和写.读和写的目的是干嘛?不就是操作数据嘛对不对?那它的数据哪里来的呢?就是在这个HDFS上,这个RegionService就给你提供了这么一个IO的一个入口然后供你客户端来对HDFS进行一个交互,所以RegionService在这上面是一台机器,但是在这个机器上面它会运行着一个进程,这个进程就叫做HRegionServer,这是进程,它这个进程是在Hbase里面是属于一个非常非常核心的一个进程,一个HRegionServer内部管理了一系列的HRegion对象.


    【12,Hregion与region区别?】 Region是你对应Table的一个Region,然后HRegion相当于是对着Region一个封装,你可以简单理解就是这个Region就是逻辑概念,而HRegion就是一个物理概念。 **【13,HTable ,Hbase,Hstore HFile?】**
    • HTable

      就是表——>表

    • Hstore

      Hbase你是可以分多个Column Family的对吧,一个Column Family就是一个Hstore,你可以认为就是一系列的文件,你简单理解就是一个文件.

    Hstore由两部分组成:

    1. 内存区(memstore)
    2. HFiles真正落入磁盘的数据的一个数据

    首先把你的数据往memstore去写,当写到一定程度的时候,它就会把这个内存里面的数据做一个内存溢并写出多个Hfiles出来。什么叫有序KV?有序KV这个之前我们讲mapreduce的时候,那不是有一个排序嘛?按key进行排序这不就是一个有序kv嘛对吧.

    Hbase的这个memstore大小是:128m.这个系统默认的128m可以改的,一旦达到了这个128m的时候它就开始往磁盘上存。

    mapreduce里面memstore它的默认的空间大小是多大来着?是100m

    通过下面图看出他们的联系:

    BlockCache是一个也是类似于像menStor一样是一块内存区域,它这个缓存区是用来读的。

    BlockCache就是一个读缓存,一个RegionService它可以管理着很多个Region是吧?然后这每一个Region里面又包含了很多的Hstore,然后每一个Hstore里面它又包含了一个MemStore又包含着很多的StoreFile,其实StoreFile本质就是一个HFile,HFile就直接落地到了你的DataNode上面去了。

    【14,hbase的系统架构】
    Hbase整个系统架构就主要包含了四个部分是吧?那就是Client和Master和Region Server和Zookeeper。

    展开全文
  • HBase写入原因

    2018-10-08 13:56:00
    HBase写可以分为单行写和批量写: 单行写使用了void put(Put put) throws IOException方法 在创建Put对象时使用构造器: Put(byte[] row) 传入一个行键 并使用add(byte[] famliy,byte[] qualifier)方法指定...

    写入:

    HBase写可以分为单行写和批量写:

    单行写使用了void put(Put put) throws IOException方法

    在创建Put对象时使用构造器:

    Put(byte[] row) 传入一个行键

    并使用add(byte[] famliy,byte[] qualifier)方法指定列族和列名即可

    然后调用HTable的put方法就可以提交了

     

    HBase客户端提供了一个写缓冲区,可以利用void setAutoFlush(false)来激活缓冲区

    如果使用了缓冲区,需要调用void flushCommits()方法来提交

     

    客户端获取meta表地址

    提交之后,客户端会先向zookeeper获取到meta表的地址:在zk中的/hbase/meta-region-server中

     

    获取到之后会缓存这个地址

    根据rowkey获取到要写入的数据所在的region Server,然后缓存这个region Server 的地址

    并向服务器请求写入数据

     

    服务器端写入:

    服务器端接收到数据之后,先将数据写入wal日志中,然后写入memStore中,就会向客户端返回写入成功

    这就是HBase写入快的原因

    具体详情可以参见:

    http://hbasefly.com/2016/03/23/hbase_writer/

     

    转载于:https://www.cnblogs.com/tianyafu/p/9753933.html

    展开全文
  • HBase快速入门系列(10) | HBase知识点总结(建议收藏!)

    千次阅读 多人点赞 2020-06-07 09:24:21
      此篇为大家带来的是HBase知识点总结(建议收藏!)。 目录1. 读写请求会集中到某一个RegionServer上 如何处理(数据倾斜)2. hbase查询一条记录的方法是什么?Hbase写入一条记录的方法是什么?3. 描述hbase的...

      大家好,我是不温卜火,是一名计算机学院大数据专业大二的学生,昵称来源于成语—不温不火,本意是希望自己性情温和。作为一名互联网行业的小白,博主写博客一方面是为了记录自己的学习过程,另一方面是总结自己所犯的错误希望能够帮助到很多和自己一样处于起步阶段的萌新。但由于水平有限,博客中难免会有一些错误出现,有纰漏之处恳请各位大佬不吝赐教!暂时只有csdn这一个平台,博客主页:https://buwenbuhuo.blog.csdn.net/

      此篇为大家带来的是HBase知识点总结(建议收藏!)。


    标注:
    此处为反爬虫标记:读者可自行忽略
    

    20
    原文地址:https://buwenbuhuo.blog.csdn.net/

    1. 读写请求会集中到某一个RegionServer上 如何处理(数据倾斜)

    • 产生热点问题的原因:
    • hbase的中的数据是按照字典序排序的,当大量连续的rowkey集中写在个别的region,各个region之间数据分布不均衡;
    • 创建表时没有提前预分区,创建的表默认只有一个region,大量的数据写入当前region
    • 创建表已经提前预分区,但是设计的rowkey没有规律可循
    • 热点问题的解决方案:
    • 随机数+业务主键,如果想让最近的数据快速get到,可以将时间戳加上。
    • Rowkey设计越短越好,不要超过10~100个字节
    • 映射regionNo,这样既可以让数据均匀分布到各个region中,同时可以根据startkey和endkey可以get到同一批数据

    2. hbase查询一条记录的方法是什么?Hbase写入一条记录的方法是什么?

      Hbase查询单一数据采用的是get方法,写入数据的方法为put方法(可在回答时说些具体的实现思路)

    3. 描述hbase的rowkey的设计原理

    Rowkey设计时需要遵循三大原则:

    • 唯一性原则

      rowkey在设计上保证其唯一性。rowkey是按照字典顺序排序存储的,因此,设计rowkey的时候,要充分利用这个排序的特点,将经常读取的数据存储到一块,将最近可能会被访问的数据放到一块。

    • 长度原则

      rowkey是一个二进制码流,可以是任意字符串,最大长度 64kb ,实际应用中一般为10-100bytes,以byte[] 形式保存,一般设计成定长。建议越短越好,不要超过16个字节,原因如下:数据的持久化文件HFile中是按照KeyValue存储的,如果rowkey过长,比如超过100字节,1000w行数据,光rowkey就要占用100*1000w=10亿个字节,将近1G数据,这样会极大影响HFile的存储效率;MemStore将缓存部分数据到内存,如果rowkey字段过长,内存的有效利用率就会降低,系统不能缓存更多的数据,这样会降低检索效率。目前操作系统都是64位系统,内存8字节对齐,控制在16个字节,8字节的整数倍利用了操作系统的最佳特性。

    • 散列原则

      如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位作为散列字段,由程序随机生成,低位放时间字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率

      加盐:如果rowkey按照时间戳的方式递增,不要将时间放在二进制码的前面,建议将rowkey的高位作为散列字段,由程序随机生成,低位放时间字段,这样将提高数据均衡分布在每个RegionServer,以实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息,所有的数据都会集中在一个RegionServer上,这样在数据检索的时候负载会集中在个别的RegionServer上,造成热点问题,会降低查询效率加盐:这里所说的加盐不是密码学中的加盐,而是在rowkey的前面增加随机数,具体就是给rowkey分配一个随机前缀以使得它和之前的rowkey的开头不同。分配的前缀种类数量应该和你想使用数据分散到不同的region的数量一致。加盐之后的rowkey就会根据随机生成的前缀分散到各个region上,以避免热点
      哈希:哈希会使同一行永远用一个前缀加盐。哈希也可以使负载分散到整个集群,但是读却是可以预测的。使用确定的哈希可以让客户端重构完整的rowkey,可以使用get操作准确获取某一个行数据
      反转:第三种防止热点的方法时反转固定长度或者数字格式的rowkey。这样可以使得rowkey中经常改变的部分(最没有意义的部分)放在前面。这样可以有效的随机rowkey,但是牺牲了rowkey的有序性。反转rowkey的例子以手机号为rowkey,可以将手机号反转后的字符串作为rowkey,这样的就避免了以手机号那样比较固定开头导致热点问题
      时间戳反转:一个常见的数据处理问题是快速获取数据的最近版本,使用反转的时间戳作为rowkey的一部分对这个问题十分有用,可以用Long.Max_Value - timestamp 追加到key的末尾.

    4. hbase中compact的用途是什么,什么时候触发,分为哪两种,有什么区别。

      在HBase中,每当memstore的数据flush到磁盘后,就形成一个storefile,当storefile的数量越来越大时,会严重影响HBase的读性能 ,HBase内部的compact处理流程是为了解决MemStore Flush之后,文件数目太多,导致读数据性能大大下降的一种自我调节手段,它会将文件按照某种策略进行合并,大大提升HBase的数据读性能。

    主要起到如下几个作用:

    1. 合并文件
    2. 清除删除、过期、多余版本的数据
    3. 提高读写数据的效率

    HBase中实现了两种compaction的方式:
    minor and major. Minor compactions will usually pick up a couple of the smaller adjacent StoreFiles and rewrite them as one. Minors do not drop deletes or expired cells, only major compactions do this. Sometimes a minor compaction will pick up all the StoreFiles in the Store and in this case it actually promotes itself to being a major compaction.

    这两种compaction方式的区别是:

    • Minor操作只用来做部分文件的合并操作以及包括minVersion=0并且设置ttl的过期版本清理,不做任何删除数据、多版本数据的清理工作。
    • Major操作是对Region下的HStore下的所有StoreFile执行合并操作,最终的结果是整理合并出一个文件。

    compaction触发时机:

    • Memstore刷写后,判断是否compaction
    • CompactionChecker线程,周期轮询

    5. Hbase的原理 regionserver挂了 如何恢复数据 ?新的数据从Hlog里读出来是如何恢复的

      引起RegionServer宕机的原因各种各样,有因为Full GC导致、网络异常导致、官方Bug导致(close wait端口未关闭)以及DataNode异常导致等等

      HBase检测宕机是通过Zookeeper实现的, 正常情况下RegionServer会周期性向Zookeeper发送心跳,一旦发生宕机,心跳就会停止,超过一定时间(SessionTimeout)Zookeeper就会认为RegionServer宕机离线,并将该消息通知给Master

      一旦RegionServer发生宕机,HBase都会马上检测到这种宕机,并且在检测到宕机之后会将宕机RegionServer上的所有Region重新分配到集群中其他正常RegionServer上去,再根据HLog进行丢失数据恢复,恢复完成之后就可以对外提供服务,整个过程都是自动完成的,并不需要人工介入.
    1

    6. 讲一下Hbase,Hbase二级索引用过吗

      默认情况下,Hbase只支持rowkey的查询,对于多条件的组合查询的应用场景,不够给力。如果将多条件组合查询的字段都拼接在RowKey中显然又不太可能。全表扫描再结合过滤器筛选出目标数据(太低效),所以通过设计HBase的二级索引来解决这个问题。

      这里所谓的二级索引其实就是创建新的表,并建立各列值(family:column)与行键(rowkey)之间的映射关系。这种方式需要额外的存储空间,属于一种以空间换时间的方式

    7. Hbase如何优化的

    内存优化

    • 垃圾回收优化:CMS, G1(Region)
    • JVM启动:-Xms(1/64) –Xmx(1/4)

    Region优化

    • 预分区
    • 禁用major合并,手动合并

    客户端优化

    • 批处理

    8. hbase中查询表名为buwenbuhuo,rowkey为user开头的

    HBase Shell : scan 'buwenbuhuo', FILTER => "PrefixFilter ('user')"
    
    HBase JavaAPI : 
    Scan scan = new Scan();
    Filter filter = new PrefixFilter(Bytes.toBytes("user"));
    scan.setFilter(filter);
    
    

    9. hbase表的设计有哪些注意点

    • 行键的结构是什么的并且要包含什么内容
    • 表有多少个列族?
    • 列族中都要放什么数据?
    • 每个列族中有多少个列?
    • 列名是什么?尽管列名在创建表时不需要指定,你读写数据是需要用到它们。
    • 单元数据需要包含哪些信息?
    • 每个单元数据需要存储的版本数量是多少?

    10. HBase与mysql得区别

    数据存储的方式:

    • Mysql面向行存储数据,整个行的数据是一个整体,存储在一起。
      HBase面向列存储数据,整个列的数据是一个整体,存储在一起,有利于压缩和统计

    数据之间的关系

    • Mysql存储关系型数据,结构化数据
    • Hbase存储的非关系型数据,存储结构化和非结构化数据

    事务处理

    • Mysql数据库存在事务,因为着重于计算(算法)
    • Hbase数据库侧重于海量数据的存储,所以没有事务的概念

    储存容量

    • Hbase依托于Hadoop,容量非常大,一般都以PB级为单位存储
    • Mysql存储数据依赖于所在的硬件设备

      本次的分享就到这里了,


    11

      好书不厌读百回,熟读课思子自知。而我想要成为全场最靓的仔,就必须坚持通过学习来获取更多知识,用知识改变命运,用博客见证成长,用行动证明我在努力。
      如果我的博客对你有帮助、如果你喜欢我的博客内容,请“点赞” “评论”“收藏”一键三连哦!听说点赞的人运气不会太差,每一天都会元气满满呦!如果实在要白嫖的话,那祝你开心每一天,欢迎常来我博客看看。
      码字不易,大家的支持就是我坚持下去的动力。点赞后不要忘了关注我哦!

    13
    12

    展开全文
  • Hbase

    千次阅读 多人点赞 2019-10-22 20:14:12
    文章目录Hbase来源:应用:行业:Hbase定义:Hbase特性:Hbase shellnamespaceDDLDMLHbase Java Api依赖HbaseUtilsHbaseDemoHbase过滤器Hbase原理架构Hbase读写流程写数据流程Hbase的存储机制存储模型布隆过滤器...

    Hbase

    来源:

    • 解决随机近实时的高效的读写
    • 解决非结构化的数据存储

    应用:

    • 可以存储非结构化的数据(用户、商品、文章的画像属性)

    • 被用来做实时(整合flume、storm、streaming等)

    • 存储历史明细数据(较少)

    • 存储结果数据(数仓,Kylin预执行数据就是放到Hbase中)

    行业:

    • 通信、银行、金融等

    Hbase定义:

    • Hadoop的数据库
    • Hadoop的分布式、开源的、多版本的非关系型数据库
    • Hbase存储Key-Value格式,面向列存储,Hbase底层为字节数据,没有数据类型一说

    Hbase特性:

    • 线性和模块化可扩展性
    • 严格一致的读写
    • 表的自动和可配置分片
    • RegionServer之间的自动故障转移支持
    • 方便的基类,用于通过Apache HBase表备份Hadoop MapReduce作业
    • 易于使用的Java API用于客户端访问
    • 块缓存和布隆过滤器用于实时查询
    • 通过服务器端过滤器查询谓词下推
    • Thrift网关和支持XML,Protobuf和二进制数据编码选项的REST-ful Web服务
    • 可扩展的基于Jruby的(JIRB)外壳
    • 支持通过Hadoop指标子系统将指标导出到文件或Ganglia;或通过JMX

    Hbase shell

    namespace

    1. list_namespace:查询所有命名空间
    hbase(main):001:0> list_namespace
    NAMESPACE                                                                       
    default                                                                         
    hbase
    
    2. list_namespace_tables : 查询指定命名空间的表
    hbase(main):014:0> list_namespace_tables 'hbase'
    TABLE
    meta
    namespace
    
    3. create_namespace : 创建指定的命名空间
    hbase(main):018:0> create_namespace 'myns'
    hbase(main):019:0> list_namespace
    NAMESPACE
    default
    hbase
    myns
    
    4. describe_namespace : 查询指定命名空间的结构
    hbase(main):021:0> describe_namespace 'myns'
    DESCRIPTION
    {NAME => 'myns'}
    
    
    5. alter_namespace :修改命名空间的结构
    hbase(main):022:0>  alter_namespace 'myns', {METHOD => 'set', 'name' => 'eRRRchou'}
    
    hbase(main):023:0> describe_namespace 'myns'
    DESCRIPTION
    {NAME => 'myns', name => 'eRRRchou'}
    修改命名空间的结构=>删除name
    hbase(main):022:0> alter_namespace 'myns', {METHOD => 'unset', NAME => 'name'}
    hbase(main):023:0> describe_namespace 'myns'
    
    6. 删除命名空间
    hbase(main):026:0> drop_namespace 'myns'
    
    hbase(main):027:0> list_namespace
    NAMESPACE
    default
    hbase
    
    7. 利用新添加的命名空间建表
    hbase(main):032:0> create 'myns:t1', 'f1', 'f2'
    

    DDL

    1. 查询所有表
    hbase(main):002:0> list
    TABLE                                                                           
    HelloHbase                                                                      
    kylin_metadata                                                                  
    myns:t1                                                                         
    3 row(s) in 0.0140 seconds
    
    => ["HelloHbase", "kylin_metadata", "myns:t1"]
    
    2. describe : 查询表结构
    hbase(main):003:0> describe 'myns:t1'
    
    {NAME => 'f1', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP
    _DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMP
    RESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '6553
    6', REPLICATION_SCOPE => '0'}                                                   
    {NAME => 'f2', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'false', KEEP
    _DELETED_CELLS => 'FALSE', DATA_BLOCK_ENCODING => 'NONE', TTL => 'FOREVER', COMP
    RESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '6553
    6', REPLICATION_SCOPE => '0'}
    
    3. 创建分片表
    hbase(main):007:0> create 'myns:t2', 'f1', SPLITS => ['10', '20', '30', '40']
    
    4. 修改表,添加修改列簇信息
    hbase(main):009:0> alter 'myns:t1', {NAME=>'info1'}
    hbase(main):010:0> describe 'myns:t1'
    
    5. 删除列簇
    hbase(main):014:0> alter 'myns:t1', {'delete' => 'info1'}
    hbase(main):015:0> describe 'myns:t1'
    
    6. 删除表
    hbase(main):016:0> disable 'myns:t1'
    hbase(main):017:0> drop 'myns:t1'
    

    DML

    用到的表创建语句:
    hbase(main):011:0> create 'myns:user_info','base_info','extra_info'
    
    1. 插入数据(put命令,不能一次性插入多条)
    hbase(main):012:0> put 'myns:user_info','001','base_info:username','张三'
    
    2. scan扫描
    hbase(main):024:0> scan 'myns:user_info'
    
    3. 通过指定版本查询
    hbase(main):024:0> scan 'myns:user_info', {RAW => true, VERSIONS => 1}
    hbase(main):024:0> scan 'myns:user_info', {RAW => true, VERSIONS => 2}
    
    4. 查询指定列的数据
    hbase(main):014:0> scan 'myns:user_info',{COLUMNS => 'base_info:username'}
    
    5. 分页查询
    hbase(main):021:0> scan 'myns:user_info', {COLUMNS => ['base_info:username'], LIMIT => 10, STARTROW => '001'}
    
    6. get查询
    hbase(main):015:0> get 'myns:user_info','001','base_info:username'
    hbase(main):017:0> put 'myns:user_info','001','base_info:love','basketball'
    hbase(main):018:0> get 'myns:user_info','001'
    
    7. 根据时间戳查询 是一个范围,包头不包尾
    hbase(main):029:0> get 'myns:user_info','001', {'TIMERANGE' => [1571650017702, 1571650614606]}
    
    8. hbase排序
    插入到hbase中去的数据,hbase会自动排序存储:
    排序规则:  首先看行键,然后看列族名,然后看列(key)名; 按字典顺序
    
    9. 更新数据
    hbase(main):010:0> put 'myns:user_info', '001', 'base_info:name', 'rock'
    hbase(main):011:0> put 'myns:user_info', '001', 'base_info:name', 'eRRRchou'
    
    10. incr计数器
    hbase(main):053:0> incr 'myns:user_info', '002', 'base_info:age3'
    
    11. 删除
    hbase(main):058:0> delete 'myns:user_info', '002', 'base_info:age3'
    
    12. 删除一行
    hbase(main):028:0> deleteall 'myns:user_info','001'
    
    13. 删除一个版本
    hbase(main):081:0> delete 'myns:user_info','001','extra_info:feature', TIMESTAMP=>1546922931075
    
    14. 删除一个表
    hbase(main):082:0> disable 'myns:user_info'
    hbase(main):083:0> drop 'myns:user_info'
    
    15. 判断表是否存在
    hbase(main):084:0> exists 'myns:user_info'
    
    16. 表生效和失效
    hbase(main):085:0> enable 'myns:user_info'
    hbase(main):086:0> disable 'myns:user_info'
    
    17. 统计表行数
    hbase(main):088:0> count 'myns:user_info'
    
    18. 清空表数据
    hbase(main):089:0> truncate 'myns:user_info'
    

    Hbase Java Api

    依赖

        <dependencies>
            <dependency>
                <groupId>org.apache.hbase</groupId>
                <artifactId>hbase-client</artifactId>
                <version>1.4.10</version>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.12</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>compile</scope>
            </dependency>
        </dependencies>
    

    HbaseUtils

    public class HbaseUtils {
    
        public static Configuration configuration = null;
        public static ExecutorService executor = null;
        public static HBaseAdmin hBaseAdmin = null;
        public static Admin admin = null;
        public static Connection conn = null;
        public static Table table;
        static {
            //1. 获取连接配置对象
            configuration = new Configuration();
            //2. 设置连接hbase的参数
            configuration.set("hbase.zookeeper.quorum", "mini01:2181,mini02:2181,mini03:2181");
            //3. 获取Admin对象
            try {
                executor = Executors.newFixedThreadPool(20);
                conn = ConnectionFactory.createConnection(configuration, executor);
                hBaseAdmin = (HBaseAdmin)conn.getAdmin();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static HBaseAdmin getHbaseAdmin(){
            return hBaseAdmin;
        }
        public static Table getTable(TableName tableName) throws IOException {
            return conn.getTable(tableName);
        }
        public static void close(HBaseAdmin admin){
            try {
                admin.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public static void close(HBaseAdmin admin,Table table){
            try {
                if(admin!=null) {
                    admin.close();
                }
                if(table!=null) {
                    table.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void close(Table table){
            try {
                if(table!=null) {
                    table.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        public static void showResult(Result result) throws IOException {
            CellScanner scanner = result.cellScanner();
            while(scanner.advance()){
                Cell cell = scanner.current();
                System.out.print("\t" + new String(CellUtil.cloneFamily(cell),"utf-8"));
                System.out.print(" : " + new String(CellUtil.cloneQualifier(cell),"utf-8"));
                System.out.print("\t" + new String(CellUtil.cloneValue(cell),"utf-8"));
            }
        }
    }
    

    HbaseDemo

    public class HbaseDemo {
        private  HBaseAdmin hBaseAdmin = null;
        private  Admin admin = null;
        @Before
        public void init(){
                hBaseAdmin = HbaseUtils.getHbaseAdmin();
        }
        @After
        public void after(){
            HbaseUtils.close(hBaseAdmin);
        }
        @Test
        public void tableExists() throws IOException {  //检查表是否存在
            //4. 检验指定表是否存在,来判断是否连接到hbase
            boolean flag = hBaseAdmin.tableExists("myns:user_info");
            //5. 打印
            System.out.println(flag);
        }
    
        @Test
        public void listNamespace() throws IOException { //遍历命名空间
            NamespaceDescriptor[] namespaceDescriptors = hBaseAdmin.listNamespaceDescriptors();
            // 打印
            for(NamespaceDescriptor namespaceDescriptor:namespaceDescriptors){
                System.out.println(namespaceDescriptor);
            }
        }
    
        @Test
        public void listTables() throws Exception{  //获取表的名字
            //获取指定命名空间下的表
            TableName[] tables = hBaseAdmin.listTableNamesByNamespace("myns");
            System.out.println("对应命名空间下的表名:");
            for (TableName table:tables){
                System.out.println(table);
            }
            tables = hBaseAdmin.listTableNames();
            System.out.println("所有表名:");
            for (TableName table:tables){
                System.out.println(table);
            }
        }
        @Test
        public void createNamespace() throws Exception{ //创建namespace
            hBaseAdmin.createNamespace(NamespaceDescriptor.create("eRRRchou").build());
        }
    
        @Test
        public void createTable() throws Exception{ //创建表
            HTableDescriptor descriptor = new HTableDescriptor(TableName.valueOf("myns:user_info"));
            //创建列簇
            HColumnDescriptor columnDescriptor1 = new HColumnDescriptor("base_info");
            columnDescriptor1.setVersions(1, 5); //设置列簇版本从1到5
            columnDescriptor1.setTimeToLive(24*60*60); //秒
            //创建列簇
            HColumnDescriptor columnDescriptor2 = new HColumnDescriptor("extra_info");
            columnDescriptor2.setVersions(1, 5);
            columnDescriptor2.setTimeToLive(24*60*60); // 秒为单位
            //绑定关系
            descriptor.addFamily(columnDescriptor1);
            descriptor.addFamily(columnDescriptor2);
            //创建表
            hBaseAdmin.createTable(descriptor);
        }
        @Test
        public void deleteTable() throws Exception{ //删除Family
            hBaseAdmin.disableTable("myns:user_info");
            hBaseAdmin.deleteTable("myns:user_info");
        }
    
        @Test
        public void modifyFamily() throws Exception{ //修改列簇
            TableName tableName = TableName.valueOf("myns:user_info");
            //HTableDescriptor descriptor = new HTableDescriptor(tableName);//原来的列簇消失 new了个新的
            HTableDescriptor descriptor = hBaseAdmin.getTableDescriptor(tableName); //获得原来的描述
            HColumnDescriptor columnDescriptor = new HColumnDescriptor("extra_info");
            columnDescriptor.setVersions(1, 5); //设置列簇版本从1到5
            columnDescriptor.setTimeToLive(24*60*60); //秒
            descriptor.addFamily(columnDescriptor);
            hBaseAdmin.modifyTable(tableName,descriptor);
        }
    
        @Test
        public void deleteFamily() throws Exception{ //删除Family
            hBaseAdmin.deleteColumn("myns:user_info","extra_info");
        }
    
        @Test
        public void deleteColumeFamily() throws Exception{ ///删除Family
            TableName tableName = TableName.valueOf("myns:user_info");
            HTableDescriptor tableDescriptor = hBaseAdmin.getTableDescriptor(tableName);
            tableDescriptor.removeFamily("extra_info".getBytes());
            hBaseAdmin.modifyTable(tableName,tableDescriptor);
        }
    
        @Test
        public void listFamily() throws Exception{  //遍历Family
            TableName tableName = TableName.valueOf("myns:user_info");
            HTableDescriptor tableDescriptor = hBaseAdmin.getTableDescriptor(tableName);
            HColumnDescriptor[] columnFamilies = tableDescriptor.getColumnFamilies();
            for(HColumnDescriptor columnFamilie:columnFamilies){
                System.out.println(columnFamilie.getNameAsString());
                System.out.println(columnFamilie.getBlocksize());
                System.out.println(columnFamilie.getBloomFilterType());
            }
        }
    
        @Test
        public void getTable() throws IOException {
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            HbaseUtils.close(table);
        }
    
        @Test
        public void putDatas() throws IOException {
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            Put put = new Put(Bytes.toBytes("001"));
            put.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("userName"),Bytes.toBytes("zhangsan"));
            put.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("age"),Bytes.toBytes(18));
            put.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("sex"),Bytes.toBytes("male"));
            //提交
            table.put(put);
            HbaseUtils.close(table);
        }
    
        @Test
        public void batchPutDatas() throws IOException {
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            //0. 创建集合
            List<Put> list = new ArrayList<Put>();
    
            //1. 创建put对象指定行键
            Put rk004 = new Put(Bytes.toBytes("002"));
            Put rk005 = new Put(Bytes.toBytes("003"));
            Put rk006 = new Put(Bytes.toBytes("004"));
    
            //2. 创建列簇
            rk004.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("name"),Bytes.toBytes("gaoyuanyuan"));
            rk005.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("age"),Bytes.toBytes("18"));
            rk005.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("sex"),Bytes.toBytes("2"));
            rk006.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("name"),Bytes.toBytes("fanbinbin"));
            rk006.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("age"),Bytes.toBytes("18"));
            rk006.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("sex"),Bytes.toBytes("2"));
    
            //3. 添加数据
            list.add(rk004);
            list.add(rk005);
            list.add(rk006);
            table.put(list);
        }
        @Test
        public void getData() throws Exception{
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            Get get = new Get(Bytes.toBytes("001"));
            Result result = table.get(get);
            NavigableMap<byte[], byte[]> base_infos = result.getFamilyMap(Bytes.toBytes("base_info"));
            for(Map.Entry<byte[], byte[]> base_info:base_infos.entrySet()){
                String k = new String(base_info.getKey());
                String v = "";
                if(k.equals("age")) {
                     v = String.valueOf(Bytes.toInt(base_info.getValue()));
                }else{
                     v = new String(base_info.getValue());
                }
                System.out.println(k+":"+v);
            }
        }
    
    
        @Test
        public void getData2() throws IOException {
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            //1. 获Get对象
            Get get = new Get(Bytes.toBytes("004"));
            //2. 通过table获取结果对象
            Result result = table.get(get);
            //3. 获取表格扫描器
            CellScanner cellScanner = result.cellScanner();
            System.out.println("rowkey : " + result.getRow());
            //4. 遍历
            while (cellScanner.advance()) {
                //5. 获取当前表格
                Cell cell = cellScanner.current();
                //5.1 获取所有的列簇
                byte[] familyArray = cell.getFamilyArray();
                System.out.println(new String(familyArray, cell.getFamilyOffset(), cell.getFamilyLength()));
                //5.2 获取所有列
                byte[] qualifierArray = cell.getQualifierArray();
                System.out.println(new String(qualifierArray, cell.getQualifierOffset(), cell.getQualifierLength()));
                //5.3 获取所有的值
                byte[] valueArray = cell.getValueArray();
                System.out.println(new String(valueArray, cell.getValueOffset(), cell.getValueLength()));
            }
        }
    
        @Test
        public void getData3() throws IOException {
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            //1. 获得Get对象
            Get get = new Get(Bytes.toBytes("004"));
            //2. 通过table获取结果对象
            Result result = table.get(get);
            //3. 获取表格扫描器
            CellScanner cellScanner = result.cellScanner();
            //4.遍历
            while(cellScanner.advance()){
                Cell cell = cellScanner.current();
                //获取所有的列簇
                System.out.println(new String(CellUtil.cloneFamily(cell),"utf8"));
                System.out.println(new String(CellUtil.cloneQualifier(cell),"utf8"));
                System.out.println(new String(CellUtil.cloneValue(cell),"utf8"));
            }
        }
    
        @Test
        public void batchGetData() throws IOException {
            //1. 创建集合存储get对象
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            List<Get> gets = new ArrayList<Get>();
            //2. 创建多个get对象
            Get get1 = new Get(Bytes.toBytes("004"));
            get1.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("name"));
            get1.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("sex"));
            get1.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("age"));
    
            Get get2 = new Get(Bytes.toBytes("001"));
            get2.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("name"));
            get2.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("sex"));
    
            Get get3 = new Get(Bytes.toBytes("003"));
            get3.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("sex"));
            get3.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("age"));
            gets.add(get1);
            gets.add(get2);
            gets.add(get3);
            Result[] results = table.get(gets);
            for (Result result:results){
                HbaseUtils.showResult(result);
            }
        }
    
        @Test
        public void scanTable() throws IOException {
            //1. 创建扫描器
            Scan scan = new Scan();
            //2. 添加扫描的行数包头不包尾
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            scan.setStartRow(Bytes.toBytes("001"));
            scan.setStopRow(Bytes.toBytes("006" + "\001"));  //小技巧
            //3. 添加扫描的列
            scan.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("name"));
            //4. 获取扫描器
            ResultScanner scanner = table.getScanner(scan);
            Iterator<Result> it = scanner.iterator();
            while (it.hasNext()){
                Result result = it.next();
                HbaseUtils.showResult(result);
            }
        }
        @Test
        public void deleteData() throws IOException {
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            //1. 创建集合用于批量删除
            List<Delete> dels = new ArrayList<Delete>();
            //2. 创建删除数据对象
            Delete del = new Delete(Bytes.toBytes("004"));
            del.addColumn(Bytes.toBytes("base_info"),Bytes.toBytes("name"));
            //3. 添加到集合
            dels.add(del);
            //4. 提交
            table.delete(dels);
        }
    
    }
    
    

    Hbase过滤器

        @Test
        public void filter() throws IOException {
            //RegexStringComparator 正则
            //SubstringComparator; subString比较器
            //BinaryComparator 二进制比较器
            //and条件
            FilterList filterList = new FilterList(FilterList.Operator.MUST_PASS_ALL);
            SingleColumnValueFilter nameFilter = new SingleColumnValueFilter(Bytes.toBytes("base_info"), Bytes.toBytes("name"),
                    CompareFilter.CompareOp.LESS_OR_EQUAL,Bytes.toBytes("gaoyuanyuan"));
            filterList.addFilter(nameFilter);
            Scan scan = new Scan();
            scan.setFilter(filterList);
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            ResultScanner scanner = table.getScanner(scan);
            Iterator<Result> it = scanner.iterator();
            while (it.hasNext()){
                Result result = it.next();
                HbaseUtils.showResult(result);
            }
        }
    
    
        @Test
        public void familyFilter() throws IOException {
            //RegexStringComparator 正则
            //SubstringComparator; subString比较器
            //BinaryComparator 二进制比较器
            //and条件
            RegexStringComparator regexStringComparator = new RegexStringComparator("^base");
            //2. 创建FamilyFilter:结果中只包含满足条件的列簇信息
            FamilyFilter familyFilter = new FamilyFilter(CompareFilter.CompareOp.EQUAL, regexStringComparator);
    
    
    
            //4.创建扫描器进行扫描
            Scan scan = new Scan();
            //5. 设置过滤器
            scan.setFilter(familyFilter);
            //6. 获取表对象
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            //7. 扫描表
            ResultScanner scanner = null;
            try {
                scanner = table.getScanner(scan);
                //8. 打印数据
                Iterator<Result> iterator = scanner.iterator();
                while (iterator.hasNext()) {
                    Result result = iterator.next();
                    HbaseUtils.showResult(result);
                }
            } catch (IOException e) {
            } finally {
                try {
                    table.close();
                } catch (IOException e) {
                }
            }
        }
    
        @Test
        public void rowFiter() throws IOException {
            //1. 创建RowFilter
            BinaryComparator binaryComparator = new BinaryComparator(Bytes.toBytes("002"));
            RowFilter rowFilter = new RowFilter(CompareFilter.CompareOp.EQUAL, binaryComparator);
            //4.创建扫描器进行扫描
            Scan scan = new Scan();
            //5. 设置过滤器
            scan.setFilter(rowFilter);
            //6. 获取表对象
            Table table = HbaseUtils.getTable(TableName.valueOf("myns:user_info"));
            //7. 扫描表
            ResultScanner scanner = null;
            try {
                scanner = table.getScanner(scan);
                //8. 打印数据
                Iterator<Result> iterator = scanner.iterator();
                while (iterator.hasNext()) {
                    Result result = iterator.next();
                    HbaseUtils.showResult(result);
                }
            } catch (IOException e) {
            } finally {
                try {
                    table.close();
                } catch (IOException e) {
                }
            }
        }
    

    Hbase原理

    在这里插入图片描述

    架构

    1、Hmaster

    • 负责管理Hbase的元数据,表结构,表的Region信息
    • 负责表的创建,删除和修改
    • 负责为HRegionServer分配Region,分配后将元数据写入相应位置

    2、HRegionServer

    • 含有多个HRegion
    • 处理Client端的读写请求(根据从HMaster返回的元数据找到对应的HRegionServer)
    • 管理Region的Split分裂、StoreFile的Compaction合并。

    3、HRegion

    • 一个HRegion里可能有1个或多个Store。
    • HRegionServer维护一个HLog。
    • HRegion是分布式存储和负载的最小单元。
    • 表通常被保存在多个HRegionServer的多个Region中。

    4、Store

    • Store是存储落盘的最小单元,由内存中的MemStore和磁盘中的若干StoreFile组成。
    • 一个Store里有1个或多个StoreFile和一个memStore。
    • 每个Store存储一个列族。

    Hbase读写流程

    写数据流程

    在这里插入图片描述

    • Client访问ZK,根据ROOT表获取meta表所在Region的位置信息,并将该位置信息写入Client Cache。
      (注:为了加快数据访问速度,我们将元数据、Region位置等信息缓存在Client Cache中)。

    • Client读取meta表,再根据meta表中查询得到的Namespace、表名和RowKey等相关信息,获取将要写入Region的位置信息(此过程即Region三层定位,如下图),最后client端会将meta表写入Client Cache。

    • Hbase使用memstore和storefile存储对表的更新,数据在更新时首先写入hlog和memstore,memstore是排序的。

    • 当memstore积累到一定的阈值时,就会创建一个新的memstore,并将老的memstore加入flush队列,由单独的线程flush到磁盘上,成为一个StoreFile

    • 系统Zookeeper中记录一个checkpoint,表示这个时刻之前的数据变更已经持久化,发生故障只需要恢复checkpoint的数据

    • storefile是只读的,一旦创建之后就不可修改,当一个store的storefile达到一定的阀值后,就会进行一次合并操作,将对同一个key的修改合并到一起,同时进行版本合并和数据删除,形成一个大的storefile。当storefile的大小达到一定的阀值后,又会对storefile进行切分操作,等分为两个storefile。

    • Hbase中只有增添数据,所有的更新和删除操作都是在后续的合并中进行的,使得用户的写操作只要进入内存就可以立刻返回,实现了hbase的高速存储。

    (1) Client通过Zookeeper的调度,向RegionServer发出写数据请求,在Region中写数据。
    (2) 数据被写入Region的MemStore,直到MemStore达到预设阈值。
    (3) MemStore中的数据被Flush成一个StoreFile。
    (4) 随着StoreFile文件的不断增多,当其数量增长到一定阈值后,触发Compact合并操作,将多个StoreFile合并成一个StoreFile,同时进行版本合并和数据删除。
    (5) StoreFiles通过不断的Compact合并操作,逐步形成越来越大的StoreFile。
    (6) 单个StoreFile大小超过一定阈值后,触发Split操作,把当前Region Split成2个新的Region。父Region会下线,新Split出的2个子Region会被HMaster分配到相应的RegionServer上,使得原先1个Region的压力得以分流到2个Region上。
    

    Hbase的存储机制

    存储模型

    在这里插入图片描述

    1. 每一次的插入操作都会先进入MemStore(内存缓冲区),
    2. 当 MemStore达到上限的时候,Hbase会将内存中的数据输出为有序的StoreFile文件数据(根据Rowkey、版本、列名排序,这里已经和列簇无关了因为Store里都属于同一个列簇)。
    3. 这样会在Store中形成很多个小的StoreFile,当这些小的File数量达到一个阀值的时 候,Hbase会用一个线程来把这些小File合并成一个大的File。这样,Hbase就把效率低下的文件中的插入、移动操作转变成了单纯的文件输出、 合并操作。
    
    由上可知,在Hbase底层的Store数据结构中,
    
        1) 每个StoreFile内的数据是有序的,
        2) 但是StoreFile之间不一定是有序的,
        3) Store只 需要管理StoreFile的索引就可以了。
    
    	这里也可以看出为什么指定版本和Rowkey可以加强查询的效率,因为指定版本和Rowkey的查询可以利用 StoreFile的索引跳过一些肯定不包含目标数据的数据。
    

    在这里插入图片描述

    布隆过滤器

    它的时间复杂度是O(1),但是空间占用取决其优化的方式。它是布隆过滤器的基础。
    布隆过滤器(Bloom Filter)的核心实现是一个超大的位数组(或者叫位向量)和几个哈希函数。假设位数组的长度为m,哈希函数的个数为k
    假设集合里面有3个元素{x, y, z},哈希函数的个数为3。
    
    Step1:将位数组初始化,每位都设置为0。
    
    Step2:对于集合里面的每一个元素,将元素依次通过3个哈希函数进行映射,每次映射都会产生一个哈希值,哈希值对应位数组上面的一个点,将该位置标记为1。
    
    Step3:查询W元素是否存在集合中的时候,同样的方法将W通过哈希映射到位数组上的3个点。
    
    Step4:如果3个点的其中有一个点不为1,则可以判断该元素一定不存在集合中。反之,如果3个点都为1,则该元素可能存在集合中。注意:此处不能判断该元素是否一定存在集合中,可能存在一定的误判率。
    	可以从图中可以看到:假设某个元素通过映射对应下标为4,5,6这3个点。虽然这3个点都为1,但是很明显这3个点是不同元素经过哈希得到的位置,因此这种情况说明元素虽然不在集合中,也可能对应的都是1,这是误判率存在的原因。
    

    在这里插入图片描述

    • 布隆过滤器应用在Hbase
    	当我们随机读get数据时,如果采用hbase的块索引机制,hbase会加载很多块文件。如果采用布隆过滤器后,它能够准确判断该HFile的所有数据块中,是否含有我们查询的数据,从而大大减少不必要的块加载,从而增加hbase集群的吞吐率。这里有几点细节:
    	
    1. 布隆过滤器的存储在哪?
    	对于hbase而言,当我们选择采用布隆过滤器之后,HBase会在生成StoreFile(HFile)时包含一份布隆过滤器结构的数据,称其为MetaBlock;MetaBlock与DataBlock(真实的KeyValue数据)一起由LRUBlockCache维护。所以,开启bloomfilter会有一定的存储及内存cache开销。但是在大多数情况下,这些负担相对于布隆过滤器带来的好处是可以接受的。
    	
    2. 采用布隆过滤器后,hbase如何get数据?
    	在读取数据时,hbase会首先在布隆过滤器中查询,根据布隆过滤器的结果,再在MemStore中查询,最后再在对应的HFile中查询。
    	
    3. 采用ROW还是ROWCOL布隆过滤器?
    	这取决于用户的使用模式。如果用户只做行扫描,使用更加细粒度的行加列布隆过滤器不会有任何的帮助,这种场景就应该使用行级布隆过滤器。当用户不能批量更新特定的一行,并且最后的使用存储文件都含有改行的一部分时,行加列级的布隆过滤器更加有用。
    	
    tip:
    ROW和ROWCOL只是名字上有联系,但是ROWCOL并不是ROW的扩展,也不能取代ROW
    

    2.6.10 Hbase的寻址机制

    读数据流程

    在这里插入图片描述

        (1) Client访问Zookeeper,查找-ROOT-表,获取.META.表信息。
        (2) 从.META.表查找,获取存放目标数据的Region信息,从而找到对应的RegionServer。
        (3) 通过RegionServer获取需要查找的数据。
        (4) Regionserver的内存分为MemStore和BlockCache两部分,MemStore主要用于写数据,BlockCache主要用于读数据。读请求先到MemStore中查数据,查不到就到BlockCache中查,再查不到就会到StoreFile上读,并把读的结果放入BlockCache。
    

    StoreFile合并

    目的:减少StoreFile数量,提升数据读取效率。

    Compaction分为两种:

    major compaction
    将Store下面所有StoreFile合并为一个StoreFile,此操作会删除其他版本的数据(不同时间戳的)

    minor compaction
    选取Store下的部分StoreFile,将它们合并为一个StoreFile,此操作不会删除其他版本数据。

    Region分割

    目的:实现数据访问的负载均衡。

    做法:利用Middle Key将当前Region划分为两个等分的子Region。需要指出的是:Split会产生大量的I/O操作,Split开始前和Split完成后,HRegionServer都会通知HMaster。Split完成后,由于Region映射关系已变更,故HRegionServer会更新meta表。

    Hbase2Hdfs

    class HbaseMapper extends TableMapper<Text, NullWritable> {
        private Text k = new Text();
        @Override
        protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {
            //0. 定义字符串存放最终结果
            StringBuffer sb = new StringBuffer();
            //1. 获取扫描器进行扫描解析
            CellScanner cellScanner = value.cellScanner();
            //2. 推进
            while (cellScanner.advance()) {
                //3. 获取当前单元格
                Cell cell = cellScanner.current();
                //4. 拼接字符串
                sb.append(new String(CellUtil.cloneQualifier(cell)));
                sb.append(":");
                sb.append(new String(CellUtil.cloneValue(cell)));
                sb.append("\t");
            }
            //5. 写出
            k.set(sb.toString());
            context.write(k, NullWritable.get());
        }
    }
    
    public class Hbase2Hdfs implements Tool {
    
    
        private Configuration configuration;
        private final static String HBASE_CONNECT_KEY = "hbase.zookeeper.quorum";
        private final static String HBASE_CONNECT_VALUE = "mini01:2181,mini02:2181,mini03:2181";
        private final static String HDFS_CONNECT_KEY = "fs.defaultFS";
        private final static String HDFS_CONNECT_VALUE = "hdfs://mini01/";
        private final static String MAPREDUCE_CONNECT_KEY = "mapreduce.framework.name";
        private final static String MAPREDUCE_CONNECT_VALUE = "yarn";
    
        @Override
        public int run(String[] strings) throws Exception {
            Job job = Job.getInstance(configuration, "hbase2hdfs");
            job.setJarByClass(Hbase2Hdfs.class);
            TableMapReduceUtil.initTableMapperJob("myns:user_info", getScan(), HbaseMapper.class,
                    Text.class, NullWritable.class, job);
            FileOutputFormat.setOutputPath(job,new Path("/hbaseout/04"));
            boolean b = job.waitForCompletion(true);
            return b ? 1 : 0;
        }
    
        @Override
        public void setConf(Configuration configuration) {
            configuration.set(HBASE_CONNECT_KEY, HBASE_CONNECT_VALUE); // 设置连接的hbase
            configuration.set(HDFS_CONNECT_KEY, HDFS_CONNECT_VALUE); // 设置连接的hadoop
            configuration.set(MAPREDUCE_CONNECT_KEY, MAPREDUCE_CONNECT_VALUE); // 设置使用的mr运行平台
            this.configuration = configuration;
        }
    
        @Override
        public Configuration getConf() {
            return configuration;
        }
    
        public static void main(String[] args) throws Exception {
            ToolRunner.run(HBaseConfiguration.create(), new Hbase2Hdfs(), args);
        }
    
        private static Scan getScan() {
            return new Scan();
        }
    }
    
    

    Hdfs2Hbase

    public class Hdfs2Hbase implements Tool {
    
        private void createTable(String tablename) {
            //1. 获取admin对象
            HBaseAdmin admin = HbaseUtils.getHbaseAdmin();
            //2.
            try {
                boolean isExist = admin.tableExists(TableName.valueOf(tablename));
                if(isExist) {
                    admin.disableTable(TableName.valueOf(tablename));
                    admin.deleteTable(TableName.valueOf(tablename));
                }
                HTableDescriptor tableDescriptor = new HTableDescriptor(TableName.valueOf(tablename));
                HColumnDescriptor columnDescriptor2 = new HColumnDescriptor("age_info");
                columnDescriptor2.setBloomFilterType(BloomType.ROW);
                columnDescriptor2.setVersions(1, 3);
                tableDescriptor.addFamily(columnDescriptor2);
                admin.createTable(tableDescriptor);
            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                HbaseUtils.close(admin);
            }
        }
    
    
    
        public static class HBaseMapper extends Mapper<LongWritable, Text,Text,LongWritable>{
            Text text = new Text();
            LongWritable lw = new LongWritable(1);
            @Override
            protected void map(LongWritable key, Text value, Context context) throws IOException, InterruptedException {
                String line = value.toString();
                String[] datas = line.split(",");
                text.set(datas[0]);
                lw.set(Long.parseLong(datas[1]));
                context.write(text,lw);
            }
        }
    
        public static class HBaseReducer extends TableReducer<Text, LongWritable, ImmutableBytesWritable> {
            @Override
            protected void reduce(Text key, Iterable<LongWritable> values, Context context) throws IOException, InterruptedException {
                //1. 计数器
                long count = 0l;
                //2. 迭代
                Iterator<LongWritable> iterator = values.iterator();
                //3. 输出一定要是可以修改hbase的对象,put,delete
                Put put = new Put(Bytes.toBytes(key.toString()));
                String value = values.iterator().next().toString();
                //4. 将结果集写入put对象
                put.addColumn(Bytes.toBytes("age_info"), Bytes.toBytes("age"), Bytes.toBytes(value));
                //5. 写
                context.write(new ImmutableBytesWritable(Bytes.toBytes(key.toString())), put);
            }
        }
    
        //1. 创建配置对象
        private Configuration configuration;
        private final static String HBASE_CONNECT_KEY = "hbase.zookeeper.quorum";
        private final static String HBASE_CONNECT_VALUE = "mini01:2181,mini02:2181,mini03:2181";
        //private final static String HDFS_CONNECT_KEY = "fs.defaultFS";
       // private final static String HDFS_CONNECT_VALUE = "hdfs://mini01/";
        //private final static String MAPREDUCE_CONNECT_KEY = "mapreduce.framework.name";
       // private final static String MAPREDUCE_CONNECT_VALUE = "yarn";
    
    
    
        @Override
        public int run(String[] strings) throws Exception {
            Job job = Job.getInstance(configuration);
            job.setJarByClass(Hdfs2Hbase.class);
            job.setMapperClass(HBaseMapper.class);
            job.setReducerClass(HBaseReducer.class);
            job.setMapOutputKeyClass(Text.class);
            job.setMapOutputValueClass(LongWritable.class);
            String tablename = "user_infomation";
            createTable(tablename);
            FileInputFormat.setInputPaths(job,new Path("D://information.txt"));
            TableMapReduceUtil.initTableReducerJob(tablename,HBaseReducer.class,job);
            return job.waitForCompletion(true)?1:0;
        }
    
    
    
        @Override
        public void setConf(Configuration conf) {
            conf.set(HBASE_CONNECT_KEY, HBASE_CONNECT_VALUE); // 设置连接的hbase
            //conf.set(HDFS_CONNECT_KEY, HDFS_CONNECT_VALUE); // 设置连接的hadoop
            //conf.set(MAPREDUCE_CONNECT_KEY, MAPREDUCE_CONNECT_VALUE); // 设置使用的mr运行平台
            this.configuration = conf;
        }
    
        @Override
        public Configuration getConf() {
            return configuration;
        }
    
        public static void main(String[] args) throws Exception {
            ToolRunner.run(HBaseConfiguration.create(), new Hdfs2Hbase(), args);
        }
    }
    
    展开全文
  • 问题现象 今天早上,我还在上班路上,测试老大在群里面喊,xx应用仿真环境访问不了,并且截图了log日志,...遇到此类,本来好好的,现在不行的问题,一般都是一脸问号,没办法,只能撸起袖子找原因了。 第一步:hbase
  • hbase

    千次阅读 2018-08-03 11:34:02
    HBase是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统。  适合于存储大表数据(表的规模可以达到数十亿行以及数百万列),并且对大表数据的读、写访问可以达到实时级别;  利用Hadoop HDFS...
  • hbase为什么

    2019-01-18 13:15:21
    面试的时候也会问到为何Hbase的速度或者为什么选择Hbase作为数据库存储。下面的文章是转发的,对于上述问题的回答有一定的参考意义。仅供参考。 HBase能提供实时计算服务主要原因是由其架构和底层的数据结构决定的...
  • HBase

    千次阅读 2019-10-29 13:46:59
    HBase一 .概述 一 .概述
  • HBase如何快速查询

    2020-04-23 20:31:23
       HBase能提供实时计算服务主要原因是由其架构和底层的数据结构决定的,即由LSM-Tree(Log-Structured Merge-Tree) + region分区 + Cache决定——客户端可以直接定位到要查数据所在的HRegion server服务器,然后...
  • hbase快速入门之---逻辑视图

    千次阅读 2017-12-11 20:56:38
    hbase逻辑视图,rowkey,timestamp,cell等,图片摘自官网
  • Hbase查询速度的原理分析

    千次阅读 2018-07-10 13:46:58
    面试的时候也会问到为何Hbase的速度或者为什么选择Hbase作为数据库存储。下面的文章是转发的,对于上述问题的回答有一定的参考意义。仅供参考。HBase能提供实时计算服务主要原因是由其架构和底层的数据结构决定的...
  • HBase Shell命令大全

    万次阅读 多人点赞 2019-03-18 20:55:18
    HBase关键名称: Row Key 列族 column family 单元 Cell 时间戳 timestamp HBase Shell 是官方提供的一组命令,用于操作HBase。如果配置了HBase的环境变量了,就可以知己在命令行中输入hbase shell 命令进入命令行。...
  • 参考引用大佬连接↓ https://blog.csdn.net/mas2005/article/details/100026058 原因:防火墙未关闭,下面为关闭命令 hadoop dfsadmin -safemode leave
  • HBase查询速度慢原因排查

    千次阅读 2019-07-17 15:55:00
    问题:通过HBase访问服务在HBase中查询ASSET_NORMAL 表速度很慢 如下,查询一条数据需要2.970s时间: 如下,统计总条数需要14.675s时间: HBase访问服务部署了3个节点: HBase部署了3个节点: 表 ASSET...
  • HBase详解

    2018-03-21 19:43:29
    在系统地学习了下Hbase,为了加深对Hbase的理解,对相关知识点做了笔记,并在组内进行了Hbase相关技术的分享,由于Hbase涵盖的内容比较多,因此计划分享2期,下面就是针对第一期Hbase技术分享整体而成,主要内容如下...
  • Hbase查询速度的缘由

    千次阅读 2017-04-25 02:39:23
    A:如果快速查询(从磁盘读数据),hbase是根据rowkey查询的,只要能快速的定位rowkey, 就能实现快速的查询,主要是以下因素:  1、hbase是可划分成多个region,你可以简单的理解为关系型数据库的多个分区。  2...
  • 为什么HBase数据查询快速

    千次阅读 2016-11-24 16:17:53
    A:如果快速查询(从磁盘读数据),hbase是根据rowkey查询的,只要能快速的定位rowkey, 就能实现快速的查询,主要是以下因素:  1、hbase是可划分成多个region,你可以简单的理解为关系型数据库的多个分区。  2...
  • HBase客户端访问超时原因及参数优化

    万次阅读 2016-08-29 18:53:28
    默认的HBase客户端的参数配置是没有做过优化的,所以对于低延时响应的HBase集群,需要对客户端的参数进行优化。1. hbase.rpc.timeout以毫秒计算的所有HBase RPC超时,默认为60s。该参数表示一次RPC请求的超时时间。...
  • HBase学习

    千次阅读 多人点赞 2018-12-08 10:53:54
    HBase学习 0x01 摘要 本文是一篇HBase学习综述,将会介绍HBase的特点、对比其他数据存储技术、、架构、存储、数据结构、使用、过滤器等。 未完成 0x02 HBase基础概念 2.1 HBase是什么 2.2 HBase相对于RDMBS能...
  • Hbase官方手册-快速入门

    千次阅读 2017-11-08 18:46:02
    概述你可以使用Hbase用来随机,实时的读写大数据。这个项目的目标是处理非常大的表:数十亿行和列,并且使用廉价的服务器集群就可以实现。Hbase是开源的,分布式的,非关系型数据库。可以直接使用本地系统文件,也...
  • Hbase 查询为什么

    万次阅读 2014-11-05 21:16:24
    第二、hbase的数据格式 HFile V2 (HFile V1代码已经出hbase版本删除了) B、查询数据block的次数和HFile内部数据分开+索引分块   1、bloomfilter改进查找次数 2、hbase的三维...
  • HBase原理

    2019-08-23 22:10:51
    目录 HBase原理 1 HBase架构 2 HBase中的核心概念 3 HBase的存储机制 4 HBase的寻址机制 5 HBase的读写流程 6 HBase的设计 7 HBase和Hive的整合 ...
  • HBase合并详解

    千次阅读 2020-09-05 21:02:38
    本文介绍了HBase的合并原因、合并原理、合并分类、何时触发合并,以及对大合并的性能优化等内容,这也是HBase不同于其他关系型数据库的一种新特性,也是HBase能存储大量数据的写入不会慢,而且随着数据量的增加,...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 38,442
精华内容 15,376
关键字:

hbase快的原因