Interface RaftServer

All Known Implementing Classes:
DefaultRaftServer

public interface RaftServer
Provides a standalone implementation of the Raft consensus algorithm.

To create a new server, use the server RaftServer.Builder. Servers require cluster membership information in order to perform communication. Each server must be provided a local MemberId to which to bind the internal RaftServerProtocol and a set of addresses for other members in the cluster.

State machines

State machines are provided in a factory to allow servers to transition between stateful and stateless states.

 Address address = new Address("123.456.789.0", 5000);
 Collection<Address> members = Arrays.asList(new Address("123.456.789.1", 5000), new Address("123.456.789.2", 5000));

 RaftServer server = RaftServer.builder(address)
   .withStateMachine(MyStateMachine::new)
   .build();

 
Raft relies upon determinism to ensure consistency throughout the cluster, so it is imperative that each server in a cluster have the same state machine with the same commands. State machines are provided to the server as a factory to allow servers to transition between stateful and stateless states.

Storage

By default, the log is stored on disk, but users can override the default RaftStorage configuration via RaftServer.Builder.withStorage(RaftStorage).

 RaftServer server = RaftServer.builder(address)
   .withStateMachine(MyStateMachine::new)
   .withStorage(Storage.builder()
     .withDirectory(new File("logs"))
     .build())
   .build();
 
Servers use the Storage object to manage the storage of cluster configurations, voting information, and state machine snapshots in addition to logs. See the RaftStorage documentation for more information.

Bootstrapping the cluster

Once a server has been built, it must be bootstrapped to form a new cluster.

 CompletableFuture<RaftServer> future = server.bootstrap();
 future.thenRun(() -> {
   System.out.println("Server bootstrapped!");
 });

 
Alternatively, the bootstrapped cluster can include multiple servers by providing an initial configuration to the bootstrap(MemberId...) method on each server. When bootstrapping a multi-node cluster, the bootstrap configuration must be identical on all servers for safety.

 List<Address> cluster = Arrays.asList(
   new Address("123.456.789.0", 5000),
   new Address("123.456.789.1", 5000),
   new Address("123.456.789.2", 5000)
 );

 CompletableFuture<RaftServer> future = server.bootstrap(cluster);
 future.thenRun(() -> {
   System.out.println("Cluster bootstrapped");
 });

 
See Also:
  • Method Details

    • builder

      static RaftServer.Builder builder()
      Returns a new Raft server builder using the default host:port.

      The server will be constructed at 0.0.0.0:8700.

      Returns:
      The server builder.
    • builder

      static RaftServer.Builder builder(MemberId localMemberId)
      Returns a new Raft server builder.

      The provided MemberId is the address to which to bind the server being constructed.

      Parameters:
      localMemberId - The local node identifier.
      Returns:
      The server builder.
    • name

      String name()
      Returns the server name.

      The server name is provided to the server via the builder configuration. The name is used internally to manage the server's on-disk state. Log, snapshot, and configuration files stored on disk use the server name as the prefix.

      Returns:
      The server name.
    • cluster

      RaftCluster cluster()
      Returns the server's cluster configuration.

      The RaftCluster is representative of the server's current view of the cluster configuration. The first time the server is started, the cluster configuration will be initialized using the MemberId list provided to the server builder

      Returns:
      The server's cluster configuration.
    • addRoleChangeListener

      void addRoleChangeListener(RaftRoleChangeListener listener)
      Adds a role change listener.
      Parameters:
      listener - The role change listener that consumes the role and the raft term.
    • removeRoleChangeListener

      void removeRoleChangeListener(RaftRoleChangeListener listener)
      Removes a role change listener.
      Parameters:
      listener - The role change listener to remove.
    • addFailureListener

      void addFailureListener(FailureListener listener)
      Adds a failure listener
    • removeFailureListener

      void removeFailureListener(FailureListener listener)
      Removes a failure listener
    • bootstrap

      default CompletableFuture<RaftServer> bootstrap()
      Bootstraps a single-node cluster.

      Bootstrapping a single-node cluster results in the server forming a new cluster to which additional servers can be joined.

      Only RaftMember.Type.ACTIVE members can be included in a bootstrap configuration. If the local server is not initialized as an active member, it cannot be part of the bootstrap configuration for the cluster.

      When the cluster is bootstrapped, the local server will be transitioned into the active state and begin participating in the Raft consensus algorithm. When the cluster is first bootstrapped, no leader will exist. The bootstrapped members will elect a leader amongst themselves.

      It is critical that all servers in a bootstrap configuration be started with the same exact set of members. Bootstrapping multiple servers with different configurations may result in split brain.

      The CompletableFuture returned by this method will be completed once the cluster has been bootstrapped, a leader has been elected, and the leader has been notified of the local server's client configurations.

      Returns:
      A completable future to be completed once the cluster has been bootstrapped.
    • bootstrap

      Bootstraps the cluster using the provided cluster configuration.

      Bootstrapping the cluster results in a new cluster being formed with the provided configuration. The initial nodes in a cluster must always be bootstrapped. This is necessary to prevent split brain. If the provided configuration is empty, the local server will form a single-node cluster.

      Only RaftMember.Type.ACTIVE members can be included in a bootstrap configuration. If the local server is not initialized as an active member, it cannot be part of the bootstrap configuration for the cluster.

      When the cluster is bootstrapped, the local server will be transitioned into the active state and begin participating in the Raft consensus algorithm. When the cluster is first bootstrapped, no leader will exist. The bootstrapped members will elect a leader amongst themselves.

      It is critical that all servers in a bootstrap configuration be started with the same exact set of members. Bootstrapping multiple servers with different configurations may result in split brain.

      The CompletableFuture returned by this method will be completed once the cluster has been bootstrapped, a leader has been elected, and the leader has been notified of the local server's client configurations.

      Parameters:
      cluster - The bootstrap cluster configuration.
      Returns:
      A completable future to be completed once the cluster has been bootstrapped.
    • bootstrap

      default CompletableFuture<RaftServer> bootstrap(MemberId... members)
      Bootstraps the cluster using the provided cluster configuration.

      Bootstrapping the cluster results in a new cluster being formed with the provided configuration. The initial nodes in a cluster must always be bootstrapped. This is necessary to prevent split brain. If the provided configuration is empty, the local server will form a single-node cluster.

      Only RaftMember.Type.ACTIVE members can be included in a bootstrap configuration. If the local server is not initialized as an active member, it cannot be part of the bootstrap configuration for the cluster.

      When the cluster is bootstrapped, the local server will be transitioned into the active state and begin participating in the Raft consensus algorithm. When the cluster is first bootstrapped, no leader will exist. The bootstrapped members will elect a leader amongst themselves.

      It is critical that all servers in a bootstrap configuration be started with the same exact set of members. Bootstrapping multiple servers with different configurations may result in split brain.

      The CompletableFuture returned by this method will be completed once the cluster has been bootstrapped, a leader has been elected, and the leader has been notified of the local server's client configurations.

      Parameters:
      members - The bootstrap cluster configuration.
      Returns:
      A completable future to be completed once the cluster has been bootstrapped.
    • promote

      Promotes the server to leader if possible.
      Returns:
      a future to be completed once the server has been promoted
    • compact

      Compacts server logs.
      Returns:
      a future to be completed once the server's logs have been compacted
    • flushLog

      CompletableFuture<Void> flushLog()
      Ensures that all records written to the log are flushed to disk
      Returns:
      a future which will be completed after the log is flushed to disk
    • shutdown

      CompletableFuture<Void> shutdown()
      Shuts down the server without leaving the Raft cluster.
      Returns:
      A completable future to be completed once the server has been shutdown.
    • goInactive

      CompletableFuture<Void> goInactive()
      Transitions the server to INACTIVE without shutting down or leaving the cluster.
      Returns:
      A completable future to be completed once the server is inactive.
    • getContext

      RaftContext getContext()
      Returns the current Raft context.
      Returns:
      the current Raft context
    • getTerm

      long getTerm()
      Returns the server's term.
      Returns:
      the server's term
    • isFollower

      default boolean isFollower()
      Returns whether the server is a follower.
      Returns:
      whether the server is a follower
    • getRole

      RaftServer.Role getRole()
      Returns the server role.

      The initial state of a Raft server is RaftServer.Role.INACTIVE. Once the server is started and until it is explicitly shutdown, the server will be in one of the active states - RaftServer.Role.PASSIVE, RaftServer.Role.FOLLOWER, RaftServer.Role.CANDIDATE, or RaftServer.Role.LEADER.

      Returns:
      The server role.
    • isLeader

      default boolean isLeader()
      Returns whether the server is the leader.
      Returns:
      whether the server is the leader
    • isRunning

      boolean isRunning()
      Returns a boolean indicating whether the server is running.
      Returns:
      Indicates whether the server is running.
    • stepDown

      CompletableFuture<Void> stepDown()
      Steps down from the current leadership, which means tries to transition directly to follower.