Hbase的API操作
HBase 是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统,利用 HBASE 技
术可在廉价 PC Server 上搭建起大规模结构化存储集群。
Hbase中的角色
HMaster
1.监控 RegionServer
2.处理 RegionServer 故障转移
3.处理元数据的变更
4.处理 region 的分配或转移
5.在空闲时间进行数据的负载均衡
6.通过 Zookeeper 发布自己的位置给客户端
RegionServer
1.负责存储 HBase 的实际数据
2.处理分配给它的 Region
3.刷新缓存到 HDFS
4.维护 Hlog
5.执行压缩
6.负责处理 Region 分片
其他组件
1.Write-Ahead logs HBase 的修改记录,当对 HBase 读写数据的时候,数据不是直接写进磁盘,它会在内存中保留一段时间(时间以及数据量阈值可以设定)。但把数据保存在内存中可能有更高的概率引起数据丢失,为了解决这个问题,数据会先写在一个叫做 Write-Ahead logfile 的文件中,然后再写入内存中。所以在系统出现故障的时候,数据可以通过这个日志文件重建。
2.Region Hbase表的分片,HBase表会根据RowKey值被切分成不同的region存储在RegionServer
中,在一个 RegionServer 中可以有多个不同的 region。
3.Store HFile 存储在 Store 中,一个 Store 对应 HBase 表中的一个列族(列簇, Column Family)。
4.MemStore 顾名思义,就是内存存储,位于内存中,用来保存当前的数据操作,所以当数据保存在
WAL 中之后,RegsionServer 会在内存中存储键值对。
5.HFile 这是在磁盘上保存原始数据的实际的物理文件,是实际的存储文件。StoreFile 是以 Hfile
的形式存储在 HDFS 的。
API(JAVA)
主要的客户端接口是由org.apache.hadoop.hbase.client的Htable这个类提供的,可以通过这个类对Hbase中的数据进行检索、存储,以及删除无效的数据。每个Htable实例都要扫描.META表。所以一个线程只推荐创建一个实例,然后复用这个对象(可以使用HTablePool类)。
put
1.单行put
创建put实例时,用户需要提供一个行键rowkey。创建put对象后就可以通过add方法添加一列数据了。若用户没有指定时间戳,则由region服务器设定一个。可以调用get方法获取一个KeyValue的单元格(Cell)。也可以调用getFamilyMap获取该行每一个可用的KeyValue。当需要判断特定列是否存在时可以调用has方法并进行限定来返回是否存在
2.KeyValue
建议将KeyValue实例和它的比较器都用作Hbase内部使用。可以让用户访问原始数据,减少额外的复制还可以进行基于字节的比较。每个字节数组都有一个length和offset参数,它们允许用户提交一个已经存在的字节数组,以及效率很高的字节级别的操作。
KeyValue还提供一系列实现了Compartor接口的静态内部类。toString方法用于检查数据是否已经被标记或恢复,同时也可以查看元信息。KeyValue有一系列便捷的方法来对数据进行更底层的操作。
3.写缓冲区
每一个put操作都是一个RPC操作,Hbase的API提供了一个缓冲区,由全局交换机控制着该缓冲区是否被使用。用户可以将Htable的setAutoFlush设置为false来激活缓冲区(默认禁用)。使用isAutoFlush检查标识的状态,也可以通过flushCommits(显示刷写)将修改传送到远程服务器(对应的region),客户端会计算缓冲区的大小,一旦大小超过默认大小(默认2M)就会隐式的刷写缓冲区。可以客户端修改缓冲区大小,也可以修改hbase-site.xml来固定缓冲区大小。
4.put列表
put除了单行操作,也可以对一个put类型的List集合操作,失败的put操作在进行重试后依然失败(默认一次)会返回一个异常,并保存在本地写缓冲区中,用户可以通过getWriteBuffer来访问它们,或者进行清除。失败的put不会计入缓冲区刷写大小。
5.原子性操作CAS
put的checkAndPut可以保证服务器端put操作的原子性,这种操作经常被用于账户结余,状态转换,或数据处理。它们的共同点是读取数据的同时对数据进行操作。
get
1.单行get
与put类似,可以获取一行数据。也需要设置行键。如果没有设定时间戳,则设置默认值(默认为1)。
2.Result类
当用户使用get方法时,返回一个Result实例,通过其方法获取对应数据。也可以调用getMap返回所有结果。
3.get列表
get允许对一个get类型的List进行操作。与put不同,get中若发生异常则会导致get终止。
4.获取数据的一些相关方法
exists方法可以判断数据是否存在。getRowOrBefore会查找一个特定行。
delete
1.单行删除
通过Delete实例可以删除数据。deleteClumons若不指定时间戳会删除该列所有版本数据,deleteClumon会删除最新版本的数据。
2.delete列表
通过Delete实例可以操作一个delete类型的List。
3.原子性操作CAS
通过CheckAndDelete可以检查要删除的列。
批量处理
put、get、delete都有一个共同的父类Row。我们可以将它们放到一起,进行批量操作。调用Htable中的batch,并传入Row类型的集合。如果自己传入一个Object的数组,发生异常时会返回部分结果,反之没有结果。batch是同步的,不会使用写缓冲区。
行锁
region服务器提供了一个行锁来保证操作的原子性,但客户端需要显示的指定一个行锁(创建Row类型的实例时传一个RowLock参数)。然后通过lockRow方法加锁,unLockRow解锁。若长时间没有解锁则该锁会过期,可以在hbase-site.xml中设置这个过期时长。但用户应该尽量避免使用行锁,因为可能会形成死锁。
扫描
1.Scanner
可以调用Htable的getScanner来获得一个扫描器,隐式的有一个Scan的参数。可以显示的指定起始行与结束行,不指定则默认全扫描。也可以给Scan指定过滤器。
2.ResultScanner
扫描操作不会一次RPC返回所有数据,而是会将一行封装成一个Result,将Result放入一个迭代器中。通过next获取数据,close释放资源。
3.缓冲与批量处理
每一个next方法都会为每行数据生成一个单独的RPC请求,这样做性能不是很好。我们可以通过Htable的getScannerCaching来设置表级别的缓冲。也可以设置hbase-site.xml来设置扫描器级别(优先于表级别)的缓冲。