Documentation ¶
Overview ¶
Example (GRPC) ¶
package main import ( "io" "github.com/alekseyvit/raft" "github.com/alekseyvit/raft/transport" "github.com/alekseyvit/raft/transport/raftgrpc" "google.golang.org/grpc" ) type stateMachine struct{} func (stateMachine) Apply([]byte) {} func (stateMachine) Snapshot() (r io.ReadCloser, err error) { return } func (stateMachine) Restore(io.ReadCloser) (err error) { return } func main() { srv := grpc.NewServer() node := raft.NewNode(stateMachine{}, transport.GRPC) raftgrpc.RegisterHandler(srv, node.Handler()) }
Output:
Example (Http) ¶
package main import ( "io" "net/http" "github.com/alekseyvit/raft" "github.com/alekseyvit/raft/transport" "github.com/alekseyvit/raft/transport/rafthttp" ) type stateMachine struct{} func (stateMachine) Apply([]byte) {} func (stateMachine) Snapshot() (r io.ReadCloser, err error) { return } func (stateMachine) Restore(io.ReadCloser) (err error) { return } func main() { node := raft.NewNode(stateMachine{}, transport.HTTP) handler := rafthttp.Handler(node.Handler()) _ = http.Server{ Handler: handler, } }
Output:
Index ¶
- Constants
- Variables
- type Member
- type MemberType
- type Node
- func (n *Node) AddMember(ctx context.Context, raw *RawMember) error
- func (n *Node) DemoteMember(ctx context.Context, id uint64) error
- func (n *Node) GetMemebr(id uint64) (Member, bool)
- func (n *Node) Handler() etransport.Handler
- func (n *Node) HardState() (etcdraftpb.HardState, error)
- func (n *Node) Leader() uint64
- func (n *Node) Leave(ctx context.Context) error
- func (n *Node) LinearizableRead(ctx context.Context) error
- func (n *Node) Members() []Member
- func (n *Node) PromoteMember(ctx context.Context, id uint64) error
- func (n *Node) RemoveMember(ctx context.Context, id uint64) error
- func (n *Node) Replicate(ctx context.Context, data []byte) error
- func (n *Node) Shutdown(ctx context.Context) error
- func (n *Node) Snapshot() (io.ReadCloser, error)
- func (n *Node) SoftStatus() (raft.SoftState, error)
- func (n *Node) Start(opts ...StartOption) error
- func (n *Node) Stepdown(ctx context.Context) error
- func (n *Node) TermIndex() (uint64, uint64, error)
- func (n *Node) TransferLeadership(ctx context.Context, id uint64) error
- func (n *Node) UpdateMember(ctx context.Context, raw *RawMember) error
- func (n *Node) Whoami() uint64
- type NodeGroup
- type Option
- func WithCheckQuorum() Option
- func WithContext(ctx context.Context) Option
- func WithDisableProposalForwarding() Option
- func WithDrainTimeOut(d time.Duration) Option
- func WithElectionTick(tick int) Option
- func WithHeartbeatTick(tick int) Option
- func WithLinearizableReadLeaseBased() Option
- func WithLinearizableReadSafe() Option
- func WithLogger(lg raftlog.Logger) Option
- func WithMaxCommittedSizePerReady(max uint64) Option
- func WithMaxInflightMsgs(max int) Option
- func WithMaxSizePerMsg(max uint64) Option
- func WithMaxSnapshotFiles(max int) Option
- func WithMaxUncommittedEntriesSize(max uint64) Option
- func WithPipelining() Option
- func WithPreVote() Option
- func WithSnapshotInterval(i uint64) Option
- func WithStateDIR(dir string) Option
- func WithStreamTimeOut(d time.Duration) Option
- func WithTickInterval(d time.Duration) Option
- type RawMember
- type StartOption
- func WithAddress(addr string) StartOption
- func WithFallback(opts ...StartOption) StartOption
- func WithForceJoin(addr string, timeout time.Duration) StartOption
- func WithForceNewCluster() StartOption
- func WithInitCluster() StartOption
- func WithJoin(addr string, timeout time.Duration) StartOption
- func WithMembers(membs ...RawMember) StartOption
- func WithRestart() StartOption
- func WithRestore(path string) StartOption
- type StateMachine
Examples ¶
Constants ¶
const None = raft.None
None is a placeholder node ID used to identify non-existence.
Variables ¶
var ( // ErrNodeStopped is returned by the Node methods after a call to // Shutdown or when it has not started. ErrNodeStopped = raftengine.ErrStopped // ErrNotLeader is returned when an operation can't be completed on a // follower or candidate node ErrNotLeader = errors.New("raft: node is not the leader") )
Functions ¶
This section is empty.
Types ¶
type Member ¶
type Member interface { ID() uint64 Address() string ActiveSince() time.Time IsActive() bool Type() MemberType Raw() RawMember }
Member represents a raft cluster member.
type MemberType ¶
type MemberType = raftpb.MemberType
MemberType used to distinguish members (voter, learner, etc).
const ( // VoterMember participate in elections and log entry commitment, It is the default type. VoterMember MemberType = raftpb.VoterMember // RemovedMember represents an removed raft node. RemovedMember MemberType = raftpb.RemovedMember // LearnerMember will receive log entries, but it won't participate in elections or log entry commitment. LearnerMember MemberType = raftpb.LearnerMember // StagingMember will receive log entries, but it won't participate in elections or log entry commitment, // and once it receives enough log entries to be sufficiently caught up to // the leader's log, the leader will promote him to VoterMember. StagingMember MemberType = raftpb.StagingMember )
type Node ¶
type Node struct {
// contains filtered or unexported fields
}
Node is a controller of the current effective raft member, It also represents the front API to proposes changes into the raft cluster.
Node packed with a built-in segmented WAL to provide durability and ensure data integrity. alongside snapshotter that take a snapshot of the state of a system at a particular point in time. Although, the application must have its own backend DB delegated by the state machine interface.
Node also maintains a membership pool containing all other raft members.
Multiple goroutines may invoke methods on a Node simultaneously.
func NewNode ¶
func NewNode(fsm StateMachine, proto etransport.Proto, opts ...Option) *Node
NewNode construct a new node from the given configuration. The returned node is in a stopped state, therefore it must be start explicitly.
func (*Node) AddMember ¶
AddMember proposes to add the given member to the cluster, It considered complete after reaching a majority. After committing the addition, each member in the cluster add the given member to its pool.
Although, most applications will use the basic join.
If the provided context expires before, the add is complete, AddMember returns the context's error, otherwise it returns any error returned due to the add.
If the provided member id is None, AddMember will assign next available id.
func (*Node) DemoteMember ¶
DemoteMember proposes to take away a member vote. It considered complete after reaching a majority. After committing the demotion, each member in the cluster updates the given member type on its pool.
If the provided context expires before, the promotion is complete, DemoteMember returns the context's error, otherwise it returns any error returned due to the demotion.
func (*Node) GetMemebr ¶
GetMemebr returns member associated to the given id if exist, Otherwise, it return nil and false.
func (*Node) Handler ¶
func (n *Node) Handler() etransport.Handler
Handler return node transportation handler, that delegated to respond to RPC requests over the wire. the returned handler must be registered with the transportation server, unless the node is registered with a node group.
func (*Node) Leader ¶
Leader returns the id of the raft cluster leader, if there any. Otherwise, it return None.
func (*Node) Leave ¶
Leave proposes to remove current effective member. See the documentation of "RemoveMember" for more information.
func (*Node) LinearizableRead ¶
LinearizableRead implies that once a write completes, all later reads should return the value of that write, or the value of a later write.
func (*Node) PromoteMember ¶
PromoteMember proposes to promote a learner member to a voting member, It considered complete after reaching a majority. After committing the promotion, each member in the cluster updates the given member type on its pool.
If the provided context expires before, the promotion is complete, PromoteMember returns the context's error, otherwise it returns any error returned due to the promotion.
func (*Node) RemoveMember ¶
RemoveMember proposes to remove the given member from the cluster, It considered complete after reaching a majority. After committing the removal, each member in the cluster remove the given member from its pool.
Although, the removed member configuration will remain and only its type will be changed to "RemovedMember". therefore its id is not reusable again, and its cannot rejoin the cluster again.
If the provided context expires before, the removal is complete, RemoveMember returns the context's error, otherwise it returns any error returned due to the removal.
func (*Node) Replicate ¶
Replicate proposes to replicate the given data to all raft members, in a highly consistent manner. If the provided context expires before, the replication is complete, Replicate returns the context's error, otherwise it returns any error returned due to the replication.
func (*Node) Shutdown ¶
Shutdown gracefully shuts down the node without interrupting any active requests. Shutdown works by first closing all open requests listeners, then blocks until all the pending requests are finished, and then shut down. If the provided context expires before the shutdown is complete, Shutdown force the node to shut off, Shutdown returns any error returned from closing the Node's underlying internal(s).
When Shutdown is called, Start may immediately return ErrNodeStopped. Make sure the program doesn't exit and waits instead for Shutdown to return.
func (*Node) Snapshot ¶
func (n *Node) Snapshot() (io.ReadCloser, error)
Snapshot is used to manually force node to take a snapshot. Returns a io.ReadCloser that can be used to to read snapshot file. the caller must invoke close method on the returned io.ReadCloser explicitly, Otherwise, the underlying os.File remain open.
func (*Node) SoftStatus ¶
It is not required to consume or store SoftState.
func (*Node) Start ¶
func (n *Node) Start(opts ...StartOption) error
Start start the node and accepts incoming requests on the handler or on local node methods. It can be called after Stop to restart the node.
Start always returns a non-nil error. After Shutdown, the returned error is ErrNodeStopped.
func (*Node) Stepdown ¶
Stepdown proposes to transfer leadership to the longest active member in the cluster. This must be run on the leader or it will fail.
func (*Node) TransferLeadership ¶
TransferLeadership proposes to transfer leadership to the given member id.
func (*Node) UpdateMember ¶
UpdateMember proposes to update the given member, It considered complete after reaching a majority. After committing the update, each member in the cluster updates the given member configuration on its pool.
If the provided context expires before, the update is complete, UpdateMember returns the context's error, otherwise it returns any error returned due to the update.
Note: the member id and type are not updatable.
type NodeGroup ¶
type NodeGroup struct {
// contains filtered or unexported fields
}
NodeGroup manage multi Raft nodes from many different Raft groups known as Raft clusters. NodeGroup is more efficient than a collection of nodes.
Scales raft into multiple raft groups requires data sharding, each raft group responsible for managing data in the range [start, end]. as the system grows to include more ranges, so does the amount of traffic required to handle heartbeats. The number of ranges is much larger than the number of physical nodes so many ranges will have overlapping membership this is where NodeGroup comes in: instead of allowing each range to run Raft independently, we manage an entire node’s worth of ranges as a group. Each pair of physical nodes only needs to exchange heartbeats once per tick (coalesced heartbeats), no matter how many ranges they have in common.
Create, Remove can run while node group stopped. starting an created node is required a started node group, Otherwise, it will hang until the node group started.
func NewNodeGroup ¶
func NewNodeGroup(proto etransport.Proto) *NodeGroup
NewNodeGroup returns a new NodeGroup. the returned node group will lazily initialize, from the first node registered within it, So it's recommended to apply the same HeartbeatTick, ElectionTick, and TickInterval configuration to all sub-nodes.
func (*NodeGroup) Create ¶
func (ng *NodeGroup) Create(groupID uint64, fsm StateMachine, opts ...Option) *Node
Create construct and returns a new node that associated to the given group id,
The node and the group are correlated so each group id must have its own node object and each node object must have its own group id.
All registered nodes within the node group must have the same id, that is how multiple nodes object representing one single physical node that participate in multiple raft groups. Starting a node with a different id from the previous one will cause a panic. Make sure the program set the node id using option, if it's not first node.
func (*NodeGroup) Handler ¶
func (ng *NodeGroup) Handler() etransport.Handler
Handler return NodeGroup transportation handler, that delegated to respond to RPC requests over the wire. the returned handler must be registered with the transportation server.
func (*NodeGroup) Remove ¶
Remove remove node related to the given group id. after the removal, the actual node will become idle, it must coordinate with node shutdown explicitly.
nodeGroup.Remove(12) node.Shutdown(ctx)
type Option ¶
type Option interface {
// contains filtered or unexported methods
}
Option configures raft node using the functional options paradigm popularized by Rob Pike and Dave Cheney. If you're unfamiliar with this style, see https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html and https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis.
func WithCheckQuorum ¶
func WithCheckQuorum() Option
WithCheckQuorum specifies if the leader should check quorum activity. Leader steps down when quorum is not active for an electionTimeout.
Default Value: false.
func WithContext ¶
WithContext set raft node parent ctx, The provided ctx must be non-nil.
The context controls the entire lifetime of the raft node: obtaining a connection, sending the msgs, reading the response, and process msgs.
Default Value: context.Background().
func WithDisableProposalForwarding ¶
func WithDisableProposalForwarding() Option
WithDisableProposalForwarding set to true means that followers will drop proposals, rather than forwarding them to the leader. One use case for this feature would be in a situation where the Raft leader is used to compute the data of a proposal, for example, adding a timestamp from a hybrid logical clock to data in a monotonically increasing way. Forwarding should be disabled to prevent a follower with an inaccurate hybrid logical clock from assigning the timestamp and then forwarding the data to the leader.
Default Value: false.
func WithDrainTimeOut ¶
WithDrainTimeOut is the timeout on the streaming pending messages to other raft members. Drain can be very useful for graceful shutdown.
Default Value: 10's.
func WithElectionTick ¶
WithElectionTick is the number of node tick (WithTickInterval) invocations that must pass between elections. That is, if a follower does not receive any message from the leader of current term before ElectionTick has elapsed, it will become candidate and start an election. ElectionTick must be greater than HeartbeatTick. We suggest ElectionTick = 10 * HeartbeatTick to avoid unnecessary leader switching.
Default Value: 10.
func WithHeartbeatTick ¶
WithHeartbeatTick is the number of node tick (WithTickInterval) invocations that
must pass between heartbeats. That is, a leader sends heartbeat messages to
maintain its leadership every HeartbeatTick ticks.
Default Value: 1.
func WithLinearizableReadLeaseBased ¶
func WithLinearizableReadLeaseBased() Option
WithLinearizableReadLeaseBased ensures linearizability of the read only request by relying on the leader lease. It can be affected by clock drift. If the clock drift is unbounded, leader might keep the lease longer than it should (clock can move backward/pause without any bound). ReadIndex is not safe in that case.
func WithLinearizableReadSafe ¶
func WithLinearizableReadSafe() Option
WithLinearizableReadSafe guarantees the linearizability of the read request by communicating with the quorum. It is the default and suggested option.
func WithLogger ¶
WithLogger sets logger that is used to generates lines of output.
Default Value: raftlog.DefaultLogger.
func WithMaxCommittedSizePerReady ¶
WithMaxCommittedSizePerReady limits the size of the committed entries which can be applied.
Default Value: 0.
func WithMaxInflightMsgs ¶
WithMaxInflightMsgs limits the max number of in-flight append messages during optimistic replication phase. The application transportation layer usually has its own sending buffer over TCP/UDP. Setting MaxInflightMsgs to avoid overflowing that sending buffer.
Default Value: 256.
func WithMaxSizePerMsg ¶
WithMaxSizePerMsg limits the max byte size of each append message. Smaller value lowers the raft recovery cost(initial probing and message lost during normal operation). On the other side, it might affect the throughput during normal replication. Note: math.MaxUint64 for unlimited, 0 for at most one entry per message.
Default Value: 1024 * 1024.
func WithMaxSnapshotFiles ¶
WithMaxSnapshotFiles is the number of snapshots to keep beyond the current snapshot.
Default Value: 5.
func WithMaxUncommittedEntriesSize ¶
WithMaxUncommittedEntriesSize limits the aggregate byte size of the uncommitted entries that may be appended to a leader's log. Once this limit is exceeded, proposals will begin to return ErrProposalDropped errors. Note: 0 for no limit.
Default Value: 1 << 30.
func WithPipelining ¶
func WithPipelining() Option
WithPipelining is the process to send successive requests, over the same persistent connection, without waiting for the answer. This avoids latency of the connection. Theoretically, performance could also be improved if two or more requests were to be packed into the same connection.
Note: pipelining spawn 4 goroutines per remote member connection.
func WithPreVote ¶
func WithPreVote() Option
WithPreVote enables the Pre-Vote algorithm described in raft thesis section 9.6. This prevents disruption when a node that has been partitioned away rejoins the cluster.
Default Value: false.
func WithSnapshotInterval ¶
WithSnapshotInterval is the number of log entries between snapshots.
Default Value: 1000.
func WithStateDIR ¶
WithStateDIR is the directory to store durable state (WAL logs and Snapshots).
Default Value: os.TempDir().
func WithStreamTimeOut ¶
WithStreamTimeOut is the timeout on the streaming messages to other raft members.
Default Value: 10's.
func WithTickInterval ¶
WithTickInterval is the time interval to, increments the internal logical clock for, the current raft member by a single tick.
Default Value: 100'ms.
type StartOption ¶
type StartOption interface {
// contains filtered or unexported methods
}
StartOption configures how we start the raft node using the functional options paradigm , popularized by Rob Pike and Dave Cheney. If you're unfamiliar with this style, see https://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html and https://dave.cheney.net/2014/10/17/functional-options-for-friendly-apis.
func WithFallback ¶
func WithFallback(opts ...StartOption) StartOption
WithFallback can be used if other options do not succeed.
WithFallback( WithJoin(), WithRestart, )
func WithForceJoin ¶
func WithForceJoin(addr string, timeout time.Duration) StartOption
WithForceJoin send rpc request to join an existing cluster even if already part of a cluster.
func WithForceNewCluster ¶
func WithForceNewCluster() StartOption
WithForceNewCluster initialize a new cluster from state dir. One use case for this feature would be in restoring cluster quorum.
Note: ForceNewCluster preserve the same node id.
func WithInitCluster ¶
func WithInitCluster() StartOption
WithInitCluster initialize a new cluster and create first raft node.
func WithJoin ¶
func WithJoin(addr string, timeout time.Duration) StartOption
WithJoin send rpc request to join an existing cluster.
func WithMembers ¶
func WithMembers(membs ...RawMember) StartOption
WithMembers add the given members to the raft node.
WithMembers safe to be used with initiate cluster kind options, ("WithForceNewCluster", "WithRestore", "WithInitCluster") Otherwise, it may conflicts with other options like WithJoin.
As long as only one url member, WithMembers will only set the current node, then it will be safe to be composed with other options even "WithJoin".
WithMembers and WithInitCluster must be applied to all cluster nodes when they are composed, Otherwise, the quorum will be lost and the cluster become unavailable.
Node A: n.Start(WithInitCluster(), WithMembers(<node A>, <node B>)) Node B: n.Start(WithInitCluster(), WithMembers(<node B>, <node A>))
Note: first member will be assigned to the current node.
func WithRestore ¶
func WithRestore(path string) StartOption
WithRestore initialize a new cluster from snapshot file. One use case for this feature would be in restoring cluster data.
type StateMachine ¶
type StateMachine = raftengine.StateMachine
StateMachine define an interface that must be implemented by application to make use of the raft replicated log.
Directories ¶
Path | Synopsis |
---|---|
_examples
|
|
internal
|
|
mocks/membership
Package membershipmock is a generated GoMock package.
|
Package membershipmock is a generated GoMock package. |
mocks/raftengine
Package raftenginemock is a generated GoMock package.
|
Package raftenginemock is a generated GoMock package. |
mocks/storage
Package storagemock is a generated GoMock package.
|
Package storagemock is a generated GoMock package. |
mocks/transport
Package transportmock is a generated GoMock package.
|
Package transportmock is a generated GoMock package. |
Package raftlog implements a simple logging package.
|
Package raftlog implements a simple logging package. |
Package rafttest provides functional tests for raft implementation.
|
Package rafttest provides functional tests for raft implementation. |
Package transport provides types for raft transport functions.
|
Package transport provides types for raft transport functions. |
raftgrpc
Package raftgrpc implements gRPC transportation layer for raft.
|
Package raftgrpc implements gRPC transportation layer for raft. |
rafthttp
Package rafthttp implements HTTP transportation layer for raft.
|
Package rafthttp implements HTTP transportation layer for raft. |