# 1)长度原则
# 最大64KB,推荐长度10~100 byte
# 最好设为8的倍数,能短则短,rowkey如果太长会影响性能。
# 2)唯一原则:rowkey应该具备唯一性
# 3)散列原则
# 3-1)盐值散列,不能使用时间戳直接作为rowkey
# 在rowkey加随机数
# 3-2)字符串反转
# 时间戳,电话号码(前面位数相同容易分到一个分区)
# 3-3)计算分区号,HashMap
# ASCII有序,常用列设计Rowkey放在前面
生成分区键,以6个分区
分区号:0,1,2,3,4,5
分区范围:(-∞,0),[0,1),[1,2),[2,3),[3,4),[4,5),[5,+∞)
RowKey前缀:0|,1|,2|,3|,4|,5|
Rowkey范围:(-∞,0|),[0|,1|),[1|,2|),[2|,3|),[2|,3|),[4|,5|),[5|,+∞)
/**
* 生成分区 键(优化)
*
* @param regionCount 分区数
* @return
*/
private byte[][] getSplitKeys(int regionCount) {
int splitKeyCount = regionCount - 1;
int length = Integer.toString(regionCount - 2).length();
byte[][] bs = new byte[splitKeyCount][];
List<byte[]> bsList = new ArrayList<>();
for (int i = 0; i < splitKeyCount; i++) {
String key = NumberUtils.format(i, length) + "|";
// System.out.println(key);
bsList.add(Bytes.toBytes(key));
}
bsList.toArray(bs);
return bs;
}
生成分区号
通过手机号+日期生成分区号,得到Rowkey的前缀。
/**
* TODO:计算分区号
*
* @param tel
* @param date
* @return
*/
protected String getRagionNum(String tel, String date) {
//手机号码的后4位
String usercode = tel.substring(tel.length() - 4);
//年月日时分秒(年月)
String yearMonth = date.substring(0, 6);
int userCodeHash = usercode.hashCode();
int yearMonthHash = yearMonth.hashCode();
//crc检验采用异或算法
int crc = Math.abs(userCodeHash ^ yearMonthHash);
int regionNum = crc % ValueConstant.REGION_COUNT;
int length = Integer.toString(ValueConstant.REGION_COUNT - 2).length();
return NumberUtils.format(regionNum, length);
}
Rowkey
String rowkey = getRagionNum(call1, calltime) + "_" + call1 + "_" + calltime;
补零工具类
/**
* 将数字格式化为字符串
* @param num
* @param length
* @return
*/
public static String format(int num,int length){
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < length; i++) {
stringBuffer.append("0");
}
DecimalFormat df =new DecimalFormat(stringBuffer.toString());
return df.format(num);
}