public class FallbackKVDatabase extends Object implements KVDatabase
KVDatabase that automatically migrates between a clustered RaftKVDatabase
and a local, non-clustered "standalone mode" KVDatabase, based on availability of the Raft cluster.
A RaftKVDatabase requires that the local node be part of a cluster majority, otherwise, transactions
cannot commit (even read-only ones) and application progress halts. This class adds partition tolerance to
a RaftKVDatabase, by maintaining a separate private "standalone mode" KVDatabase that can be used
in lieu of the normal RaftKVDatabase when the Raft cluster is unavailable.
Instances transparently and automatically switch over to standalone mode KVDatabase when they determine
that the RaftKVDatabase is unavailable, and automatically switch back to using the RaftKVDatabase
once it is available again. The rate of switching is limited by an enforced hysteresis; see
FallbackTarget.getMinAvailableTime() and FallbackTarget.getMinUnavailableTime().
Of course, this sacrifices consistency. To address that, a configurable MergeStrategy is used to migrate the data
when switching between normal mode and standalone mode. The MergeStrategy is given read-only access to the
database being switched away from, and read-write access to the database being switched to; when switching away from
the RaftKVDatabase, Consistency.EVENTUAL_COMMITTED is used to eliminate the requirement for
communication with the rest of the cluster.
Although more exotic, instances support migrating between multiple RaftKVDatabases in a prioritized list.
For example, the local node may be part of two independent RaftKVDatabase clusters: a higher priority one
containing every node, and a lower priority one containing only nodes in the same data center as the local node.
In any case, the "standalone mode" database (which is not a clustered database) always has the lowest priority.
Raft cluster availability is determined by FallbackTarget.checkAvailability(); subclasses may override the default
implementation if desired.
| Constructor and Description |
|---|
FallbackKVDatabase() |
| Modifier and Type | Method and Description |
|---|---|
protected Thread |
createExecutorThread(Runnable action,
int uniqueId)
Create the service thread used by this instance.
|
FallbackKVTransaction |
createTransaction() |
FallbackKVTransaction |
createTransaction(Map<String,?> options) |
int |
getCurrentTargetIndex()
Get the index of the currently active database.
|
FallbackTarget |
getFallbackTarget()
Get most preferred
FallbackTarget. |
List<FallbackTarget> |
getFallbackTargets()
Get the
FallbackTarget(s). |
int |
getInitialTargetIndex()
Get the configured target index to use when starting up for the very first time.
|
Date |
getLastStandaloneActiveTime()
Get the last time the standalone database was active.
|
int |
getMaximumTargetIndex()
Get the maximum allowed target index.
|
KVDatabase |
getStandaloneTarget()
Get the configured "standalone mode"
KVDatabase to be used when all FallbackTargets are unavailable. |
File |
getStateFile()
Get this instance's persistent state file.
|
protected boolean |
isMigrationAllowed(int currTargetIndex,
int nextTargetIndex)
Subclass hook to veto an impending migration.
|
protected void |
migrationCompleted(int prevTargetIndex,
int currTargetIndex)
Subclass hook to be notified when a migration occurs.
|
void |
setFallbackTarget(FallbackTarget target)
Configure a single
FallbackTarget. |
void |
setFallbackTargets(List<? extends FallbackTarget> targets)
Configure multiple
FallbackTarget(s). |
void |
setInitialTargetIndex(int initialTargetIndex)
Configure the index of the currently active database when starting up for the very first time.
|
void |
setMaximumTargetIndex(int maximumTargetIndex)
Configure the maximum allowed target index.
|
void |
setStandaloneTarget(KVDatabase standaloneKV)
Configure the local "standalone mode"
KVDatabase to be used when all FallbackTargets are unavailable. |
void |
setStateFile(File stateFile)
Configure this instance's persistent state file.
|
void |
start() |
void |
stop() |
String |
toString() |
protected final Logger log
public File getStateFile()
public void setStateFile(File stateFile)
Required property.
stateFile - file for persistent stateIllegalArgumentException - if stateFile is nullIllegalStateException - if this instance is already startedpublic KVDatabase getStandaloneTarget()
KVDatabase to be used when all FallbackTargets are unavailable.public void setStandaloneTarget(KVDatabase standaloneKV)
KVDatabase to be used when all FallbackTargets are unavailable.standaloneKV - "standalone mode" databaseIllegalArgumentException - if standaloneKV is nullIllegalStateException - if this instance is already startedpublic FallbackTarget getFallbackTarget()
FallbackTarget.
Targets will be sorted in order of increasing preference.
public List<FallbackTarget> getFallbackTargets()
FallbackTarget(s).
Targets will be sorted in order of increasing preference.
public void setFallbackTarget(FallbackTarget target)
FallbackTarget.target - fallback targetIllegalArgumentException - if target is nullIllegalArgumentException - if any target does not have a RaftKVDatabase configuredIllegalStateException - if this instance is already startedpublic void setFallbackTargets(List<? extends FallbackTarget> targets)
FallbackTarget(s).
Targets should be sorted in order of increasing preference.
targets - targets in order of increasing preferenceIllegalArgumentException - if targets is nullIllegalArgumentException - if targets is emptyIllegalArgumentException - if any target is nullIllegalArgumentException - if any target does not have a RaftKVDatabase configuredIllegalStateException - if this instance is already startedpublic int getInitialTargetIndex()
public void setInitialTargetIndex(int initialTargetIndex)
Default value is the most highly preferred target. Use -1 to change the default to standalone mode; this is appropriate when the Raft cluster is not yet configured on initial startup.
initialTargetIndex - initial target index, -1 meaning standalone mode; out of range values will be clippedpublic int getCurrentTargetIndex()
public void setMaximumTargetIndex(int maximumTargetIndex)
Default value is Integer.MAX_VALUE.
maximumTargetIndex - maximum target index, -1 meaning standalone mode; out of range values will be clippedpublic int getMaximumTargetIndex()
public Date getLastStandaloneActiveTime()
public void start()
start in interface KVDatabasepublic void stop()
stop in interface KVDatabaseprotected Thread createExecutorThread(Runnable action, int uniqueId)
The implementation in FallbackKVDatabase simply instantiates a thread and sets the name.
Subclasses may override to set priority, etc.
action - thread entry pointuniqueId - unique ID for the thread which increments each time this instance is (re)startedpublic FallbackKVTransaction createTransaction()
createTransaction in interface KVDatabasepublic FallbackKVTransaction createTransaction(Map<String,?> options)
createTransaction in interface KVDatabaseprotected boolean isMigrationAllowed(int currTargetIndex,
int nextTargetIndex)
The implementation in FallbackKVDatabase always returns true.
currTargetIndex - current fallback target list index (before migration), or -1 for standalone modenextTargetIndex - next fallback target list index (after migration), or -1 for standalone modeprotected void migrationCompleted(int prevTargetIndex,
int currTargetIndex)
The implementation in FallbackKVDatabase does nothing.
prevTargetIndex - previous fallback target list index, or -1 for standalone modecurrTargetIndex - current fallback target list index, or -1 for standalone modeCopyright © 2016. All rights reserved.