public interface Quorum<S extends Remote,C extends QuorumClient<S>>
Quorum
interface provides a view of the quorum from the
perspective of one of those member services. A quorum has a replication
factor k. A member service may "join" with a quorum when it shares
an agreement with at least (k+1)/2 other quorum members concerning its state.
When there are at least (k+1)/2 member services joined with the quorum, the
quorum is "meets" and elects a leader. Each time a new leader is elected, it
assigns a unique token to the quorum. Client reads and writes will block
unless the quorum is met. If a quorum breaks, then any outstanding writes
will be discarded and the client must wait until the quorum meets again
before reading or writing on the quorum.
The first service in the chain is the quorum leader. Client writes are directed to the leader (also known as the master) and replicated to the member services joined with the quorum. Clients may read from any service in the quorum, but only for historical commit points. The current uncommitted state is only available from the quorum leader as the followers are only guaranteed to be consistent as of each commit point.
The services in the quorum are organized into a write pipeline for the purposes of replication. The leader is always the first service in the write pipeline. Services which are not yet joined with the quorum are allowed into the write pipeline while they are synchronizing with the leader. When a service is synchronized, it can then join the quorum.
This interface reflects state changes in the quorum for some logical service.
Logical services and their physical instances are managed outside of the
Quorum
interface. When a physical service is starts or stops, it uses
a Quorum
for the corresponding logical service to observe and manage
state changes in the emergent quorum of physical services for the same
logical service.
Modifier and Type | Field and Description |
---|---|
static long |
NO_QUORUM
The constant used to indicate that there is no quorum (@value
-1L).
|
Modifier and Type | Method and Description |
---|---|
void |
addListener(QuorumListener listener)
Add a listener
|
void |
assertLeader(long token)
Assert that the token is still valid and that the
getClient() is
the quorum leader. |
void |
assertQuorum(long token)
Assert that the quorum associated with the token is still valid.
|
void |
awaitBreak()
Await a met break (blocking).
|
void |
awaitBreak(long timeout,
TimeUnit units)
Await a met break (blocking).
|
long |
awaitQuorum()
Await a met quorum (blocking).
|
long |
awaitQuorum(long timeout,
TimeUnit units)
Await a met quorum (blocking).
|
QuorumActor<S,C> |
getActor()
The object used to effect changes in distributed quorum state on the
behalf of the
QuorumMember . |
Long |
getCastVote(UUID serviceId)
Return the vote cast by the service.
|
Long |
getCastVoteIfConsensus(UUID serviceId)
Search for the vote for the service.
|
C |
getClient()
Return the
QuorumClient iff the quorum is running. |
UUID[] |
getJoined()
Return the identifiers for the member services joined with this quorum.
|
UUID |
getLastInPipeline()
Return the
UUID of the service which is the last service in the
write pipeline. |
UUID |
getLeaderId()
|
QuorumMember<S> |
getMember()
Return the
QuorumMember iff the quorum is running. |
UUID[] |
getMembers()
Return the identifiers for the member services (all known physical
services for the logical service).
|
UUID[] |
getPipeline()
Return the service identifiers for the services in the write pipeline in
the order in which they will accept and relay writes.
|
UUID[] |
getPipelinePriorAndNext(UUID serviceId)
Return the
UUID of the service in the pipeline which is
immediately upstream from (prior to) and downstream from (next to) the
specified service. |
Map<Long,UUID[]> |
getVotes()
Return an immutable snapshot of the votes cast by the quorum members.
|
boolean |
isHighlyAvailable()
Return
true if replicationFactor() is GT ONE (1). |
boolean |
isQuorum(int njoined)
Return
true iff the argument is large enough to constitute a
quorum. |
boolean |
isQuorumFullyMet(long token)
Return true iff the #of services joined with the quorum EQUALS
k AND the provided quorum token is valid. |
boolean |
isQuorumMet()
Return true iff the #of services joined with the quorum is GTE
(k + 1)/2 . |
long |
lastValidToken()
The quorum token which was assigned the last time a leader was elected.
|
void |
removeListener(QuorumListener listener)
Remove a listener (the quorum's client is always a listener).
|
int |
replicationFactor()
Return k, the target replication factor.
|
void |
start(C client)
Start any asynchronous processing associated with maintaining the
Quorum state. |
void |
terminate()
Terminate any asynchronous processing associated with maintaining the
Quorum state. |
long |
token()
The current token for the quorum.
|
static final long NO_QUORUM
Note: The quorum token is formed by adding one to the
lastValidToken()
. The initial value of the
lastValidToken()
is -1L. Therefore, the the
first valid quorum token is ZERO (0).
int replicationFactor()
A normal quorum requires a simple majority and a replication factor that
is a non-negative odd integer (1, 3, 5, 7, etc). For this case, a quorum
exists only when (k + 1)/2
physical services for the same
logical service have an agreement on state. A single service with
k := 1
is the degenerate case and has a minimum quorum size
of ONE (1). High availability is only possible when k
is GT
ONE (1). Thus k := 3
is the minimum value for which services
can be highly available and has a minimum quorum size of 2
.
isQuorum(int)
boolean isQuorum(int njoined)
true
iff the argument is large enough to constitute a
quorum.
Note: This method makes it easier to write code that obeys policies other than simple majority rule. For example, a quorum could exist only when ALL services are joined. This alternative rule is useful when the services do not support a resynchronization policy. For such services, all services must participate in all commits since services can not recover if they miss a commit. Simple replication is an example of this policy.
njoined
- The argument.true
if that a quorum is met for that many joined
services.long token()
NO_QUORUM
. When a leader is elected, it sets the current
token as token := lastValidToken() + 1
. The current token is
cleared to NO_QUORUM
if the leader leaves the met quorum. It is
cleared NO_QUORUM
if the quorum breaks. While a leader may be
elected many times for the same lastCommitTime, a new quorum
token is assigned each time a leader is elected.long lastValidToken()
boolean isHighlyAvailable()
true
if replicationFactor()
is GT ONE (1).
High availability exists (in principle) when the
replicationFactor()
k is greater than one. High
availability exists (in practice) when the Quorum
is met
for a Quorum
that is
configured for high availability.true
if this Quorum
is highly available
in principleboolean isQuorumMet()
(k + 1)/2
. A service with a met quorum is highly available
in practice.boolean isQuorumFullyMet(long token)
k
AND the provided quorum token is valid. A service with a
fully met quorum may be eligible to release storage associated with
historical allocations since it does not need to maintain history in
support of resynchronization of disconnected quorum services.token
- The quorum token.QuorumException
- if the token is no longer valid.void addListener(QuorumListener listener)
listener
- The listener.IllegalArgumentException
- if the listener is null.IllegalArgumentException
- if the listener is the quorum's client (the quorum's client
is always a listener).void removeListener(QuorumListener listener)
listener
- The listener.IllegalArgumentException
- if the listener is null.IllegalArgumentException
- if the listener is the quorum's client (the quorum's client
is always a listener).UUID[] getMembers()
UUID
s of the member services.Map<Long,UUID[]> getVotes()
Long getCastVote(UUID serviceId)
serviceId
- The service.null
if the
service has not cast a vote.IllegalArgumentException
- if the serviceId is null
.Long getCastVoteIfConsensus(UUID serviceId)
serviceId
- The service identifier.null
if the service is not participating in a
consensus.UUID[] getJoined()
UUID
s of the member services joined with this quorum.UUID[] getPipeline()
UUID
s of the ordered services in the write pipeline.UUID getLastInPipeline()
UUID
of the service which is the last service in the
write pipeline.UUID
of the last service in the write pipeline or
null
if there are no services in the write pipeline.UUID[] getPipelinePriorAndNext(UUID serviceId)
UUID
of the service in the pipeline which is
immediately upstream from (prior to) and downstream from (next to) the
specified service. These are, respectively, the service from which it
receives data (upstream) and to which it sends data (downstream).serviceId
- The service id.null
if the serviceId does not appear
in the write pipeline -or- an array of two elements whose values
are: [0] The upstream serviceId in the write pipeline, which will
be null
iff serviceId is the first service in
the write pipeline; and [1] The downstream service in the write
pipeline, which will be null
iff serviceId is
the last service in the write pipeline.long awaitQuorum() throws InterruptedException, AsynchronousQuorumCloseException
Quorum
is not met, then this
will block until the Quorum
meets.AsynchronousQuorumCloseException
- if terminate()
is invoked while awaiting a quorum
meet.InterruptedException
long awaitQuorum(long timeout, TimeUnit units) throws InterruptedException, AsynchronousQuorumCloseException, TimeoutException
Quorum
is not met, then this
will block until the Quorum
meets.timeout
- The timeout.units
- The timeout units.AsynchronousQuorumCloseException
- if terminate()
is invoked while awaiting a quorum
meet.TimeoutException
- if the timeout expired before the quorum met.InterruptedException
void awaitBreak() throws InterruptedException, AsynchronousQuorumCloseException
AsynchronousQuorumCloseException
- if terminate()
is invoked while awaiting a quorum
break.InterruptedException
void awaitBreak(long timeout, TimeUnit units) throws InterruptedException, AsynchronousQuorumCloseException, TimeoutException
timeout
- The timeout.units
- The timeout units.AsynchronousQuorumCloseException
- if terminate()
is invoked while awaiting a quorum
break.TimeoutException
- if the timeout expired before the quorum breaks.InterruptedException
void assertQuorum(long token)
token()
somewhere.
This method may then be invoked to verify that the saved token is still
valid and, hence, that the quorum is still met.token
- The token for the quorum.QuorumException
- if the quorum is not met.QuorumException
- if the quorum is not met on a the caller's token.QuorumException
- if the token is NO_QUORUM
.void assertLeader(long token)
getClient()
is
the quorum leader.token
- A quorum token.QuorumException
- if the quorum is invalid.QuorumException
- if the token is NO_QUORUM
.QuorumException
- if our client is not the quorum leader.UUID getLeaderId()
void start(C client)
Quorum
state.void terminate()
Quorum
state.C getClient()
QuorumClient
iff the quorum is running.QuorumClient
.IllegalStateException
- if the quorum is not running.QuorumMember<S> getMember()
QuorumMember
iff the quorum is running.QuorumMember
.IllegalStateException
- if the quorum is not running.UnsupportedOperationException
- if the client does not implement QuorumMember
.QuorumActor<S,C> getActor()
QuorumMember
.QuorumActor
which will effect changes in the
distributed state of the quorum.IllegalStateException
- if the quorum is not running.IllegalStateException
- if the client is not a QuorumMember
.Copyright © 2006–2019 SYSTAP, LLC DBA Blazegraph. All rights reserved.