Documentation ¶
Overview ¶
Package paxos implements the paxos algorithm. The logic is mostly ported from mjpitz/paxos, but with a few modifications. First, I didn't continue using gRPC as the transport as I wanted something a bit less cumbersome. I've tried to break down the interface in such a way where different transports _could_ be plugged in. More on that later.
This package is (and likely will be for a while) a work in progress. As it stands, it _should_ support simple paxos.
Index ¶
- func RegisterYarpcAcceptorServer(svr *yarpc.ServeMux, impl AcceptorServer)
- func RegisterYarpcObserverServer(svr *yarpc.ServeMux, impl ObserverServer)
- func RegisterYarpcProposerServer(svr *yarpc.ServeMux, impl ProposerServer)
- type Acceptor
- type AcceptorClient
- type AcceptorServer
- type Badger
- type Bytes
- type Config
- type IDGenerator
- type Log
- type Memory
- type MockStream
- func (m *MockStream) Close() error
- func (m *MockStream) Context() context.Context
- func (m *MockStream) ReadMsg(i interface{}) error
- func (m *MockStream) SetReadDeadline(deadline time.Time) error
- func (m *MockStream) SetWriteDeadline(deadline time.Time) error
- func (m *MockStream) WriteMsg(i interface{}) error
- type MultiAcceptorClient
- type ObserveClientStream
- type ObserveServerStream
- type Observer
- type ObserverClient
- type ObserverServer
- type Paxos
- type Promise
- type Proposal
- type Proposer
- type ProposerClient
- type ProposerServer
- type Request
- type Stream
- type Vote
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func RegisterYarpcAcceptorServer ¶
func RegisterYarpcAcceptorServer(svr *yarpc.ServeMux, impl AcceptorServer)
RegisterYarpcAcceptorServer registers the provided AcceptorServer implementation with the yarpc.Server to handle requests.
func RegisterYarpcObserverServer ¶
func RegisterYarpcObserverServer(svr *yarpc.ServeMux, impl ObserverServer)
RegisterYarpcObserverServer registers the provided ObserverServer implementation with the yarpc.Server to handle requests. Acceptors should implement the observer server, otherwise other members of the cluster cannot determine what records have been accepted.
func RegisterYarpcProposerServer ¶
func RegisterYarpcProposerServer(svr *yarpc.ServeMux, impl ProposerServer)
RegisterYarpcProposerServer registers the provided ProposerServer implementation with the yarpc.Server to handle requests. Typically, proposers aren't embedded as a server and are instead run as client side code.
Types ¶
type AcceptorClient ¶
type AcceptorClient interface { Prepare(ctx context.Context, request *Request) (*Promise, error) Accept(ctx context.Context, proposal *Proposal) (*Proposal, error) }
func NewYarpcAcceptorClient ¶
func NewYarpcAcceptorClient(cc *yarpc.ClientConn) AcceptorClient
NewYarpcAcceptorClient wraps the provided yarpc.ClientConn with an AcceptorClient implementation.
type AcceptorServer ¶
type Badger ¶
type Badger struct { DB *badger.DB // contains filtered or unexported fields }
Badger implements a Log that wraps an underlying badgerdb instance.
func (*Badger) WithPrefix ¶
type Bytes ¶
type Bytes struct {
Value []byte `json:"value,omitempty"`
}
Bytes contains a value to be accepted via paxos.
type Config ¶
type Config struct { Clock clockwork.Clock IDGenerator IDGenerator PromiseLog Log AcceptedLog Log RecordedLog Log AcceptorDialer func(ctx context.Context, member string) (AcceptorClient, error) ObserverDialer func(ctx context.Context, member string) (ObserverClient, error) }
Config contains configurable elements of Paxos.
type IDGenerator ¶
IDGenerator defines an interface for generating IDs used internally by paxos.
func ServerIDGenerator ¶
func ServerIDGenerator(serverID uint8, clock clockwork.Clock) IDGenerator
ServerIDGenerator returns an IDGenerator that creates an ID using a provided serverID and clock. It works by by taking a millisecond level timestamp, shifting it's value left 8 bits, and or'ing it with the server ID. The leading byte can be used to expand this representation later on.
const ( wordView = 0x0000000000000000 nowMillis = 0x0000017c96370c09 shifted = 0x00017c96370c0900 withSID = 0x00017c96370c09XX )
As you can see, there is plenty of space for the IDGenerator to function. Obviously, there are limitations with this implementation.
- 256 max possible instances
- Throughput constrained to 1 op/ms
Granted, some of these aren't _huge_ issues for the types of systems that this _could_ help build.
type Memory ¶
type Memory struct {
// contains filtered or unexported fields
}
func (*Memory) WithPrefix ¶
type MockStream ¶
func NewMockStream ¶
func NewMockStream(size int) *MockStream
NewMockStream provides a mock Stream implementation useful for testing. This could be yarpc or paxos related.
func (*MockStream) Close ¶
func (m *MockStream) Close() error
func (*MockStream) Context ¶
func (m *MockStream) Context() context.Context
func (*MockStream) ReadMsg ¶
func (m *MockStream) ReadMsg(i interface{}) error
func (*MockStream) SetReadDeadline ¶
func (m *MockStream) SetReadDeadline(deadline time.Time) error
func (*MockStream) SetWriteDeadline ¶
func (m *MockStream) SetWriteDeadline(deadline time.Time) error
func (*MockStream) WriteMsg ¶
func (m *MockStream) WriteMsg(i interface{}) error
type MultiAcceptorClient ¶
type MultiAcceptorClient struct { Dialer func(ctx context.Context, member string) (AcceptorClient, error) // contains filtered or unexported fields }
func (*MultiAcceptorClient) Start ¶
func (m *MultiAcceptorClient) Start(ctx context.Context, membership *cluster.Membership) error
type ObserveClientStream ¶
type ObserveClientStream struct {
Stream
}
func (*ObserveClientStream) Recv ¶
func (s *ObserveClientStream) Recv() (*Proposal, error)
type ObserveServerStream ¶
type ObserveServerStream struct {
Stream
}
func (*ObserveServerStream) Recv ¶
func (s *ObserveServerStream) Recv() (*Request, error)
func (*ObserveServerStream) Send ¶
func (s *ObserveServerStream) Send(msg *Proposal) error
type Observer ¶
type Observer struct { Dialer func(ctx context.Context, member string) (ObserverClient, error) Log Log }
Observer watches the Acceptors to learn about what values have been accepted.
type ObserverClient ¶
type ObserverClient interface {
Observe(ctx context.Context, request *Request) (*ObserveClientStream, error)
}
func NewYarpcObserverClient ¶
func NewYarpcObserverClient(cc *yarpc.ClientConn) ObserverClient
NewYarpcObserverClient wraps the provided yarpc.ClientConn with an ObserverClient implementation.
type ObserverServer ¶
type ObserverServer interface {
Observe(call *ObserveServerStream) error
}
type Paxos ¶
type Paxos struct { // Proposer contains the logic required to propose changes to the paxos state machine. Any member in paxos can act // as a proposer. Proposers communicate with all acceptor to propose changes to the log. Proposer // Observer contains the logic required to be an observer of the paxos protocol. Every member in paxos _must_ be an // observer. Observers watch all acceptor to learn about the records they've accepted. Observer // Acceptor must implement the functionality of an AcceptorServer and an ObserverServer. The ObserverServer is how // other members of the cluster learn about changes. Acceptor }
Paxos defines the core elements of a paxos participant.
type Promise ¶
type Promise struct { ID uint64 `json:"id,omitempty"` Accepted *Proposal `json:"accepted,omitempty"` }
Promise is returned by an accepted prepare. If more than one attempt was made, and accepted value is returned with the last accepted proposal so clients can catch up.
type Proposer ¶
type Proposer struct { IDGenerator IDGenerator Acceptor AcceptorClient }
Proposer can be run either as an embedded client, or as part of a standalone server. Proposers Propose additions to the paxos log and uses the acceptors to get consensus on if the proposed value was accepted.
type ProposerClient ¶
func NewYarpcProposerClient ¶
func NewYarpcProposerClient(cc *yarpc.ClientConn) ProposerClient
NewYarpcProposerClient wraps the provided yarpc.ClientConn with an ProposerClient implementation.
type ProposerServer ¶
type Request ¶
Request is used during the PREPARE and OBSERVE phases of the paxos algorithm. Prepare sends along their ID value and attempt number, where Observe sends along their last accepted id.
type Stream ¶
type Stream interface { Context() context.Context SetReadDeadline(deadline time.Time) error ReadMsg(i interface{}) error SetWriteDeadline(deadline time.Time) error WriteMsg(i interface{}) error Close() error }
Stream provides an abstract definition of the functionality the underlying stream needs to provide.
type Vote ¶
type Vote struct { // Member contains which member of the cluster cast this vote. Member string // Payload contains the payload of the message we're voting on. This is usually a Promise or Proposal. Payload interface{} }
Vote is an internal structure used by multiple components to cast votes on behalf of the acceptor that they're communicating with.