All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.permazen.kv.raft.Consistency Maven / Gradle / Ivy


/*
 * Copyright (C) 2015 Archie L. Cobbs. All rights reserved.
 */

package io.permazen.kv.raft;

/**
 * {@link RaftKVTransaction} supported consistency levels.
 *
 * 

* Read-write transactions (i.e., transactions containing any mutations or cluster configuration changes) are always * {@link #LINEARIZABLE}. Read-only transactions may also have one of the weaker consistency levels. Specifying a * weaker consistency levels implicitly sets the transaction to be read-only. The default is {@link #LINEARIZABLE}. * *

* A transaction's {@link Consistency} is configured when created. To configure a non-{@link #LINEARIZABLE} consistency, * supply the desired {@link Consistency} under the {@link RaftKVDatabase#OPTION_CONSISTENCY} key in the options provided * to {@link RaftKVDatabase#createTransaction(java.util.Map)}. * *

* Raft {@linkplain RaftKVTransaction#watchKey key watches} are compatible with all {@link Consistency} levels, * in that if a key watch fires due to a mutation to some key, then a subsequent transaction will see that mutation, * no matter what {@link Consistency} level is configured for that transaction. * * @see RaftKVTransaction#getConsistency RaftKVTransaction.getConsistency() * @see Strong consistency models */ public enum Consistency { /** * Uncommitted eventual consistency. * *

* This level is only for read-only transactions; read-write transactions are always {@link #LINEARIZABLE}. * *

* Transactions see a consistent view of the database that is either already committed or likely to be committed soon. * This is the same as {@link #EVENTUAL_COMMITTED}, but with the additional (unlikely) possibility that the view that the * transaction sees may never actually get committed; this can only happen if there is a Raft leadership change * during the transaction. * *

* Transactions at this level require no network communication, commit immediately, and never result in * {@link io.permazen.kv.RetryTransactionException}s. Committing a transaction at this level is actually * equivalent to invoking {@link RaftKVTransaction#rollback rollback()} instead of {@link RaftKVTransaction#commit commit()}. * *

* In Raft terms, transactions are based on the latest uncommitted log entry, the commit operation does not wait * for that log entry to be committed, and up-to-date reads are not guaranteed. */ UNCOMMITTED(false, false, false, true), /** * Committed eventual consistency. * *

* This level is only for read-only transactions; read-write transactions are always {@link #LINEARIZABLE}. * *

* Transactions see a consistent, committed view of the database as it existed at some point in the "recent past". * The view is not guaranteed to be up-to-date; it's only guaranteed to be as up-to-date as what was known to this * node when the transaction was opened. In general (for example, if stuck in a network partition minority), the view * could be from arbitrarily far in the past. * *

* Unlike {@link #EVENTUAL}, transactions at this level require no network communication, commit immediately, and never * result in {@link io.permazen.kv.RetryTransactionException}s; however, they see a potentially older view. Compared * to {@link #UNCOMMITTED}, transactions at this level see a view that is potentially older, in exchange for the guarantee * that it has definitely been committed. * *

* This consistency level is useful when it's important to allow reading the database in any situation, e.g., even when * the local node is in a minority partition of the cluster. Of course, the data will only be as up-to-date as is known * locally. * *

* In Raft terms, transactions are based on the latest committed log entry, and up-to-date reads are not guaranteed. */ EVENTUAL_COMMITTED(true, false, false, true), /** * Eventual consistency. * *

* This level is only for read-only transactions; read-write transactions are always {@link #LINEARIZABLE}. * *

* Transactions see a consistent, committed view of the database as it existed at some point in the "recent past". * The view is not guaranteed to be up-to-date; it's only guaranteed to be as up-to-date as what was known to this * node when the transaction was opened. In general (for example, if stuck in a network partition minority), the view * could be from arbitrarily far in the past. * *

* No network traffic is generated by {@link RaftKVTransaction#commit commit()}, and transactions can never throw * {@link io.permazen.kv.RetryTransactionException}s due to read/write conflicts, however they can throw * {@link io.permazen.kv.RetryTransactionException}s in other situations, e.g., if a leader changes occurs and the * base log entry is never committed. * *

* A {@link RaftKVTransaction#commit commit()} blocks until the log entry on which the transaction is based is committed; * if no concurrent write transactions are occurring, this will happen immediately. * *

* In Raft terms, transactions are based on the latest uncommitted log entry, the commit operation waits * for that log entry to be committed, and up-to-date reads are not guaranteed. */ EVENTUAL(false, true, false, true), /** * Linearizable consistency. * *

* Transactions see a database that evolves step-wise through a global, linear sequence of atomic changes, where * each change appears to have occurred instantaneously at some point in time between the start and end of the * corresponding transaction. * *

* This is the default consistency level. * *

* In Raft terms, transactions are based on the latest uncommitted log entry, the commit operation waits * for that log entry to be committed, and up-to-date reads are guaranteed. */ LINEARIZABLE(false, true, true, false); private final boolean basedOnCommittedLogEntry; private final boolean waitsForLogEntryToBeCommitted; private final boolean guaranteesUpToDateReads; private final boolean readOnly; Consistency(boolean basedOnCommittedLogEntry, boolean waitsForLogEntryToBeCommitted, boolean guaranteesUpToDateReads, boolean readOnly) { this.basedOnCommittedLogEntry = basedOnCommittedLogEntry; this.waitsForLogEntryToBeCommitted = waitsForLogEntryToBeCommitted; this.guaranteesUpToDateReads = guaranteesUpToDateReads; this.readOnly = readOnly; } /** * Determines the log entry on which transactions at this level are based. * *

* When false, transactions are based on this node's most recent log entry, whether committed or not. * When true, transactions are based on this node's most recent committed log entry. The former provides * a more up-to-date view, but {@link RaftKVTransaction#commit commit()} can block (and could possibly * fail with a {@link io.permazen.kv.RetryTransactionException}) when {@link #isWaitsForLogEntryToBeCommitted} is true. * The latter, when combined with {@link #isGuaranteesUpToDateReads} being false, allows read-only transactions * to commit immediately with no network traffic, even when in a minority partition. * * @return true if transactions at this level are always based on committed log entries */ public boolean isBasedOnCommittedLogEntry() { return this.basedOnCommittedLogEntry; } /** * Determines whether transactions at this level block in {@link RaftKVTransaction#commit commit()} until * the log entry on which they are based is committed. * *

* This setting has no effect if {@link #isBasedOnCommittedLogEntry} returns true (i.e., {@link #EVENTUAL_COMMITTED}), * because in that case the log entry on which the transaction is based is already committed when transaction starts. * * @return true if transactions at this level wait for their base log entry to be committed */ public boolean isWaitsForLogEntryToBeCommitted() { return this.waitsForLogEntryToBeCommitted; } /** * Determines whether transactions at this level guarantee reading the most up-to-date information. * *

* This setting has no effect on transactions that contain mutations; they always read the most up-to-date information. * *

* If this returns false, read-only transactions may read out-of-date information ("eventual consistency"). * * @return true if transactions at this level guarantee up-to-date reads */ public boolean isGuaranteesUpToDateReads() { return this.guaranteesUpToDateReads; } /** * Determines whether transactions at this level are always read-only. * *

* This is true for all levels except {@link #LINEARIZABLE}. * * @return true if transactions at this level are always read-only */ public boolean isReadOnly() { return this.readOnly; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy