Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 22 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,32 @@
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-core</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>${powermock.version}</version>
<scope>test</scope>
</dependency>
</dependencies>

<groupId>moe.cnkirito.sample</groupId>
<artifactId>consistent-hash</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<powermock.version>2.0.9</powermock.version>
</properties>
<build>
<plugins>
<plugin>
Expand All @@ -34,4 +55,4 @@
</build>


</project>
</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package moe.cnkirito.consistenthash;

/**
* @author daofeng.xjf
* @date 2019/2/15
*/
public interface AbstractHashStrategy {

/**
* 根据服务器地址标识符生成在一致性hash环上的hash值
*
* @param origin 服务器地址标识字符串
* @return 一致性hash环上的hash值
*/
int getHashCode(String origin);

}

This file was deleted.

11 changes: 0 additions & 11 deletions src/main/java/moe/cnkirito/consistenthash/HashStrategy.java

This file was deleted.

14 changes: 0 additions & 14 deletions src/main/java/moe/cnkirito/consistenthash/JdkHashCodeStrategy.java

This file was deleted.

22 changes: 22 additions & 0 deletions src/main/java/moe/cnkirito/consistenthash/LoadBalanceable.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package moe.cnkirito.consistenthash;

import moe.cnkirito.consistenthash.bo.Invocation;
import moe.cnkirito.consistenthash.bo.Server;

import java.util.List;

/**
* @author daofeng.xjf
* @date 2019/2/16
*/
public interface LoadBalanceable {

/**
* 根据数据的hash值在一致性hash环上选择第一个服务器
*
* @param servers 服务器列表
* @param invocation 包含数据hash值的请求
* @return 选择到的服务器
*/
Server select(List<Server> servers, Invocation invocation);
}
12 changes: 0 additions & 12 deletions src/main/java/moe/cnkirito/consistenthash/LoadBalancer.java

This file was deleted.

39 changes: 0 additions & 39 deletions src/main/java/moe/cnkirito/consistenthash/StatisticsUtil.java

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package moe.cnkirito.consistenthash;
package moe.cnkirito.consistenthash.bo;

/**
* @author daofeng.xjf
* @date 2019/2/15
*/
public class Invocation {
public Invocation() {
}
private String hashKey;

public Invocation() {}

public Invocation(String hashKey) {
this.hashKey = hashKey;
}

private String hashKey;

public String getHashKey() {
return hashKey;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package moe.cnkirito.consistenthash;
package moe.cnkirito.consistenthash.bo;

/**
* @author daofeng.xjf
* @date 2019/2/15
*/
public class Server {

public Server() {
}
private String url;

public Server() {}

public Server(String url) {
this.url = url;
}

private String url;

public String getUrl() {
return url;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package moe.cnkirito.consistenthash.load.balancer;


import moe.cnkirito.consistenthash.AbstractHashStrategy;
import moe.cnkirito.consistenthash.bo.Invocation;
import moe.cnkirito.consistenthash.LoadBalanceable;
import moe.cnkirito.consistenthash.bo.Server;
import moe.cnkirito.consistenthash.strategy.FnvHashStrategy;
import moe.cnkirito.consistenthash.strategy.HashStratetyFactory;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
* @author daofeng.xjf
* @date 2019/2/15
*/
public class ConsistentHashLoadBalancer implements LoadBalanceable {

private static final AbstractHashStrategy hashStrategy = HashStratetyFactory.getHashStrategy();

@Override
public Server select(List<Server> servers, Invocation invocation) {
int invocationHashCode = hashStrategy.getHashCode(invocation.getHashKey());
ConsistentHashRing consistentHashRing = ConsistentHashRing.getInstance(servers);
return consistentHashRing.locate(invocationHashCode);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package moe.cnkirito.consistenthash.load.balancer;

import com.google.common.annotations.VisibleForTesting;
import moe.cnkirito.consistenthash.AbstractHashStrategy;
import moe.cnkirito.consistenthash.bo.Server;
import moe.cnkirito.consistenthash.strategy.FnvHashStrategy;
import moe.cnkirito.consistenthash.strategy.HashStratetyFactory;

import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import static moe.cnkirito.consistenthash.load.balancer.constant.HashRingConstant.VIRTUAL_NODE_SIZE;
import static moe.cnkirito.consistenthash.load.balancer.constant.HashRingConstant.VIRTUAL_NODE_SUFFIX;

/**
* 一致性hash环
*
* @author dailj
* @date 2022/11/25 15:54
*/
public class ConsistentHashRing {
private static ConsistentHashRing instance;
private static TreeMap<Integer, Server> virtualNodeRing;
private static AbstractHashStrategy hashStrategy = HashStratetyFactory.getHashStrategy();

public static ConsistentHashRing getInstance(List<Server> servers) {
if (instance == null) {
synchronized (ConsistentHashRing.class) {
if (instance == null) {
instance = new ConsistentHashRing(servers);
}
}
}
return instance;
}

public Server locate(Integer invocationHashCode) {
// 向右找到第一个 key
Map.Entry<Integer, Server> locateEntry = virtualNodeRing.ceilingEntry(invocationHashCode);
if (locateEntry == null) {
// 想象成一个环,超过尾部则取第一个 key
locateEntry = virtualNodeRing.firstEntry();
}
return locateEntry.getValue();
}

private ConsistentHashRing(List<Server> servers) {
init(servers);
}

private ConsistentHashRing() {}

private void init(List<Server> servers) {
virtualNodeRing = buildConsistentHashRing(servers);
}

private TreeMap<Integer, Server> buildConsistentHashRing(List<Server> servers) {
TreeMap<Integer, Server> virtualNodeRing = new TreeMap<>();
for (Server server : servers) {
for (int i = 0; i < VIRTUAL_NODE_SIZE; i++) {
// 新增虚拟节点的方式如果有影响,也可以抽象出一个由物理节点扩展虚拟节点的类
virtualNodeRing.put(hashStrategy.getHashCode(server.getUrl() + VIRTUAL_NODE_SUFFIX + i), server);
}
}
return virtualNodeRing;
}
}
Loading