- 光说不练假把式,造轮子就是要实践Raft算法。
- 基于Raft算法的分布式KV存储,Golang,C++等语言的非常之多,Java版本非常少。
- RPC框架(Netty4)
- 状态机&日志存储实现(Rocksdb)
- leader 选举
- 日志复制
- 成员变更
- Idea配置5个Application启动类,并设置
SERVICE_PORT
,以及SERVER_PORT
两个环境变量。 - 启动5个RaftNodeBootstrap.startRaft()方法。
- 监控日志。
public class RaftNodeBootstrap {
public static void main(String[] args) throws Throwable {
startRaft();
}
public static void startRaft() throws Throwable {
//获取Node实例
DefaultNode node = DefaultNode.getInstance();
//设置config信息
String[] peerAddr = {"127.0.0.1:2781", "127.0.0.1:2782", "127.0.0.1:2783", "127.0.0.1:2784", "127.0.0.1:2785"};
NodeConfig config = new NodeConfig();
config.setSelfPort(Integer.valueOf(System.getenv("SERVICE_PORT")));
config.setPeerAddrs(Arrays.asList(peerAddr));
node.setConfig(config);
//初始化节点
node.init();
//线程结束钩子,销毁node。
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
try {
node.destroy();
} catch (Throwable throwable) {
throwable.printStackTrace();
}
}));
}
}
存储uname:泰勒斯威夫特
public class TestKVStorage {
private static RpcClient rpcClient;
private static String addr = "127.0.0.1:2781";
static {
rpcClient = RpcClient.getInstance();
rpcClient.startRpcClient(DefaultNode.getInstance());
}
@Before
public void write() {
RpcRequest<Object> request = RpcRequest.builder()
.cmd(RpcRequest.CLIENT_REQ)
.url(addr)
.obj(ClientKVReq.builder()
.key("uname")
.value("泰勒斯威夫特")
.type(ClientKVReq.PUT)
.build()).build();
try {
Object response = rpcClient.sendSyncMsg(addr, request);
System.out.println("写入key后,返回结果json:" + JSON.toJSONString(response));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
@Test
public void read() {
RpcRequest<Object> request = RpcRequest.builder()
.cmd(RpcRequest.CLIENT_REQ)
.url(addr)
.obj(ClientKVReq.builder()
.key("uname")
.type(ClientKVReq.GET)
.build()).build();
try {
Object response = rpcClient.sendSyncMsg(addr, request);
System.out.println("读取Key后,返回结果:" + JSON.toJSONString(response));
} catch (InterruptedException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
}