通过测试可以发现ycsb进行评测数据库工作负载的时候insert生成的key值是通过Fowler_Noll_Vo_hash之后得到18或者是19长度的字符串然后在前面加上"user"和填充位之后得到22或者23固定长度。这里主要是coreworkload中的buildKeyName(keynum) 方法实现的(这里的keynum是按照顺序递增的,value是keynum进行hash编码之后得到的值,加上“user”之后就会变成22位或者23位)
pre keynum:994 value:633995401461691778 value length:18
pre keynum:995 value:6858042526771971499 value length:19
pre keynum:996 value:4152828024211893584 value length:19
如果我想变成16位固定长度的key就需要更改hash算法,hash算法主要是调用core目录下Utils文件中hash,因此我在util文件中添加有关md5 hash算法,可以通过调用直接生成以下三种形式字符串:16位纯数字、数字和字母组合还有32位数字和字母组合。
import java.security.MessageDigest;
//生成16位纯数字的字符串
public static String getMD5(byte[] source) {
String s = null;
char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'};
try {
MessageDigest md = MessageDigest.getInstance("MD5");
md.update(source);
byte[] tmp = md.digest();
char[] str = new char[16];
int k = 0;
for (int i = 0; i < 16; i++) {
byte byte0 = tmp[i];
//只取高位
str[k++] = hexDigits[(byte0 >>> 4 & 0xf)%10];
// str[k++] = hexDigits[byte0 & 0xf];
}
s = new String(str); // 换后的结果转换为字符串
}catch(Exception e) {
e.printStackTrace();
}
return s;
}
//md5生成32位带数字和字母的字符串
public static String encrypt32(String encryptStr) {
MessageDigest md5;
try {
md5 = MessageDigest.getInstance("MD5");
byte[] md5Bytes = md5.digest(encryptStr.getBytes());
StringBuffer hexValue = new StringBuffer();
for (int i = 0; i < md5Bytes.length; i++) {
int val = ((int) md5Bytes[i]) & 0xff;
if (val < 16) {
hexValue.append("0");
}
hexValue.append(Integer.toHexString(val));
}
encryptStr = hexValue.toString();
} catch (Exception e) {
throw new RuntimeException(e);
}
return encryptStr;
}
/**
* @Description:加密-16位小写,md5生成16位带数字和字母的字符串
* @author:wangrui
* @time:2019年7月1日 上午11:15:33
*/
public static String encrypt16(String encryptStr) {
return encrypt32(encryptStr).substring(8, 24);
}
由于主要是想生成16位纯数字的字符串,因此hash方法改为调用getMD5()方法:
public static String hash(long val) {
//return fnvhash64(val);s
String value = Long.toString(val);
String result = getMD5(value.getBytes());
System.out.println("md5 16:" + result);
// System.out.println("type" + Long.parseLong(encrypt16(value)).getClass().getName());
return result;
}
同时coreworkloads文件中buildKeyName方法也要进行修改:
protected String buildKeyName(long keynum) {
long key1 = keynum;
String value;
if (!orderedinserts) {
value = Utils.hash(keynum);
}else{
value = Long.toString(keynum);
}
System.out.print("pre keynum:" + key1 + "value:" + value + "\tvalue length:" + value.length());
int fill = zeropadding - value.length();
String prekey = "user";
for (int i = 0; i < fill; i++) {
prekey += '0';
}
return value;
}
然后就可以啦,直接mvn clean package之后如果成功直接
bin/ycsb load mapkeeper -s -P workloads/workloada -p "mapkeeper.host=127.0.0.1" -p "mapkeeper.port=9090"
bin/ycsb run mapkeeper -s -P workloads/workloada -p "mapkeeper.host=127.0.0.1" -p "mapkeeper.port=9090"
会在server端显示如下结果:(前面字符串就是key,后面1080是value的长度)
3331381741354218 1080
5063212704481401 1080
5745152715228050 1080
3623115442630601 1080
9029155151691022 1080
0103052120949582 1080
4090110252202017 1080
6291874550027021 1080
8021102527374213 1080
7112324837217912 1080
9410524758250505 1080