public class LittleCASPaxos extends Object
This is a super simple Single-Decree Paxos implementation as outlined in this paper https://arxiv.org/abs/1802.07000 . This allows for consensus mutation of an arbitrary set of key/values. In this case, keys are strings. While it is simple, it is pretty cool and does the job if you need to prototype consensus. For an earlier discussion of the same paper's impl, the one I originally did the impl from, see this (and associated) link: http://rystsov.info/2015/09/16/how-paxos-works.html With all due respect the LL, these sources are much more digestible than the original paper.
You have to provide impls for the Network and the Storage, as well as the Node specifier. All of the KV, Ballot, and message implementations should be Serializable for simple usage.
It's notoriously hard to get Paxos of any flavor right, though SDP is a lot simpler than any of the Multi-Paxos algorithms. And testing is hard. So it is even money there is a bug here and there, more eyes will help. Still, should be close.
As a consequence of SDP, you'll note you provide a transform function for the value of key; to "read" a value, you need use the identity function, and run the full 2 stage paxos round, else you lose linearizability. Note that we do none of the optimizations outlined in the paper.
In this case, each node is a LittleCASPaxos object. If you wanted a remote
client, then use some protocol to remotely invoke the
paxos(String, Function, int, long, TimeUnit) method and return the
result. Note that in SDP, you can start a round from any node, there are no
distinguished nodes.
Note also that there is no enumeration/iteration; traversal like this is not a natural fit for CASPaxos, and would need further thought. With a sorted storage, you could do range queries with paxos rounds if you wanted, but thats more than I want to do.
A more expansive impl could do lots more, like formalize adding and removing nodes (see the paper for how this proceeds), turning single operations into sequences of mutations, iteration, sloppy reads, etc. Lots of directions to go.
It would be interesting to do a single file Raft impl, but that's actually a lot more complicated, at least so it seems, because log-based consensus just seems heavier.
| Modifier and Type | Class and Description |
|---|---|
static class |
LittleCASPaxos.Acceptance
Acceptance message.
|
static class |
LittleCASPaxos.Ballot
Immutable ballot for Paxos rounds.
|
static class |
LittleCASPaxos.KV
Key and value with last modification ballot.
|
static interface |
LittleCASPaxos.Node
Node interface.
|
static class |
LittleCASPaxos.PaxosResult
Result codes, blah.
|
static class |
LittleCASPaxos.Prepare
Proposal message.
|
static class |
LittleCASPaxos.RoundResult
Result of a paxos round (prep/accept).
|
static class |
LittleCASPaxos.RoundStepResult
Result message.
|
| Constructor and Description |
|---|
LittleCASPaxos(org.sfj.LittleCASPaxos.Network net,
LittleCASPaxos.Node me,
org.sfj.LittleCASPaxos.Storage storage)
Create a paxos node.
|
| Modifier and Type | Method and Description |
|---|---|
LittleCASPaxos.RoundResult |
paxos(String key,
Function<Object,Object> transform,
int quorum,
long roundTimeout,
TimeUnit units)
Actual entry point to run a paxos round.
|
void |
processAcceptance(LittleCASPaxos.Acceptance acc,
Consumer<LittleCASPaxos.RoundStepResult> response)
Call this process an Acceptance message.
|
void |
processPrepare(LittleCASPaxos.Prepare prep,
Consumer<LittleCASPaxos.RoundStepResult> response)
Call this to process a Prepare message.
|
public LittleCASPaxos(org.sfj.LittleCASPaxos.Network net,
LittleCASPaxos.Node me,
org.sfj.LittleCASPaxos.Storage storage)
Create a paxos node. You need to provide a network, which node this is,
and a sotrage component. Generally, you invoke by calling
paxos(String, Function, int, long, TimeUnit); this will send prepare
messages to each node, and then based on that send accept messages to
everyone.
The network needs to process Prepare/Accept messages and process them
on the local node by calling processPrepare(Prepare, Consumer)
and processAcceptance(Acceptance, Consumer)
net - Networkme - This nodestorage - Storage provider.public void processPrepare(LittleCASPaxos.Prepare prep, Consumer<LittleCASPaxos.RoundStepResult> response)
prep - Prepare messageresponse - consumer for response.public void processAcceptance(LittleCASPaxos.Acceptance acc, Consumer<LittleCASPaxos.RoundStepResult> response)
acc - Acceptance messageresponse - Response consumerpublic LittleCASPaxos.RoundResult paxos(String key, Function<Object,Object> transform, int quorum, long roundTimeout, TimeUnit units)
key - key in questiontransform - transform to apply to current valuequorum - quorum for successroundTimeout - timeout for each of the stagesunits - timout unitsCopyright © 2020. All rights reserved.