Interface KeyValueTable

  • All Superinterfaces:
    java.lang.AutoCloseable

    @Beta
    public interface KeyValueTable
    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.

    TableKeys are made up of two components: Primary Key and Secondary Key.

    • The Primary Key is mandatory and is used to group all TableKeys with the same Primary Key together in the same Table Partition; this allows multiple keys/entries sharing the same Primary Key to be updated/removed atomically. The Primary Keys must all have the same length throughout the Key-Value Table. This needs to be configured when the Key-Value Table is created (See KeyValueTableConfiguration.getPrimaryKeyLength() and must be greater than 0.
    • The Secondary Key is optional. The Secondary Keys must all have the same length throughout the Key-Value Table. This needs to be configured when the Key-Value Table is created (See KeyValueTableConfiguration.getSecondaryKeyLength() and must be at least 0. For Key-Value Tables with no Secondary Keys, set this value to 0. It is important to note that if specifying a non-zero value, then all TableKeys must have both the Primary Key and Secondary Key set; so we may not have TableKeys without Secondary Keys in this case. The Secondary Key is optional at the Table level, not at the Key level.
    • Two TableKey instances are considered equal if they have the same Primary Key and same Secondary Key. The same Secondary Key may be "associated" with different Primary Keys, in which case the resulting TableKeys will be distinct. For example, if we consider Primary Keys PK1 != PK2 and Secondary Key SK1, then key PK1.SK1 is different from key PK2.SK1.
    • Multiple TableKey/TableEntry instances with the same Primary Key can be updated or removed atomically (either all changes will be applied or none will). However, it is important to note that it is not possible to mix updates with removals in the same atomic operation.
    • TableKeys that do not share the same Primary Key may be hashed to different Key-Value Table Partitions and cannot be used for multi-key/entry atomic updates or removals.
    • TableKeys sharing the same Primary Key are grouped into the same Table Segment; as such, the choice of Table Key can have performance implications. As Primary Keys are hashed to Table Segments, a large number of Primary Keys (larger than the number of Table Segments) and a uniform distribution of operations across keys leads to an even distribution of load across Table Segments. Many realistic workloads are skewed, however, and can lead to an uneven load distribution across Table Segments. The use of Secondary Keys also has implications to the load balance. All keys containing a given Primary Key map to the same Table Segment independent of Secondary Key. In the presence of Secondary Keys, the total load for a given Primary Key depends on the load aggregate across all of its Secondary Keys. When the load distribution is highly skewed, one option to consider is eliminating Secondary Keys and only using Primary Keys. The application must be able to encode the key into a single one rather than split into two parts. To illustrate, if we have two Table Keys "A.B" and "A.C", "." representing the separation between Primary and Secondary Keys, then they map to the same Table Segment because they have the same Primary Key "A". If instead, we use "AB" and "AC" as keys, eliminating the Secondary Keys but retaining the necessary information in the Primary Key, then we should be able to map those keys to different Table Segments depending on the hashing.

    Types of Updates:

    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 from Version.NOT_EXISTS or Version.NO_VERSION) but the Key does not exist in the KeyValueTable.
    • BadKeyVersionException: the update or removal has been conditioned on a specific version (different from Version.NO_VERSION but the Key exists in the KeyValueTable with a different version.