数据倾斜到一个节点,其余节点空转
出现haase热点情况一定是这两个原因:
rowkey设计太low没有做预分区rowkey设计原则:唯一,如果不唯一数据就会被覆盖,2散列的,防止出现hbase热点问题,3,字典 rowkey长度设计2的整数倍16,32,64,最长不超过64位.只有这样才可以使用高速缓存,如果不是这些,不能被64整除,就只能使用主机内存,那是比较慢的(最快是寄存器,其次是高速缓存,再往后是内存,磁盘) 列族只设计1个,如果数据量特别大,也就做2个列族,不要在多了.列族最好使用一个字母表示"M",最多使用两个字母"MM"定义其名称
为了便利scan操作
hbase给我们提供了两个方法可以做预分区:
RegionSplitter.HexStringSplit:适合于当前rowkey是16进制字符串(7E8A9S777A)RegionSplitter.UnformSplit:适合于rowkey经过hash,MD5处理过后的0000| 0001| 0002| 0003|…0007| 竖杠是ASCII中最大的值,因为我们rowkey是字典排序,增加竖杠就就一点会在这个范围之内
byte[][]二进制数组
实现过程中要运用到lang3这个包下的leftPad()左填充构建前缀
StringUtils.leftPad(null, *, *) = null StringUtils.leftPad("", 3, 'z') = "zzz" StringUtils.leftPad("bat", 3, 'z') = "bat" StringUtils.leftPad("bat", 5, 'z') = "zzbat" StringUtils.leftPad("bat", 1, 'z') = "bat" StringUtils.leftPad("bat", -1, 'z') = "bat" @param str:要给那个的字符串左边进行拼接,可以为null @param size:拼接后总字符个数 @param padChar:拼接的字符 实现预分区前缀的生成 package com.cartravel.hbase; import org.apache.commons.lang3.StringUtils; import org.apache.hadoop.hbase.util.Bytes; import java.util.Iterator; import java.util.TreeSet; /** *工具类实现的是:生成预分区前缀 */ public class SparkKeyBuilder implements SplitKeyCalulaor { //############## 实现上述接口生成预分区的前缀(返回的是二进制数组) ################### public byte[][] getSplitKeys(int regionNum) { //1.构建前缀 String[] keys = new String[regionNum]; for(int i=0;i<regionNum;i++){ String pre = StringUtils.leftPad(String.valueOf(i), 4, "0") + "|"; keys[i] = pre; } //2.构建一个返回值数组 byte[][] splitKeys = new byte[keys.length][]; //使用一个有序集合封装前缀 TreeSet<byte[]> row = new TreeSet<byte[]>(); for (int i = 0; i < keys.length; i++) { row.add(Bytes.toBytes(keys[i])); } //迭代TreeSet,把值赋值给splitKeys Iterator<byte[]> iterator = row.iterator(); int i =0; while(iterator.hasNext()){ byte[] tempRow = iterator.next(); iterator.remove(); splitKeys[i] = tempRow; i++; } row.clear(); row=null; return splitKeys; } }