Buy Negative Google Reviews

Search engine optimization (SEO) is an important part of online marketing. It helps businesses increase their visibility on search engines, such as Google. But, what if you want to gain visibility…

Smartphone

独家优惠奖金 100% 高达 1 BTC + 180 免费旋转




Extensible Raft Consensus algorithm in .NET

Consensus means multiple servers agreeing on same information. It’s needed to design fault-tolerant distributed systems.

Raft is a consensus algorithm that is designed to be easy to understand. It’s equivalent to Paxos in fault-tolerance and performance. The difference is that it’s decomposed into relatively independent subproblems, and it cleanly addresses all major pieces needed for practical systems.

I was introduced to Raft first via this fantastic video on YouTube. And the ending really cracked me up.

I will not delve into the inner workings of Raft, since it has been brilliantly explained in the above resources and of course in other online materials. But there is one thing which may help you understand Raft a bit more, and that is hands-on experience.

Believe me when I say that working on this side project of mine took over a year. To completely grasp, interpret and extend the algorithm, implement different aspects and features listed in the paper, while keeping the code as readable as possible was an entertaining challenge.

Coracle.Raft in .NET

Coracle.Raft is a completely extensible implementation of the Raft consensus algorithm in .NET which can be used to clusterize your own functionality and build your own replicated state machine.

There are 4 important aspects which make it extensible:

Moreover, there are some additional features:

To know more about Coracle.Raft, check out this GitHub repository.

This section deals with the demo of Coracle.Raft with an example use-case.

Coracle.Raft.Examples has a very basic example where —

Check out Coracle.Raft.Examples:

To get things rolling however, we would need to extend a couple of more stuff. This is where Coracle.Web.Examples comes in, where —

You can check out the implementation of Coracle.Web.Examples here:

To make it easy to understand, the UI shown in the following videos have certain internal RAFT properties being captured and displayed using SignalR for every node.

Let’s get started.

We start off with 3 Coracle nodes. Each Web API launched using Kestrel is internally running Coracle.Raft, and below are their NodeIds and Uris:

Once we click on “Ready Coracle” for any node, the Initialization and Start of the Coracle.Raft node takes place.

For initialization, ICoracleNode.InitializeConfiguration() is called and internally the following occurs:

Each node holds a chain of log entries. Each entry would store the Term, Index, Type and Contents. The Term and Index are apparent, but the Type is an enum which can have any of the below:

The Contents of that corresponding entry would reflect data pertaining to that type.

The PersistentStateHandler is responsible for all operations w.r.t involatile data; inclusive of the log chain discussed above.

Once the node starts, as RAFT suggests, the initial state is Follower. The number of functional nodes in cluster must be equal to or more than 3, and for majorities to follow, an odd number is suggested for achieving quorum.

Each node has a randomized timeout for when it can start candidacy. The timeout is set between the Minimum and Maximum election timeouts in the IEngineConfiguration settings.

If we take our example, the Node3 times-out and it becomes a Candidate and start elections; and internally fires RequestVoteRPCs to other nodes.

The specifics of how the node serializes the data and communicates with other coracle nodes is all left to the implementation of IOutboundRequestHandler. Here, we are using HTTP-based Web APIs with JSON payloads.

Once Node3 receives a majority of votes, i.e. RequestVoteRPC responses with VoteGranted as true, the node changes its own state to Leader. Once Leader, it would write a new NoOperation entry to its log and send multiple outbound AppendEntriesRPC to other nodes. This RPC is not only used to replicate logEntries, but also serves as a heartbeat thereafter.

The functionality of the cluster can be described by the way ICommand works and how the IStateMachineHandler interprets these commands. The purpose of the cluster implementing Coracle.Raft can be anything; it could be to maintain a replicated state machine which represents a distributed key-value store, or something much more complex. For our example, we are using it to store “Notes” which are nothing but string key-value pairs — UniqueHeader:Text.

The ICommand has been implemented accordingly for adding and reading notes. The IStateMachineHandler also needs to be compatible to process these commands. The ICommand contains some mandatory properties:

For issuing commands, the internal component ICommandExecutor can be called from DI, and ICommandExecutor.Execute() can be invoked with the ICommand object.

Non-readonly commands are handled by the Leader, i.e. Node3. Thus the internal client will contact Node2, Node2 will return back the recognized Leader, and the client will then send that request to Node3.

Once Node3 gets the command, internally, it would write a new entry into its log with Type as Command, and make sure that the entry is replicated across a majority of the cluster. Once that occurs, the Leader would commit that entry, and apply it to the state machine using IStateMachineHandler.ExecuteAndApply(). Once the command is applied, the Execute() call ends, as the result for the applied command is returned using IStateMachineHandler.TryGetResult()

Read-only commands need linearizable and consistent outputs, thus the Leader Node3 again has to repond to the command. The Leader has to make sure it has not deposed (i.e check if it is still the leader of the cluster) before it responds to the command. Thus, it would wait and affirm via background AppendEntriesRPCs, and finally respond back using IStateMachineHandler.TryGetResult().

In the background, a node compacts logEntries based on certain criteria, and the state of the system is chunked and stored under a snapshot.

Here, we issue multiple commands to add notes. Since our SnapshotThresholdSize (which denotes the size of entries to compact) is set to 5 and SnapshotBufferSizeFromLastEntry (which denotes a buffer size required from the last applied entry) is set to 1, we need at least 6 entries for compaction to occur.

As seen in the above video, once compaction occurs, a new snapshot logEntry has replaced the previous 5 entries after Index 0, and 1 entry has been left at the end.

The same is not true for the follower nodes Node1 and Node2:

Both the Follower nodes have 5 entries (excluding None entry). It is expected that there not only be 5 entries in the log chain, but ALSO 1 extra entry inclusive of the last applied entry (as the SnapshotBufferSizeFromLastEntry is set to 1). Since one extra entry is missing, local compaction was not triggered for Node1 and Node2.

If there is a need to add/remove nodes from the operational cluster, RAFT suggests using the “Joint-Consensus” approach. The above workflow is internally handled, and the IConfigurationRequestExecutor.IssueChange() can be called by supplying the desired configuration.

In our case, we wanted to remove Node3 (the current Leader) and add a different node “Node4”:

Once Node3 receives that request, it would do the following:

In the above video, we see that since the Heartbeats stopped from Node3 to all other nodes, Node4 timed out, won the elections and became the new Leader.

Apart from the core functionality explained above, if there ever is a need to check out how the internal processing happens, the ActivityLogger in the UI can be turned on.

If you still think there’s a lot I have missed out, you’re right. To keep it short and simple, I’ve put up the bare minimum here. The extensive documentation is present here:

You can use the above example and try it out yourself here:

— Or you can build your own implementation using Coracle.Raft:

Here’s the NuGet link:

Well, hope you liked it! 😃 Thanks for the read and cheers! 🍻

Add a comment

Related posts:

Buy 5 Star Google Reviews

Buy 5-Star Google Reviews Google’s star rating system is nothing new. As early as the early 2000s, they started using 5-star reviews on their maps and other products, much like TripAdvisor and Yelp…

Bware LABS

Bware Labs is a tech startup that has been making waves in the industry since its inception. Founded in 2019 by a group of passionate tech enthusiasts, Bware Labs is dedicated to creating innovative…

How to hack a music venue for deaf and disabled audiences

Attitude is Everything (AIE) has published a new DIY guide for bands and promoters, showing cheap and easy ways to make gigs more accessible for deaf and disabled fans. DIY Access Guide will be…