1.Get操作
需求:根据业务ID,获取这个业务ID对应的属性
为什么要进行md5 或 Hash 或进行反转?
一句话说明:负载均衡,可以将记录平均分到不同的region
比如:业务id有时候开头是跟业务相关的一些编码。有个可能某个编码下面对应记录比较多,某些编码对应比较少。
比如上图示例中1111开头的有3条数据。其他前缀的都在3条以下
所以通过md5或者其他方式进行散列。
MD5 => DHS中选十六进制(string)
手机号反转=>DHS中选十进制(string)
其他自定义hash并序列化存储的=>DHS中选二进制
api:
写入:table.put。
查询:通过rowkey精准查询:table.get( Get(rowkey) )
DHS选“十六进制String类型”
MD5开头前缀作为rowkey代码写法:
1 2 3 4 5 6 | import com.google.common.hash.Hashing; String uid= "uid01" ; String md5_uid= Hashing.md5().newHasher().putString(uid).hash().toString(); String rowkey=md5_uid+ "其他内容" ; //因为是前缀匹配,只要前缀是MD5开头的就可以,后面有其他内容没关系。 Put put= new Put(rowkey.getBytes()); table.put(put); |
2.Scan操作(扫描操作):
利用hbase表,字典排序的特性,进行的扫描操作,要查询的数据有共同的前缀
scan操作不是无限制的!
scan操作一般都设置startkey,stopkey。数据量比较多的时候要增加salt_bucket
但是这还不够:为防止超时,scan 1w条以上的操作,要分成多次进行scan。因为scan数据操作会有大量的磁盘读取操作(磁盘IO升高),把结果放入内存(占用内存导致GC频率升高),再通过RPC发送到客户端(网络带宽)。
如果设置Filter进行过滤呢?——即使设置了Filter,也会扫描startkey到stopkey之间的所有数据。再在内存中过滤之后再返回客户端。
对客户端有什么影响?如果不分批扫描,除了对服务器磁盘内存网络造成压力,也会造成客户端超时。
下面是增加salt_bucket之后,分多个线程同时scan的情况。如果没有分salt_bucket,就是其中一个scan线程的情况。