Interface KeyValueTable<KeyT,ValueT>
-
- Type Parameters:
KeyT
- Table Key Type.ValueT
- Table Value Type.
- All Superinterfaces:
java.lang.AutoCloseable
@Beta public interface KeyValueTable<KeyT,ValueT> extends java.lang.AutoCloseable
Defines all operations that are supported on a Key-Value Table.A Key-Value Table is a distributed Key-Value Store that indexes Entries by Keys. It uses Table Segments (non-distributed Key-Value Store backed by a single Pravega Segment) as the fundamental storage primitive and provides a unified view of all Table Segments involved. Each
TableKey
is hashed to a Table Partition which may be represented by one or more Table Segments (depending on the Key-Value Table configuration chosen when it was created). Such partitioning enables the Key-Value Table to be distributed across the Pravega cluster but also introduces some constraints for certain operations (such as multi-key/entry atomic updates). See below for details.Key Families are used to group related Keys together in the same Table Partition, which allows multiple keys/entries belonging to the same Key Family to be updated/removed atomically.
- Multiple Keys/Entries in the same Key Family can be updated or removed atomically (either all changes will be applied or none will).
- Iterating through all Keys/Entries in the same Key Family is possible.
- The same Key may exist in multiple Key Families or even not be associated with any Key Family at all. Such keys are treated as distinct keys and will not interfere with each other (i.e., if key K1 exists in Key Families F1 and F2, then F1.K1 is different from F2.K1 and both are different from K1 (no Key Family association).
- Keys that do not belong to any Key Family will be uniformly distributed across the Key-Value Table Partitions and cannot be used for multi-key/entry atomic updates or removals or be iterated on.
- Keys belonging to the same Key Family are grouped into the same Table Segment; as such, the choice of Key Families can have performance implications. An ideally balanced Key-Value Table is one where no Key is part of any Key Family or the number of Keys in each Key Family is approximately the same. To enable a uniform distribution of Keys over the Key-Value Table, it is highly recommended not to use Key Families at all. If this situation cannot be avoided (i.e., multi-entry atomic updates or iterators are required), then it is recommended that Key Families themselves be diversified and Keys be equally distributed across them. Such approaches will ensure that the Key-Value Table load will be spread across all its Table Segments. An undesirable situation is an extreme case where all the Keys in the Key-Value Table are associated with a single Key Family; in this case the entire Key-Value Table load will be placed on a single backing Table Segment instead of spreading it across many Table Segments, leading to eventual performance degradation.
Types of Updates:
- Unconditional Updates will insert and/or overwrite any existing values for the given Key, regardless of whether
that Key previously existed or not, and regardless of what that Key's version is. Such updates can be performed using
put(String, Object, Object)
orputAll(String, Iterable)
. - Conditional Updates will only overwrite an existing value if the specified
Version
matches the one that is currently present on the server. Conditional inserts can be performed usingputIfAbsent(String, Object, Object)
and will only succeed if the given Key does not already exist in the given Key Family. Conditional updates can be performed usingreplace(String, Object, Object, Version)
. - Unconditional Removals will remove a Key regardless of what that Key's version is. The operation will also
succeed (albeit with no effect) if the Key does not exist. Such removals can be performed using
remove(String, Object)
. - Conditional Removals will remove a Key only if the specified
Version
matches the one that is currently present on the server. Such removals can be performed usingremove(String, Object, Version)
. - Multi-key updates allow mixing different types of updates in the same update batch. Some entries may be conditioned
on their Keys not existing at all (
TableEntry.getKey()
TableKey.getVersion()
equalsVersion.NOT_EXISTS
), some may be conditioned on specific versions and some may not have condition attached at all (TableEntry.getKey()
TableKey.getVersion()
equalsVersion.NO_VERSION
). All the conditions that are present in the update batch must be satisfied in order for the update batch to be accepted - the condition checks and updates are performed atomically. UsereplaceAll(String, Iterable)
for such an update. - Multi-key removals allow mixing different types of removals in the same removal batch. Some removals may be
conditioned on their affected Keys having a specific version and some may not have a condition attached at all
(
TableKey.getVersion()
equalsVersion.NO_VERSION
). Although unusual, it is possible to have a removal conditioned on a Key not existing (TableKey.getVersion()
equalsVersion.NOT_EXISTS
); such an update will have no effect on that Key if it doesn't exist but it will prevent the rest of the removals from the same batch from being applied - this can be used in scenarios where a set of Keys must be removed only if a particular Key is not present. All the conditions that are present in the removal batch must be satisfied in order for the removal batch to be accepted - the condition checks and updates are performed atomically. UseremoveAll(String, Iterable)
for such a removal.
Conditional Update Responses:
- Success: the update or removal has been atomically validated and performed; all updates or removals in the request have been accepted.
- Failure: the update or removal has been rejected due to version mismatch; no update or removal has been performed.
-
NoSuchKeyException
: the update or removal has been conditioned on a specific version (different fromVersion.NOT_EXISTS
orVersion.NO_VERSION
) but the Key does not exist in theKeyValueTable
. -
BadKeyVersionException
: the update or removal has been conditioned on a specific version (different fromVersion.NO_VERSION
but the Key exists in theKeyValueTable
with a different version.
-
-
Field Summary
Fields Modifier and Type Field Description static int
MAXIMUM_SERIALIZED_KEY_LENGTH
The maximum serialization length of a Table Segment Key.static int
MAXIMUM_SERIALIZED_VALUE_LENGTH
The maximum serialized length of a Table Segment Value.
-
Method Summary
All Methods Instance Methods Abstract Methods Modifier and Type Method Description void
close()
Closes theKeyValueTable
.io.pravega.common.util.AsyncIterator<IteratorItem<TableEntry<KeyT,ValueT>>>
entryIterator(@NonNull java.lang.String keyFamily, int maxEntriesAtOnce, IteratorState state)
Creates a new Iterator over all theTableEntry
instances in thisKeyValueTable
that belong to a specific Key Family.java.util.concurrent.CompletableFuture<TableEntry<KeyT,ValueT>>
get(java.lang.String keyFamily, KeyT key)
Gets the latest value for the a Key that belong to a specific Key Family.java.util.concurrent.CompletableFuture<java.util.List<TableEntry<KeyT,ValueT>>>
getAll(java.lang.String keyFamily, @NonNull java.lang.Iterable<KeyT> keys)
Gets the latest values for a set of Keys that do belong to the same Key Family.KeyValueTableMap<KeyT,ValueT>
getMapFor(java.lang.String keyFamily)
Exposes thisKeyValueTable
instance as aMap
.io.pravega.common.util.AsyncIterator<IteratorItem<TableKey<KeyT>>>
keyIterator(@NonNull java.lang.String keyFamily, int maxKeysAtOnce, IteratorState state)
Creates a new Iterator over all theTableKey
s in thisKeyValueTable
that belong to a specific Key Family.java.util.concurrent.CompletableFuture<Version>
put(java.lang.String keyFamily, KeyT key, ValueT value)
Unconditionally inserts a new or updates an existing Entry in theKeyValueTable
.java.util.concurrent.CompletableFuture<java.util.List<Version>>
putAll(@NonNull java.lang.String keyFamily, @NonNull java.lang.Iterable<java.util.Map.Entry<KeyT,ValueT>> entries)
Unconditionally inserts new or updates existingTableEntry
instances that belong to the same Key Family into thisKeyValueTable
.java.util.concurrent.CompletableFuture<Version>
putIfAbsent(java.lang.String keyFamily, KeyT key, ValueT value)
Conditionally inserts a new Entry in theKeyValueTable
if the given Key is not already present.java.util.concurrent.CompletableFuture<java.lang.Void>
remove(java.lang.String keyFamily, KeyT key)
Unconditionally removes a Key from this Table Segment.java.util.concurrent.CompletableFuture<java.lang.Void>
remove(java.lang.String keyFamily, KeyT key, @NonNull Version version)
Conditionally Removes a Key from this Table Segment.java.util.concurrent.CompletableFuture<java.lang.Void>
removeAll(java.lang.String keyFamily, @NonNull java.lang.Iterable<TableKey<KeyT>> keys)
Removes one or moreTableKey
instances that belong to the same Key Family from this Table Segment.java.util.concurrent.CompletableFuture<Version>
replace(java.lang.String keyFamily, KeyT key, ValueT value, @NonNull Version version)
Conditionally updates an existing Entry in theKeyValueTable
if the given Key exists and its version matches the givenVersion
.java.util.concurrent.CompletableFuture<java.util.List<Version>>
replaceAll(@NonNull java.lang.String keyFamily, @NonNull java.lang.Iterable<TableEntry<KeyT,ValueT>> entries)
Inserts new or updates existingTableEntry
instances that belong to the same Key Family into thisKeyValueTable
.
-
-
-
Field Detail
-
MAXIMUM_SERIALIZED_KEY_LENGTH
static final int MAXIMUM_SERIALIZED_KEY_LENGTH
The maximum serialization length of a Table Segment Key.- See Also:
- Constant Field Values
-
MAXIMUM_SERIALIZED_VALUE_LENGTH
static final int MAXIMUM_SERIALIZED_VALUE_LENGTH
The maximum serialized length of a Table Segment Value.- See Also:
- Constant Field Values
-
-
Method Detail
-
put
java.util.concurrent.CompletableFuture<Version> put(@Nullable java.lang.String keyFamily, @NonNull KeyT key, @NonNull ValueT value)
Unconditionally inserts a new or updates an existing Entry in theKeyValueTable
.- Parameters:
keyFamily
- (Optional) The Key Family for the Entry. If null, this Entry will not be associated with any Key Family.key
- The Key to insert or update.value
- The Value to be associated with the Key.- Returns:
- A CompletableFuture that, when completed, will contain the
Version
associated with the newly inserted or updated entry.
-
putIfAbsent
java.util.concurrent.CompletableFuture<Version> putIfAbsent(@Nullable java.lang.String keyFamily, @NonNull KeyT key, @NonNull ValueT value)
Conditionally inserts a new Entry in theKeyValueTable
if the given Key is not already present.- Parameters:
keyFamily
- (Optional) The Key Family for the Entry. If null, this Entry will not be associated with any Key Family.key
- The Key to insert.value
- The Value to be associated with the Key.- Returns:
- A CompletableFuture that, when completed, will contain the
Version
associated with the newly inserted or updated entry. Notable exceptions:ConditionalTableUpdateException
If the Key is already present in theKeyValueTable
for the provided Key Family. See theKeyValueTable
doc for more details on Conditional Update Responses.
-
putAll
java.util.concurrent.CompletableFuture<java.util.List<Version>> putAll(@NonNull @NonNull java.lang.String keyFamily, @NonNull @NonNull java.lang.Iterable<java.util.Map.Entry<KeyT,ValueT>> entries)
Unconditionally inserts new or updates existingTableEntry
instances that belong to the same Key Family into thisKeyValueTable
. All changes are performed atomically (either all or none will be accepted).- Parameters:
keyFamily
- The Key Family for the all provided Table Entries.entries
- AnIterable
ofMap.Entry
instances to insert or update.- Returns:
- A CompletableFuture that, when completed, will contain a List of
Version
instances which represent the versions for the inserted/updated keys. The size of this list will be the same as the number of items in entries and the versions will be in the same order as the entries.
-
replace
java.util.concurrent.CompletableFuture<Version> replace(@Nullable java.lang.String keyFamily, @NonNull KeyT key, @NonNull ValueT value, @NonNull @NonNull Version version)
Conditionally updates an existing Entry in theKeyValueTable
if the given Key exists and its version matches the givenVersion
.- Parameters:
keyFamily
- (Optional) The Key Family for the Entry. If null, this Entry will not be associated with any Key Family.key
- The Key to update.value
- The new Value to be associated with the Key.version
- AVersion
representing the version that this Key must have in order to replace it.- Returns:
- A CompletableFuture that, when completed, will contain the
Version
associated with the updated entry. Notable exceptions:ConditionalTableUpdateException
If the Key is not present present in theKeyValueTable
for the provided Key Family or it is and has a differentVersion
. See theKeyValueTable
doc for more details on Conditional Update Responses.
-
replaceAll
java.util.concurrent.CompletableFuture<java.util.List<Version>> replaceAll(@NonNull @NonNull java.lang.String keyFamily, @NonNull @NonNull java.lang.Iterable<TableEntry<KeyT,ValueT>> entries)
Inserts new or updates existingTableEntry
instances that belong to the same Key Family into thisKeyValueTable
. All changes are performed atomically (either all or none will be accepted).- Parameters:
keyFamily
- The Key Family for the all providedTableEntry
instances.entries
- AnIterable
ofTableEntry
instances to insert or update. If for at least one such entry,TableEntry.getKey()
TableKey.getVersion()
indicates a conditional update, this will perform an atomic Conditional Update conditioned on the server-side versions matching the provided ones (for allTableEntry
instances that have one); otherwise an Unconditional Update will be performed. SeeKeyValueTable
doc for more details on Types of Updates.- Returns:
- A CompletableFuture that, when completed, will contain a List of
Version
instances which represent the versions for the inserted/updated keys. The size of this list will be the same as entries.size() and the versions will be in the same order as the entries. Notable exceptions:ConditionalTableUpdateException
If this is a Conditional Update and the condition was not satisfied. See theKeyValueTable
doc for more details on Conditional Update Responses.
-
remove
java.util.concurrent.CompletableFuture<java.lang.Void> remove(@Nullable java.lang.String keyFamily, @NonNull KeyT key)
Unconditionally removes a Key from this Table Segment. If the Key does not exist, no action will be taken.- Parameters:
keyFamily
- (Optional) The Key Family for the Key to remove.key
- The Key to remove.- Returns:
- A CompletableFuture that, when completed, will indicate the Key has been removed.
-
remove
java.util.concurrent.CompletableFuture<java.lang.Void> remove(@Nullable java.lang.String keyFamily, @NonNull KeyT key, @NonNull @NonNull Version version)
Conditionally Removes a Key from this Table Segment.- Parameters:
keyFamily
- (Optional) The Key Family for the Key to remove.key
- The Key to remove.version
- AVersion
representing the version that this Key must have in order to remove it.- Returns:
- A CompletableFuture that, when completed, will indicate the Key has been removed. Notable exceptions:
ConditionalTableUpdateException
If this is a Conditional Removal and the condition was not satisfied. See theKeyValueTable
doc for more details on Conditional Update Responses.
-
removeAll
java.util.concurrent.CompletableFuture<java.lang.Void> removeAll(@Nullable java.lang.String keyFamily, @NonNull @NonNull java.lang.Iterable<TableKey<KeyT>> keys)
Removes one or moreTableKey
instances that belong to the same Key Family from this Table Segment. All removals are performed atomically (either all keys or no key will be removed).- Parameters:
keyFamily
- The Key Family for theTableKey
.keys
- AnIterable
of keys to remove. If for at least one such key,TableKey.getVersion()
indicates a conditional update, this will perform an atomic Conditional Remove conditioned on the server-side versions matching the provided ones (for allTableKey
instances that have one); otherwise an Unconditional Remove will be performed. SeeKeyValueTable
doc for more details on Types of Updates.- Returns:
- A CompletableFuture that, when completed, will indicate that the keys have been removed. Notable exceptions:
ConditionalTableUpdateException
If this is a Conditional Removal and the condition was not satisfied. See theKeyValueTable
doc for more details on Conditional Update Responses.
-
get
java.util.concurrent.CompletableFuture<TableEntry<KeyT,ValueT>> get(@Nullable java.lang.String keyFamily, @NonNull KeyT key)
Gets the latest value for the a Key that belong to a specific Key Family.- Parameters:
keyFamily
- (Optional) The Key Family for the Key to get.key
- The Key to get the value for.- Returns:
- A CompletableFuture that, when completed, will contain the requested result. If no such Key exists, this will be completed with a null value.
-
getAll
java.util.concurrent.CompletableFuture<java.util.List<TableEntry<KeyT,ValueT>>> getAll(@Nullable java.lang.String keyFamily, @NonNull @NonNull java.lang.Iterable<KeyT> keys)
Gets the latest values for a set of Keys that do belong to the same Key Family.- Parameters:
keyFamily
- (Optional) The Key Family for all requested Keys.keys
- AnIterable
of Keys to get values for.- Returns:
- A CompletableFuture that, when completed, will contain a List of
TableEntry
instances for the requested keys. The size of the list will be the same as keys.size() and the results will be in the same order as the requested keys. Any keys which do not have a value will have a null entry at their index.
-
keyIterator
io.pravega.common.util.AsyncIterator<IteratorItem<TableKey<KeyT>>> keyIterator(@NonNull @NonNull java.lang.String keyFamily, int maxKeysAtOnce, @Nullable IteratorState state)
Creates a new Iterator over all theTableKey
s in thisKeyValueTable
that belong to a specific Key Family.- Parameters:
keyFamily
- The Key Family for which to iterate over keys.maxKeysAtOnce
- The maximum number ofTableKey
s to return with each call toAsyncIterator.getNext()
.state
- (Optional) AnIteratorState
that represents a continuation token that can be used to resume a previously interrupted iteration. This can be obtained by invokingIteratorItem.getState()
. A null value will create an iterator that lists all keys.- Returns:
- An
AsyncIterator
that can be used to iterate over all the Keys in thisKeyValueTable
that belong to a specific Key Family.
-
entryIterator
io.pravega.common.util.AsyncIterator<IteratorItem<TableEntry<KeyT,ValueT>>> entryIterator(@NonNull @NonNull java.lang.String keyFamily, int maxEntriesAtOnce, @Nullable IteratorState state)
Creates a new Iterator over all theTableEntry
instances in thisKeyValueTable
that belong to a specific Key Family.- Parameters:
keyFamily
- The Key Family for which to iterate over entries.maxEntriesAtOnce
- The maximum number ofTableEntry
instances to return with each call toAsyncIterator.getNext()
.state
- (Optional) AnIteratorState
that represents a continuation token that can be used to resume a previously interrupted iteration. This can be obtained by invokingIteratorItem.getState()
. A null value will create an iterator that lists all entries.- Returns:
- An
AsyncIterator
that can be used to iterate over all the Entries in thisKeyValueTable
that belong to a specific Key Family.
-
close
void close()
Closes theKeyValueTable
. No more updates, removals, retrievals or iterators may be performed using it.- Specified by:
close
in interfacejava.lang.AutoCloseable
- See Also:
AutoCloseable.close()
-
getMapFor
KeyValueTableMap<KeyT,ValueT> getMapFor(@Nullable java.lang.String keyFamily)
Exposes thisKeyValueTable
instance as aMap
. Please refer to theKeyValueTableMap
documentation for special cases and limitations.This is useful for integrating code that expects to deal with a
Map
. Not all theKeyValueTable
functionality can be implemented using aMap
, however theMap
interface is fully implemented.- Parameters:
keyFamily
- (Optional) The Key Family to create theKeyValueTableMap
for. Any operations on the returnedKeyValueTableMap
will only affect this Key Family. If no Key Family is provided (null), then certainKeyValueTableMap
APIs may not be supported. Refer toKeyValueTableMap
documentation for more details.- Returns:
- A new
KeyValueTableMap
instance bound to thisKeyValueTable
and Key Family.
-
-