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.
    • join

      Starts this raft server by joining an existing replication group. A JoinRequest is sent to an arbitrary member of the cluster.
      Parameters:
      cluster - a list of member ids that are part of the cluster and assist in joining.
      Returns:
      A completable future to be completed once the server has joined the cluster.
    • join

      default CompletableFuture<RaftServer> join(MemberId... cluster)
      Starts this raft server by joining an existing replication group. A JoinRequest is sent to an arbitrary member of the cluster.
      Parameters:
      cluster - a list of member ids that are part of the cluster and assist in joining.
      Returns:
      A completable future to be completed once the server has joined the cluster.
    • leave

      Requests to leave the replication group by sending a LeaveRequest to an arbitrary member of the cluster, as provided by the ClusterMembershipService.
      Returns:
      A future to be completed successfully once the server has left the cluster.
    • promote

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

      CompletableFuture<RaftServer> forceConfigure(Map<MemberId,RaftMember.Type> membersToRetain)
      Force configure the partition to remove all members which are not part of the given membersToRetain.

      This method is typically called to remove a set of unreachable members when there is no leader.

      Parameters:
      membersToRetain - The members to retain in the partition
      Returns:
      a future to be completed once the server has been force configured
    • reconfigurePriority

      CompletableFuture<Void> reconfigurePriority(int newPriority)
      Update priority of this server used for priority election. If priority election is not enabled, this method has no effect. To get the desired result, priority of all replicas must be updated accordingly. This method only updates the local server's priority.
      Parameters:
      newPriority - the priority to be set
      Returns:
      a future to be completed when the new priority is applied
    • 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.
    • 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.