写点什么

架构师训练营第 2 期 第五周作业

用户头像
月下独酌
关注
发布于: 2020 年 11 月 23 日

题目:测试 100 万 KV 数据,10 个服务器节点的情况下,计算了这些 KV 数据在服务器上分布数量的标准差。(代码中计算了方差)



//存放缓存服务器节点 key:hashcode value: serviceName
private static TreeMap<Integer, String> memServiceMap = new TreeMap<>();

//每台机器的虚拟节点数
private static int vmNoteNum = 100;
//真实缓存服务器数量
private static int serverSum = 10;
//请求数量
private static int clientSum = 1000000;


public static void main(String[] args) {

//虚拟节点数取值
int[] testNum = new int[]{50, 100, 150, 200, 250};
for (int i = 0; i < testNum.length; i++) {
//清除数据
memServiceMap.clear();
vmNoteNum = testNum[i];
cal();
}
}

//KV 数据在服务器上分布数量的方差
private static void cal() {
//10台机器 初始化
for (int i = 0; i < serverSum; i++) {
addMemServiceMap("service" + i);
}

String[] clients = new String[clientSum];
//准备100 万 KV 数据
Random random = new Random();
for (int i = 0; i < clientSum; i++) {
clients[i] = random.nextInt(256) + "." + random.nextInt(256) + "."
+ random.nextInt(256) + "." + random.nextInt(256) + ":"
+ random.nextInt(9999);
}

Map<String, Integer> countMap = new HashMap<>();

String serverName;
for (int i = 0; i < clientSum; i++) {
//模拟一次映射
serverName = getService(clients[i]);
//计数
if (countMap.containsKey(serverName)) {
countMap.put(serverName, countMap.get(serverName) + 1);
} else {
countMap.put(serverName, 1);
}
}
//统计服务器访问次数 保存至 arr
Set<String> countKey = countMap.keySet();
int[] arr = new int[countKey.size()];
Iterator<String> it = countKey.iterator();
int flag = 0;
while (it.hasNext()) {
arr[flag++] = countMap.get(it.next());
}
//打印 方差
System.out.println("每台服务器虚拟节点数:" + vmNoteNum
+ " 当前方差: " + Double.toString(variance(arr)));
}


/**
* 根据请求返回要访问的服务器IP
*
* @param key 一次请求相关的信息(如请求方的IP)
* @return 请求访问的服务器IP
*/
public static String getService(String key) {

int hashcode = getHash(key);
SortedMap<Integer, String> sortedMap = memServiceMap.tailMap(hashcode);
//查找第一个比当前HASH值大的节点,若未找到,则取第一个节点
return sortedMap.size() > 0 ? memServiceMap.get(sortedMap.firstKey())
: memServiceMap.firstEntry().getValue();

}


/**
* 增加节点
*
* @param serviceName 提供访问的服务器
*/
private static void addMemServiceMap(String serviceName) {
for (int j = 0; j < vmNoteNum; j++) {
memServiceMap.put(getHash(serviceName + "_visual" + j), serviceName);
}
}

/**
* 删除服务器节点
*
* @param serviceName 需要删除的服务器
*/
private static void removeMemServiceMap(String serviceName) {
for (int i = 0; i < vmNoteNum; i++) {
memServiceMap.remove(getHash(serviceName + "_visual" + i));
}
}


//抄来的获取hash方法
private static int getHash(String key) {
final int FNV_32_PRIME = 16777619;
int hash = (int) 2166136261L;
for (int i = 0; i < key.length(); i++) {
hash = (hash ^ key.charAt(i)) * FNV_32_PRIME;
}
hash += hash << 13;
hash ^= hash >> 7;
hash += hash << 3;
hash ^= hash >> 17;
hash += hash << 5;
return hash < 0 ? Math.abs(hash) : hash;
}


// 抄来的方差的计算公式
private static double variance(int[] arr) {
int m = arr.length;
double sum = 0;
for (int value : arr) {
sum += value;
}
double dAve = sum / m;
double dVar = 0;
for (int value : arr) {
dVar += (value - dAve) * (value - dAve);
}
return dVar / m;
}

输出结果:





用户头像

月下独酌

关注

还未添加个人签名 2019.07.22 加入

还未添加个人简介

评论

发布
暂无评论
架构师训练营第 2 期 第五周作业