浏览代码

HaClusterAllocator create

HANTE 1 月之前
父节点
当前提交
221800e663

+ 138 - 0
its-cluster/src/main/java/com/its/common/cluster/utils/HaClusterEvenAllocator.java

@@ -0,0 +1,138 @@
+package com.its.common.cluster.utils;
+
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.*;
+
+@Slf4j
+public final class HaClusterEvenAllocator {
+
+    private final List<String> servers;
+    private final Map<String, List<String>> allocation;
+
+    public HaClusterEvenAllocator() {
+        this.servers = new ArrayList<>();
+        this.allocation = new HashMap<>();
+    }
+
+    public void addServer(String server) {
+        if (server != null && !server.isEmpty()) {
+            this.servers.add(server);
+        }
+    }
+    public List<String> get(String server) {
+        return this.allocation.getOrDefault(server, Collections.emptyList());
+    }
+    public void allocate(List<String> clients) {
+        this.allocation.clear();
+        for (String server : this.servers) {
+            this.allocation.put(server, new ArrayList<>());
+        }
+
+        int numClients = clients.size();
+        int numServers = this.servers.size();
+        int baseSize = numClients / numServers;  // 각 서버에 기본적으로 할당할 개수
+        int remainder = numClients % numServers; // 남는 개수 (마지막 서버에 할당)
+
+        int clientIndex = 0;
+        for (int i = 0; i < numServers; i++) {
+            int allocationSize = baseSize + (i < remainder ? 1 : 0); // 마지막 서버에 여분 추가
+            String server = servers.get(i);
+
+            for (int j = 0; j < allocationSize; j++) {
+                this.allocation.get(server).add(clients.get(clientIndex++));
+            }
+        }
+    }
+
+    public static Map<String, List<String>> allocate(List<String> servers, List<String> clients) {
+        Map<String, List<String>> allocation = new HashMap<>();
+
+        // 서버별 리스트 초기화
+        for (String server : servers) {
+            allocation.put(server, new ArrayList<>());
+        }
+
+        // 라운드 로빈 방식으로 순차적 분배
+        for (int i = 0; i < clients.size(); i++) {
+            String server = servers.get(i % servers.size()); // 서버 개수로 순환
+            allocation.get(server).add(clients.get(i));
+        }
+
+        return allocation;
+    }
+    public static Map<String, List<String>> allocator(List<String> servers, List<String> clients) {
+        Map<String, List<String>> allocation = new HashMap<>();
+
+        // 서버별 리스트 초기화
+        for (String server : servers) {
+            allocation.put(server, new ArrayList<>());
+        }
+
+        int serverIndex = 0; // 첫 번째 서버부터 시작
+
+        // 순차적으로 클라이언트를 서버에 할당
+        for (String client : clients) {
+            String server = servers.get(serverIndex); // 현재 서버 선택
+            allocation.get(server).add(client); // 클라이언트 추가
+
+            serverIndex = (serverIndex + 1) % servers.size(); // 다음 서버로 이동 (마지막 서버 도달하면 처음으로)
+        }
+
+        return allocation;
+    }
+
+    public static Map<String, List<String>> sequenceAllocate(List<String> servers, List<String> clients) {
+        Map<String, List<String>> allocation = new HashMap<>();
+        for (String server : servers) {
+            allocation.put(server, new ArrayList<>());
+        }
+
+        int numClients = clients.size();
+        int numServers = servers.size();
+        int baseSize = numClients / numServers;  // 각 서버에 기본적으로 할당할 개수
+        int remainder = numClients % numServers; // 남는 개수 (마지막 서버에 할당)
+
+        int clientIndex = 0;
+        for (int i = 0; i < numServers; i++) {
+            int allocationSize = baseSize + (i < remainder ? 1 : 0); // 마지막 서버에 여분 추가
+            String server = servers.get(i);
+
+            for (int j = 0; j < allocationSize; j++) {
+                allocation.get(server).add(clients.get(clientIndex++));
+            }
+        }
+
+        return allocation;
+    }
+
+    public static void main(String[] args) {
+        List<String> serverList = Arrays.asList("Server-1", "Server-2", "Server-3");
+        List<String> clientList = Arrays.asList(
+                "L01", "L02", "L03", "L04", "L05", "L06", "L07", "L08", "L09", "L10",
+                "L11", "L12", "L13", "L14", "L15", "L16", "L17", "L18", "L19", "L20",
+                "L21", "L22", "L23", "L24", "L25", "L26", "L28", "L29", "L30", "L31",
+                "L32", "L33", "L34", "L35", "L36", "L37", "L39", "L40", "L41", "L42",
+                "L43", "L44", "L45", "L46", "L47", "L48", "L49", "L50", "L51", "L52",
+                "L53", "L54", "L55", "L56", "L57", "L58", "L59", "L60", "L65", "L66",
+                "L67", "L77", "L90", "L91", "L95"
+        );
+
+//        Map<String, List<String>> allocation = HaClusterEvenAllocator.allocate(serverList, clientList);
+        Map<String, List<String>> allocation = HaClusterEvenAllocator.sequenceAllocate(serverList, clientList);
+
+        // 결과 출력
+        allocation.forEach((server, assignedClients) -> {
+            log.info("server {} -> clients: {}", server, assignedClients);
+        });
+
+        HaClusterEvenAllocator allocator = new HaClusterEvenAllocator();
+        serverList.forEach(allocator::addServer);
+        allocator.allocate(clientList);
+        String server = "Server-1";
+        List<String> clients = allocator.get(server);
+        clients.forEach(client -> {
+            log.info("server {} -> client: {}", server, client);
+        });
+    }
+}

+ 52 - 0
its-cluster/src/main/java/com/its/common/cluster/utils/HaClusterHashAllocator.java

@@ -0,0 +1,52 @@
+package com.its.common.cluster.utils;
+
+import java.nio.ByteBuffer;
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.List;
+import java.util.Map;
+import java.util.TreeMap;
+
+public class HaClusterHashAllocator {
+    private TreeMap<Integer, String> hashRing = new TreeMap<>();
+    private List<String> servers;
+
+    public HaClusterHashAllocator(List<String> servers) {
+        this.servers = servers;
+        initializeHashRing();
+    }
+
+    // SHA-256 해시 생성 및 정수값으로 변환
+    private int generateStableHash(String key) {
+        try {
+            MessageDigest digest = MessageDigest.getInstance("SHA-256");
+            byte[] hashBytes = digest.digest(key.getBytes(StandardCharsets.UTF_8));
+            return Math.abs(ByteBuffer.wrap(hashBytes).getInt()); // 32비트 정수 변환
+        } catch (NoSuchAlgorithmException e) {
+            throw new RuntimeException("SHA-256 Algorithm not found!", e);
+        }
+    }
+
+    // 해시 링 초기화 (서버 추가)
+    private void initializeHashRing() {
+        for (String server : servers) {
+            int hash = generateStableHash(server);
+            hashRing.put(hash, server);
+        }
+    }
+
+    // 클러스터에 대한 서버 할당
+    public String allocateServer(String clientId) {
+        int hash = generateStableHash(clientId);
+        Map.Entry<Integer, String> entry = hashRing.ceilingEntry(hash);
+
+        // 만약 서버 해시 값이 초과하면 처음 서버로 할당
+        if (entry == null) {
+            return hashRing.firstEntry().getValue();
+        }
+
+        return entry.getValue();
+    }
+
+}

+ 2 - 2
its-cluster/src/main/java/com/its/common/cluster/vo/AbstractHaClusterConfig.java

@@ -104,8 +104,8 @@ public abstract class AbstractHaClusterConfig {
     private void loadClusterConfig() throws IOException {
         this.serverId = getIntValue("server.id", 1);
         this.syncSeconds = getIntValue("syncSeconds", 5);
-        if (this.syncSeconds < 5) {
-            this.syncSeconds = 5;
+        if (this.syncSeconds < 2) {
+            this.syncSeconds = 2;
         }
         if (this.syncSeconds > 60) {
             this.syncSeconds = 60;