1.hbase热点问题是什么?
数据倾斜到一个节点,其余节点空转
2.出现haase热点的原因是什么?
出现haase热点情况一定是这两个原因:
- rowkey设计太low
- 没有做预分区
3.设计hbase经验
rowkey设计原则:唯一,如果不唯一数据就会被覆盖,2散列的,防止出现hbase热点问题,3,字典
rowkey长度设计2的整数倍16,32,64,最长不超过64位.只有这样才可以使用高速缓存,如果不是这些,不能被64整除,就只能使用主机内存,那是比较慢的(最快是寄存器,其次是高速缓存,再往后是内存,磁盘)
列族只设计1个,如果数据量特别大,也就做2个列族,不要在多了.列族最好使用一个字母表示"M",最多使用两个字母"MM"定义其名称
4.为什么row可以设计要使用字典序列去排序的?
为了便利scan操作
5.rowkey设计要与预分区的前缀对应000X|+12位
我们设计这个rowkey要和我们做的预分区是对的上的
rowkey:000220190429,我们0002后面的任何一个数字或者字母要小于|就会把数据发送到0002|这个region分区上面去,从而保证他的负载均衡
package com.cartravel.hbase
import org.apache.commons.lang3.StringUtils
import org.apache.hadoop.hbase.util.{Bytes, MD5Hash}
object RowkeyUtils {
//000x|+12位
def getRowkey(pk:String):String={
val prefix = md5WithLong(pk)
//id_createTime
val split: Array[String] = pk.split("_")
val rk = s"${split(0)}_${split(1).substring(2,split(1).length)}"
val suffix = MD5Hash.getMD5AsHex(Bytes.toBytes(rk)).substring(0,12)
prefix + suffix
}
//保证rowkey的前缀是000x|
//rowkey:16为前四位是确定好的000x|后12位用MD5
//获取rowkey的前缀
private def md5WithLong(pk:String): String ={
val rkMd5: String = MD5Hash.getMD5AsHex(Bytes.toBytes(pk)).substring(0,15)
//rowkey的范围是:0-9 a-f 这些数字字母的组合 -->0-15
val hash= md5ToLong(rkMd5)
/*
1%9=1 2%9=2 3%9=3 ....
9%9=0 10%9=1 11%9=2
....18%9=0 19%9=1
*/
val str = (hash % 9).toString//取模我们可以实现把数据进行分组
val prefix = StringUtils.leftPad(str,4,"0")
prefix
}
private def md5ToLong(strs:String): Long ={
var x:Long=0
var tmp:Long=1
val split: Array[String] = strs.split("")
for(i<-split.indices){
split(i) match {
case "a" => tmp=10
case "b" => tmp=11
case "c" => tmp=12
case "d" => tmp=13
case "e" => tmp=14
case "f" => tmp=15
case _ => tmp = Integer.valueOf(split(i)).toLong
}
x += (tmp * Math.pow(8,split.length-i-1)).toLong //通过开8的多少次方让他的数字更加均衡
}
x
}
}