第3章 客户端API:基础知识
- 所有修改都保证了行级别的原子性: 要么读到最新的修改,要么等待系统允许写入改行修改
- 用户要尽量使用批处理(batch)更新来减少单独操作同一行数据的次数
- 写操作中设计的列的数目并不会影响该行数据的原子性,行原子性会同时保护到所有列
- 创建HTable实例(指的是在java中新建该类),每个实例都要扫描.META. 表,以检查该表是否存在,推荐用户只创建一次HTable实例,而且是每个线程创建一个
- 如果用户需要多个HTable实例,建议使用HTablePool类(类似连接池)
CRUD
- 还可以通过 KeyValue 来添加Put: Put add(KeyValue kv)
- getFamilyMap() 可以遍历Put实例中每一个可用的KeyValue实例
- 用 has(family, qualifier) 来检查是否存在特定的单元格,而不需要遍历整个集合
- Put.getRow() 可以获取rowkey
- Put.heapSize() 可以计算当前Put实例所需的堆大小,既包含其中的数据,也包含内部数据结构所需的空间
KeyValue
KeyValue提供了一些比较器(可能
可以进行服务器端排序?),列出可能用到的几种:
- KeyComparator 比较 getKey()
- KVComparator
- RowComparator 比较 getRow()
客户端的写缓冲区
- 客户端有一个写缓冲区(默认大小2M),收集一堆put,然后一次发给服务器
- 通过 table.setAutoFlush(false) 来激活缓冲区(只有在写非常频繁的情况下会用到)
- hbase-site.xml 中的 hbase.client.write.buffer来调整大小
以下情况会激发缓冲区的刷写
- 激活写缓冲区之后要手动调用 flushCommits()
- 缓冲区满了的时候也会自动调用flushCommits()方法
- table.close()也会触发刷写
注意:如果只存储大单元格,缓冲区的作用就不大,因为大部分时间是传输时间而不是开关socket的时间
Put列表
可以传入一个列表的 Put
void Put(List<Put> puts)
不过如果同时插入多个put,当其中某个出错的时候,前面几个会被正常插入,往后的put就都不会插入
而且客户端也不能保证服务器端的写入顺序
GET
- get.exist(Get get) 方法,在需要检查一个比较大的列的时候能节省网络传输
- Result getRowBefore 可以获取某个行之前的行
批量处理操作
- put,get, delete 列表其实都是通过 batch() 方法实现的
- 直接使用batch(List<Action> actions, Object[] results, ... ) 可以同时传入3种实例中的任意一种
- batch并不使用写缓冲区
注意:不可以把对同一行的put和delete放在一个批量处理里面,因为批量处理的顺序不可控
两种批量查询的区别
用batch(List<Row> actions, Object[] results)批量查 和 Object[] batch(List<Row> actions) 的区别是
- batch(List<Row> actions, Object[] results)可以返回部分结果
- Object[] batch(List<Row> actions) 一旦出错,一条都没有
行锁
尽量不要使用行锁,如果必须使用,请一定节约占用锁的时间
扫描
- 通过 hbase-site.xml 中的 hbase.regionserver.lease.period 设定 ResultScanner 的租约
- 由于每次next()都要发一次请求,所以扫描器也有缓存,叫scanner caching ,默认是关闭的
- 通过 setBatch(5) 可以每次 next() 返回5列,注意是 列!
各种特性
HRegionLocation getRegionLocation(row)
Map<HRegionInfo, HServerAddress> getRegionInfo()
这些方法可以获取某一行数据的具体位置,或者所在的region信息