package com.alibaba.doris.algorithm.vpm; import java.util.ArrayList; import java.util.List; /** * Doris 路由算法核心映射关系构造算法 * @author frank * */ public class VpmMapping { /** * 映射算法的主方法,根据物理节点数和虚拟节点数构造虚拟节点到物理节点的映射关系 * @param physicalNodesNum 映射关系中物理节点的数目 * @param virtualNodesNum 映射关系中虚拟节点的数目 * @return 数组下标是虚拟节点编号,数组值是物理节点编号 */ public static int[] makeVpm(int physicalNodesNum,int virtualNodesNum){ int[] r = new int[virtualNodesNum]; List<List<Integer>> l = makeP2VMapping(physicalNodesNum,virtualNodesNum); for(int i=0;i<l.size();i++){ List<Integer> temp = l.get(i); for(Integer k:temp){ r[k]=i; } } return r; } /** * 映射关系算法主要算法过程,构造物理节点到虚拟节点的映射关系 * 客户端路由一般不需要该方法,server端迁移的时候若以虚拟节点为单位迁移需要调用该方法 * @param physicalNodesNum 映射关系中物理节点的数目 * @param virtualNodesNum 映射关系中虚拟节点的数目 * @return List方式的二维数组,第一维(级)物理节点,第二维(级)是虚拟节点 */ public static List<List<Integer>> makeP2VMapping(int physicalNodesNum, int virtualNodesNum) { List<List<Integer>> h = new ArrayList<List<Integer>>(); List<Integer> t = new ArrayList<Integer>(); for (int i = 0; i < virtualNodesNum; i++) { t.add(i); } h.add(t); if (physicalNodesNum == 1) { return h; } for (int k = 2; k <= physicalNodesNum; k++) { List<List<Integer>> temp1 = new ArrayList<List<Integer>>(); List<Integer> temp3 = new ArrayList<Integer>(); int y[] = new int[k]; for (int i = 1; i <= k; i++) { y[i - 1] = (virtualNodesNum - sumY(y, i - 1)) / (k + 1 - i);// 初始化物理节点内虚拟节点数目 } for (int j = 0; j < (k-1); j++) { List<Integer> temp2 = new ArrayList<Integer>(); for (int x = 0; x < h.get(j).size(); x++) { if (x < y[j]) { temp2.add(h.get(j).get(x)); } else { temp3.add(h.get(j).get(x)); } } temp1.add(temp2); } temp1.add(temp3); h = temp1; } return h; } private static int sumY(int[] y, int i) { int sum = 0; for (int k = 0; k < i; k++) { sum += y[k ]; } return sum; } /** * @param args */ public static void main(String[] args) { long b =System.currentTimeMillis(); System.out.println(makeP2VMapping(3, 12)); long e = System.currentTimeMillis(); System.out.println(e-b); System.out.println(makeP2VMapping(4, 10000)); System.out.println(makeVpm(3,12)); } }