关于hbase

  文章:点击打开链接

一、 HBase、MongoDB、Redis

    HBase(列存储):特别适用于简单数据写入(如“消息类”应用)和海量、结构简单数据的查询(如“详单类”应用)。特别地,适合稀疏表。(个人觉得存个网页内容是极好极好的。作为MapReduce的后台数据源,以支撑离线分析型应用。场景:Facebook的消息类应用,包括Messages、Chats、Emails和SMS系统,用的都是HBase;淘宝的WEB版阿里旺旺,后台是HBase;小米的米聊用的也是HBase;移动某省公司的手机详单查询系统。(单次分析,只能scan全表或者一个范围内的)

    MongoDB:是一个介于关系型和非关系型之间的一个产品,类SQL语言,支持索引;MongoDb在类SQL语句操作方面目前比HBase具备更多一些优势,有二级索引,支持相比于HBase更复杂的集合查找等。BSON的数据结构使得处理文档型数据更为直接。支持复杂的数据结构;MongoDb也支持mapreduce,但由于HBase跟Hadoop的结合更为紧密,Mongo在数据分片等mapreduce必须的属性上不如HBase这么直接,需要额外处理。

    Redis:Redis为内存型KV系统,处理的数据量要小于HBase与MongoDB;Redis很适合用来做缓存,但除此之外,它实际上还可以在一些“读写分离”的场景下作为“读库”来用,特别是用来存放Hadoop或Spark的分析结果。Redis的读写性能在100,000 ops/s左右,时延一般为10~70微妙左右;而HBase的单机读写性能一般不会超过1,000ops/s,时延则在1~5毫秒之间。Redis的魅力还在于它不像HBase只支持简单的字符串,他还支持集合set,有序集合zset和哈希hash;是一种搭建在hadoop上的数据库。特征是分布式,面向列,高并发,低延迟,依靠hdfs来实现数据访问和数据可靠性,hadoop是一种为吞吐量优化的离线系统,互补可以搭建水平扩展的数据应用,hbase区分大小写,./hbase shell的命令行关键字只识别小写)

二、hbase的基本概念

    列簇:Column Family,Hbase通过列族划分数据的存储,列族下面可以包含任意多的列,实现灵活的数据存取。刚接触的时候,理解起来有点吃力。我想到了一个非常类似的概念,理解起来就非常容易了,那就是家族的概念,我们知道一个家族是由于很多个的家庭组成的。列族也类似,列族是由一个一个的列组成(任意多)。Hbase表的创建的时候就必须指定列族。就像关系型数据库创建的时候必须指定具体的列是一样的。Hbase的列族不是越多越好,官方推荐的是列族最好小于或者等于3。我们使用的场景一般是1个列族。

    Rowkey:概念和mysql中的主键是完全一样的,Hbase使用Rowkey来唯一的区分某一行的数据。由于Hbase只支持3中查询方式:基于Rowkey的单行查询;基于Rowkey的范围扫描;全表扫描。因此,Rowkey对Hbase的性能影响非常大,Rowkey的设计就显得尤为的重要。设计的时候要兼顾基于Rowkey的单行查询也要键入Rowkey的范围扫描。具体Rowkey要如何设计后续会整理相关的文章做进一步的描述。这里大家只要有一个概念就是Rowkey的设计极为重要

     Region:概念和关系型数据库的分区或者分片差不多,Hbase会将一个大表的数据基于Rowkey的不同范围分配到不通的Region中,每个Region负责一定范围的数据访问和存储,

    HBase的每一张表都会被切分成若干块,每块叫做一个Region。每个Region中存储着从startKey到endKey中间的记录。这些Region会被分到集群的各个节点上去存储,每个节点叫做一个RegionServer,这些节点负责数据的读写,一个RegionServer可以处理大约1000个regions。

     TimeStamp:对Hbase来说至关重要,因为它是实现Hbase多版本的关键。在Hbase中使用不同的timestame来标识相同rowkey行对应的不通版本的数据。在写入数据的时候,如果用户没有指定对应的timestamp,Hbase会自动添加一个timestamp,timestamp和服务器时间保持一致,在Hbase中相同rowkey的数据按照timestamp倒序排列,默认查询的是最新的版本,用户可同指定timestamp的值来读取旧版本的数据。


三、hbase的架构:RegionServer负责数据的读写与客户端交互,对于region分配及负载均衡操作由HMaster处理,ZooKeeper则是负责监控维护运行中的节点。

   

   Physically, HBase is composed of three types of servers in a master slave type of architecture. Region servers serve data for reads and writes. When accessing data, clients communicate with HBase RegionServers directly. Region assignment, DDL (create, delete tables) operations are handled by the HBase Master process. Zookeeper, which is part of HDFS, maintains a live cluster state.

    Client:包含了访问Hbase的接口,另外Client还维护了对应的cache来加速Hbase的访问,比如cache的.META.元数据的信息。

    Zookeeper:实现master的高可用、RegionServer的监控、元数据的入口以及集群配置的维护等工作。负责维护节点的运行状态,也就是哪个节点是运行中的,哪个是已经挂了的。每个节点周期性地像它发送心跳信息,从而让它能时刻了解到每个节点的运行情况。如果发现有节点出现异常情况,它会发出提醒。
    具体工作:保证集群中只有1个master在运行,如果master异常会通过竞争机制产生新的master提供服务;监控RegionServer的状态,当RegionSevrer有异常的时候,通过回调的形式通知Master RegionServer上下限的信息,存储元数据的统一入口地址。Hbase里有一张特殊的元数据表"hbase:meta",.META.元数据保存着hbase集群中所有region所处的主机位置信息。而zookeeper中保存这这张表所在的主机位置信息。

    ZooKeeper作为一个关系协调者,协调整个系统中各个组件的一些状态信息。Region servers和运行中的HMaster会跟ZooKeeper建立一个会话连接。ZooKeeper通过心跳信息来维持一个正在进行会话的短时节点(ephemeral node)(还是直接看英文吧,翻译总感觉说不清楚想要表达的意思)。

    每个RegionServer会创建一个短时节点(ephemeral node),而HMaster会监控这些节点来寻找空闲的节点,同时它也会检测这些节点当中是不是有节点已经挂了。HMaster会竞争创建短时节点,ZooKeeper会决定哪个HMaster作为主节点,并且时刻保持一个时间段只有一个活跃的HMaster。这个活跃的HMaster会向ZooKeeper发送心跳信息,而在之前竞争中失败的HMaster就是非活跃的HMaster,他们时刻都想着取代那个唯一的活跃的HMaster,所以他们就一直注意监听ZooKeeper中有没有那个活跃的HMaster挂了的通知。突然发现这个系统跟人类社会很相似啊,一个身居高位的人,底下有无数的人在盼望着他出丑下台从而自己取代他。

    如果一个RegionServer或者那个活跃的HMaster没有发送心跳信息给ZooKeeper,那么建立的这个会话就会被关闭,与这些出问题节点有关的所有短时节点都会被删除。会有相应的监听器监听这些信息从而通知这些需要被删除的节点。因为活跃的那个HMaster会监听这些RegionServer的状态,所以一旦他们出问题,HMaster就会想办法恢复这些错误。如果挂掉的是HMaster,那么很简单,底下那些不活跃的HMaster会第一时间收到通知并且开始竞争这个“岗位”。

    总结一下这个过程:在HMaster和RegionServer连接到ZooKeeper后创建Ephemeral节点,并使用Heartbeat机制维持这个节点的存活状态,如果某个Ephemeral节点失效,则HMaster会收到通知,并做相应的处理。HMaster通过监听ZooKeeper中的Ephemeral节点来监控HRegionServer的加入或宕机。在第一个HMaster连接到ZooKeeper时会创建Ephemeral节点来表示Active的HMaster,其后加进来的HMaster则监听该Ephemeral节点,如果当前Active的HMaster宕机,则该节点消失,因而其他HMaster得到通知,而将自身转换成Active的HMaster,在变为Active的HMaster之前,它会创建在/hbase/back-masters/下创建自己的Ephemeral节点。

     Hmaster:执行集群管理操作,跟踪数据位于哪个节点上(行健鉴别),控制负载均衡和故障切换。功能概括为:管理RegionServer,实现其负载均衡;管理和分配Region,比如在Region split时分配新的Region;在RegionServer退出时迁移其内的Region到其他RegionServer上;监控集群中所有RegionServer的状态(通过Heartbeat和监听ZooKeeper中的状态);处理schema更新请求 (创建、删除、修改Table的定义);当RegionSever失效的时候,协调对应Hlog的拆分。

    HregionServer:直接对接用户的读写请求,是真正的“干活”的节点。它的功能概括:管理master为其分配的Region;处理来自客户端的读写请求;负责和底层HDFS的交互,存储数据到HDFS;负责Region变大以后的拆分;负责Storefile的合并工作。 一个RegionServer由WAL、BlockCache、MemStore和HFile构成:

     ① WAL(Write Ahead Log):其实就是个日志文件,存储在分布式系统上。这个日志是用来存储那些还没有被写入硬盘永久保存的数据,是用来进行数据恢复的。换句话说,无论要写什么数据,都要现在这个日志里登记一下新数据,道理很简单,如果没有日志文件,那么如果在写数据的时候出问题了,比如停电啊这种故障,那么数据库如何恢复数据呢?而先写了日志之后,数据没写入硬盘没关系,直接通过日志就知道之前进行了哪些操作,通过对比日志和你现在数据库中的值就能知道是在哪个地方出故障的,接下来就按照日志的记录往后一步步执行就好了,数据库的数据就能恢复了。

    ② BlockCache:它是读缓存,它存储了被经常读取的数据,使用的是LRU算法,也就是说,缓冲区满了之后,最近最少被使用的数据会被淘汰。

    ③ MemStore:是写缓存,用于存储还没有被写入到硬盘的数据,并且是排序过的。每一个列族对应一个MemStore。    

    ④ HFile:它存储了按照KeyValue格式的每行数据。

    A Region Server runs on an HDFS data node and has the following components:
    WAL: Write Ahead Log is a file on the distributed file system. The WAL is used to store new data that hasn't yet been persisted to permanent storage; it is used for recovery in the case of failure.
    BlockCache: is the read cache. It stores frequently read data in memory. Least Recently Used data is evicted when full.
    MemStore: is the write cache. It stores new data which has not yet been written to disk. It is sorted before writing to disk. There is one MemStore per column family per region.
    Hfiles store the rows as sorted KeyValues on disk.


    HDFS:HDFS为Hbase提供最终的底层数据存储服务,同时为Hbase提供高可用(Hlog存储在HDFS)的支持,具体功能概括如下:提供元数据和表数据的底层分布式存储服务;数据多副本,保证的高可靠和高可用性。

四、查询实现:

    region定位过程:client首先从zookeeper获取.meta表所在的region server,并查询meta表中包含所需查询key范围的region所在region server,同时缓存下region与region server的映射信息,避免重复查询,连接此region server查询,如果region由于split或者balancing等原因改变了对应的region server ,则client会重新从zk中查询一遍,并再次缓存。

      HBase中有个特殊的日志表叫做META table,这个表里存储着每个region在集群的哪个节点上,回想一下region是什么,它是一张完整的表被切分的每个数据块。这张表的地址存储在ZooKeeper上,也就是说这张表实际上是存在RegionServer中的,但具体是哪个RegionServer,只有ZooKeeper知道。当客户端要读写数据的时候,无法避免的一个问题就是,我要访问的数据在哪个节点上或者要写到哪个节点上?这个问题的答案就与META table有关。

    查询步骤:①客户端要先去ZooKeeper找到这这表存在哪个RegionServer上了;②去那个RegionServer上找,怎么找呢?当然是根据要访问数据的key来找。找到后客户端会将这些数据以及META的地址存储到它的缓存中,这样下次再找到相同的数据时就不用再执行前面的步骤了,直接去缓存中找就完成了,如果缓存里没找到,再根据缓存的META地址去查META表就行了。③很简单,第二步已经知道键为key的数据在哪个RegionServer上了,直接去找就好了。

    这个META表具体是什么呢?我们一起来看看,它里面是一个所有Region地址的列表。使用的数据结构是b树,key和value分别如下图所示:

    This META table is an HBase table that keeps a list of all regions in the system.

    The .META. table is like a b tree.The .META. table structure is as follows:

    - Key: region start key,region id

    - Values: RegionServer


五、写入实现

    当客户端发起一个put请求的时候,首先根据RowKey寻址,从META表中查出该Put数据最终需要去的RegionServer,客户端把这个put操作先写到RegionServer的WAL日志文件中,一旦写入到日志成功后,RegionServer会根据put请求中的TableName和RowKey找到对应的Region,然后再根据column family找到该列族对应的MemStore,将数据写入MemStore,最后,数据写成功后,给客户端一个应答,表明数据已经写好了 。

HBase Write Steps (1)

When the client issues a Put request, the first step is to write the data to the write-ahead log, the WAL:

- Edits are appended to the end of the WAL file that is stored on disk.

- The WAL is used to recover not-yet-persisted data in case a server crashes.

HBase Write Steps (2)

Once the data is written to the WAL, it is placed in the MemStore. Then, the put request acknowledgement returns to the client.

    Hbase的使用场景: Hbase是一个通过廉价PC机器集群来存储海量数据的分布式数据库解决方案。它比较适合的场景:巨量数据(百T、PB级别);查询简单(基于rowkey或者rowkey范围查询);不涉及到复杂的关联;有几个典型的场景特别适合使用Hbase来存储:海量订单流水数据(长久保存);交易记录;数据库历史数据。


六、hbase shell指令

文章一:点击打开链接

文章二:点击打开链接

hbase shell的help语句得到的信息:

hbase(main):042:0* help
HBase Shell, version 1.1.3-bc1.3.6, r9dcd40f216cea0c556155b1ba15e5c96e6e5cda0, Wed Aug 23 17:49:52 CST 2017
Type 'help "COMMAND"', (e.g. 'help "get"' -- the quotes are necessary) for help on a specific command.
Commands are grouped. Type 'help "COMMAND_GROUP"', (e.g. 'help "general"') for help on a command group.

COMMAND GROUPS:
  Group name: general
  Commands: status, table_help, version, whoami

  Group name: ddl
  Commands: alter, alter_async, alter_status, create, describe, disable, disable_all, drop, drop_all, enable, enable_all, exists, get_table, is_disabled, is_enabled, list, show_filters

  Group name: namespace
  Commands: alter_namespace, create_namespace, describe_namespace, drop_namespace, list_namespace, list_namespace_tables

  Group name: dml
  Commands: append, count, delete, deleteall, get, get_counter, get_splits, incr, put, scan, truncate, truncate_preserve

  Group name: tools
  Commands: assign, balance_switch, balancer, balancer_enabled, catalogjanitor_enabled, catalogjanitor_run, catalogjanitor_switch, close_region, compact, compact_rs, flush, major_compact, merge_region, move, split, trace, unassign, wal_roll, zk_dump

  Group name: replication
  Commands: add_peer, append_peer_tableCFs, disable_peer, disable_table_replication, enable_peer, enable_table_replication, list_peers, list_replicated_tables, remove_peer, remove_peer_tableCFs, set_peer_tableCFs, show_peer_tableCFs

  Group name: snapshots
  Commands: clone_snapshot, delete_all_snapshot, delete_snapshot, list_snapshots, restore_snapshot, snapshot

  Group name: configuration
  Commands: update_all_config, update_config

  Group name: quotas
  Commands: list_quotas, set_quota

  Group name: security
  Commands: grant, revoke, user_permission

  Group name: procedures
  Commands: abort_procedure, list_procedures

  Group name: visibility labels
  Commands: add_labels, clear_auths, get_auths, list_labels, set_auths, set_visibility

SHELL USAGE:
Quote all names in HBase Shell such as table and column names.  Commas delimit
command parameters.  Type <RETURN> after entering a command to run it.
Dictionaries of configuration used in the creation and alteration of tables are
Ruby Hashes. They look like this:

  {'key1' => 'value1', 'key2' => 'value2', ...}

and are opened and closed with curley-braces.  Key/values are delimited by the
'=>' character combination.  Usually keys are predefined constants such as
NAME, VERSIONS, COMPRESSION, etc.  Constants do not need to be quoted.  Type
'Object.constants' to see a (messy) list of all constants in the environment.

If you are using binary keys or values and need to enter them in the shell, use
double-quote'd hexadecimal representation. For example:

  hbase> get 't1', "key\x03\x3f\xcd"
  hbase> get 't1', "key\003\023\011"
  hbase> put 't1', "test\xef\xff", 'f1:', "\x01\x33\x40"

The HBase shell is the (J)Ruby IRB with the above HBase-specific commands added.
For more on the HBase Shell, see http://hbase.apache.org/book.html

1、 查看集群状态:status,version,whoami
hbase(main):087:0* whoami
csap (auth:SIMPLE)
    groups: csap

hbase(main):038:0* status
7 servers, 5 dead, 3.2857 average load

hbase(main):040:0* version
1.1.3-bc1.3.6, r9dcd40f216cea0c556155b1ba15e5c96e6e5cda0, Wed Aug 23 17:49:52 CST 2017 

2、 列出所有表:list

hbase(main):089:0* list
TABLE                                                                                                                                                       
ambarismoketest                                                                                                                                             
bulkload_text                                                                                                                                               
hbaset_cust_info1                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       
yezonggang                                                                                                                                                  
21 row(s) in 0.0260 seconds

3、DDL语句:create,disable,enable,drop,truncate

建表t_cs_quality,列簇是info:
create 't_cs_quality','info'
0 row(s) in 1.2800 seconds
hbase(main):001:0> disable 't_cs_quality'
enable0 row(s) in 2.5080 seconds

hbase(main):002:0> enable 't_cs_quality'
0 row(s) in 0.8760 seconds
删除表:
hbase(main):010:0> drop 'yezonggang'
0 row(s) in 1.2280 seconds 
清空表:truncate 'yzg'

4、DML语句:put,delete,update,scan,get,incr

增,改:put可以增加也是修改操作
hbase(main):007:0> put 't_cs_quality','001001001001','info:businessName','0001'
put 't_cs_quality','001001001001','info:mobile','0001'
put 't_cs_quality','001001001001','info:agentNum','0001'
put 't_cs_quality','001001001001','info:agentName','0001'
put 't_cs_quality','001001001001','info:bgnTime','0001'

删:
删除行'yezonggang', 列族为‘info' 中age的值

delete 'yzg', 'yezonggang', 'info:age'

deleteall 'yzg', 'yezonggang'

查:
① 查全表:scan
hbase(main):079:0* scan 't_cs_quality'
ROW                                      COLUMN+CELL                                                                                                        
 001001001001                            column=info:agentId, timestamp=1521276523770, value=0001                                                           
 001001001001                            column=info:agentName, timestamp=1521276523463, value=0001                                                         
 001001001001                            column=info:agentNum, timestamp=1521276523428, value=0001                                                                                                         
1 row(s) in 0.0490 seconds
② 查某条记录:get
hbase(main):033:0> get 't_cs_quality','001001001001'
COLUMN                                   CELL                                                                                                               
 info:agentId                            timestamp=1521276523770, value=0001                                                                                
 info:agentName                          timestamp=1521276523463, value=0001                                                                                
 info:agentNum                           timestamp=1521276523428, value=0001                                                                                
 info:bgnTime                            timestamp=1521276523482, value=0001                                                                                
22 row(s)

七、hbase的大数据导入:

1、hbase的Put api:    最简单但不是最有效的方式,类似于关系型数据库的insert方法,不适合做大量数据导入

2、hbase的bulk load工具:    bulk load是大量数据导入最有效的方式,importtsv是内置工具,是mr方式

3、自己写MapReduce:    动态产生的数据可以使用,而且灵活

4、开源工具sqoop:    开源的工具软件,是一种hadoop和关系型数据库相互导入的工具,sqoop1和sqoop2版本

八、hbase中rowkey的设计

    hbase中的数据通过三个维度精确定位:rowkey,timestamp,column family

Row Key

Time Stamp

Column Family:c1

Column Family:c2

r1

t7

c1:1

value1-1/1

 

 

t6

c1:2

value1-1/2

 

 

t5

c1:3

value1-1/3

 

 

t4

 

 

c2:1

value1-2/1

t3

 

 

c2:2

value1-2/2

t2

t2

c1:1

value2-1/1

 

 

t1

 

 

c2:1

value2-1/1

    rowkey是hbase中很重要的一个设计,如果你把它当成普通字段那你的设计就有点失败了。它的设计可以说是一门艺术。你的查询如果不能把rowkey加入进来,那你的设计基本是失败的。加上rowkey,hbase可以快速地定位到具体的region去取你要的数据,否则就会满上遍野的找数据。

设计原则:

    1. 长度越短越好:Rowkey是一个二进制码流,Rowkey的长度被很多开发者建议说设计在10~100个字节,不过建议是越短越好,不要超过16个字节。原因:(1)数据的持久化文件HFile中是按照KeyValue存储的,如果Rowkey过长比如100个字节,1000万列数据光Rowkey就要占用100*1000万=10亿个字节,将近1G数据,这会极大影响HFile的存储效率;(2)MemStore将缓存部分数据到内存,如果Rowkey字段过长内存的有效利用率会降低,系统将无法缓存更多的数据,这会降低检索效率。因此Rowkey的字节长度越短越好。(3)目前操作系统是都是64位系统,内存8字节对齐。控制在16个字节,8字节的整数倍利用操作系统的最佳特性。

    2. 散列原则:防止出现热点现象。如果Rowkey是按时间戳的方式递增,不要将时间放在二进制码的前面,建议将Rowkey的高位作为散列字段,由程序循环生成,低位放时间字段,这样将提高数据均衡分布在每个Regionserver实现负载均衡的几率。如果没有散列字段,首字段直接是时间信息将产生所有新数据都在一个 RegionServer上堆积的热点现象,这样在做数据检索的时候负载将会集中在个别RegionServer,降低查询效率。

    3. 唯一性:HBase按指定的条件获取一批记录时,使用的就是scan方法。 scan方法有以下特点:(1)scan可以通过setCaching与setBatch方法提高速度(以空间换时间);(2)scan可以通过setStartRow与setEndRow来限定范围。范围越小,性能越高。通过巧妙的RowKey设计使我们批量获取记录集合中的元素挨在一起(应该在同一个Region下),可以在遍历结果时获得很好的性能。(3)scan可以通过setFilter方法添加过滤器,这也是分页、多条件查询的基础。

猜你喜欢

转载自blog.csdn.net/yezonggang/article/details/79581685