\section{Arbitrary configuration changes using joint consensus} \label{membership:arbitrary} This section presents a more complex approach to cluster membership changes that handles arbitrary changes to the configuration at one time. For example, two servers can be added to a cluster at once, or all of the servers in a five-server cluster can be replaced at once. This was the first approach to membership changes that we came up with, and it is described only for completeness. Now that we know about the simpler single-server approach, we recommend that one instead, since handling arbitrary changes requires extra complexity. Arbitrary changes are typically the way membership changes are assumed to operate in the literature, but we don't think this flexibility is needed in real systems, where a series of single-server changes can change the cluster membership to any desired configuration. To ensure safety across arbitrary configuration changes, the cluster first switches to a transitional configuration we call \emph{joint consensus}; once the joint consensus has been committed, the system then transitions to the new configuration. The joint consensus combines both the old and new configurations: \begin{itemize} \item Log entries are replicated to all servers in both configurations. \item Any server from either configuration may serve as leader. \item Agreement (for elections and entry commitment) requires separate majorities from \emph{both} the old and new configurations. For example, when changing from a cluster of 3 servers to a different cluster of 9 servers, agreement requires both 2 of the 3 servers in the old configuration and 5 of the 9 servers in the new configuration. \end{itemize} The joint consensus allows individual servers to transition between configurations at different times without compromising safety. Furthermore, joint consensus allows the cluster to continue servicing client requests throughout the configuration change. \begin{figure} \centering \includegraphics[scale=.50]{membership/reconfigurationconf} \vcaption[joint consensus timeline]{ Timeline for a configuration change using joint consensus. Dashed lines show configuration entries that have been created but not committed, and solid lines show the latest committed configuration entry. The leader first creates the \cboth{} configuration entry in its log and commits it to \cboth{} (a majority of \cold{} and a majority of \cnew{}). Then it creates the \cnew{} entry and commits it to a majority of \cnew{}. There is no point in time in which \cold{} and \cnew{} can both make decisions independently. } \label{fig:membership:reconfiguration} \end{figure} This approach extends the single-server membership change algorithm with an intermediate log entry for the joint configuration; Figure~\ref{fig:membership:reconfiguration} illustrates the process. When the leader receives a request to change the configuration from \cold{} to \cnew{}, it stores the configuration for joint consensus (\cboth{} in the figure) as a log entry and replicates that entry using the normal Raft mechanism. As with the single-server configuration change algorithm, each server starts using a new configuration as soon as it stores the configuration in its log. This means that the leader will use the rules of \cboth{} to determine when the log entry for \cboth{} is committed. If the leader crashes, a new leader may be chosen under either \cold{} or \cboth{}, depending on whether the winning candidate has received \cboth{}. In any case, \cnew{} cannot make unilateral decisions during this period. Once \cboth{} has been committed, neither \cold{} nor \cnew{} can make decisions without approval of the other, and the Leader Completeness Property ensures that only servers with the \cboth{} log entry can be elected as leader. It is now safe for the leader to create a log entry describing \cnew{} and replicate it to the cluster. Again, this configuration will take effect on each server as soon as it is seen. When the \cnew{} log entry has been committed under the rules of \cnew{}, the old configuration is irrelevant and servers not in the new configuration can be shut down. As shown in Figure~\ref{fig:membership:reconfiguration}, there is no time when \cold{} and \cnew{} can both make unilateral decisions; this guarantees safety. The joint consensus approach could be generalized to allow a configuration change to begin while a prior change was still in progress. However, there would not be much practical advantage to doing this. Instead, a leader rejects additional configuration changes when a configuration change is already in progress (when its latest configuration is not committed or is not a simple majority). Changes that are rejected in this way can simply wait and try again later. This joint consensus approach is more complex than the single-server changes precisely because it requires transitioning to and from an intermediate configuration. Joint configurations also require changes to how all voting and commitment decisions are made; instead of simply counting servers, the leader must check if the servers form a majority of the old cluster and also form a majority of the new cluster. Implementing this required finding and changing about six comparisons in our Raft implementation~\cite{logcabin}.