Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DOC-392 A/A support for bitfield #1300

Merged
merged 5 commits into from
Apr 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions content/rs/references/developing-for-active-active/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ where synchronization catches up to distribute all local member Active-Active da
updates to other participating clusters and other member Active-Active databases.

| **Time** | **Member CRDB1** | **Member CRDB2** |
| ------: | :------: | :------: |
| :------: | :------: | :------: |
| t1 | INCRBY key1 7 | |
| t2 | | INCRBY key1 3 |
| t3 | GET key1<br/>7 | GET key1<br/>3 |
Expand Down Expand Up @@ -112,10 +112,11 @@ followed by descriptions:

| **Data Type** | **Support Level** |
|------------|-----------------|
| Float Counters | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-strings-active-active.md#string-data-type-with-counter-value-in-crdbs" >}}) |
| Bitfield | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-strings-active-active.md" >}}) |
| Float Counters | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-strings-active-active.md#string-counter-support" >}}) |
| Geospatial | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-sorted-sets-active-active.md" >}}) |
| Hashes | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-hashes-active-active.md" >}}); Hash fields are treated as strings or counters |
| Integer Counters | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-strings-active-active.md#string-data-type-with-counter-value-in-crdbs" >}}) |
| Integer Counters | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-strings-active-active.md#string-counter-support" >}}) |
| Lists | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-lists-active-active.md" >}}) |
| Sets | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-sets-active-active.md" >}}) |
| Strings | [Supported]({{< relref "/rs/references/developing-for-active-active/developing-strings-active-active.md" >}}) |
Expand Down
Original file line number Diff line number Diff line change
@@ -1,57 +1,67 @@
---
Title: Developing with Strings in an Active-Active database
Title: Strings and Bitfields with Active-Active Databases
description:
weight: $weight
alwaysopen: false
categories: ["RS"]
aliases: /rs/references/developing-for-active-active/developing-strings-active-active.md/
/rs/developing/crdbs/strings/
---
Strings have particular unique characteristics in an Active-Active database. First off,
they are the only data type that Last Write Wins (LWW) applies to. As
part of that, a wall-clock timestamp (OS Time) is in the metadata of any
operation on a String. If Redis Enterprise Software cannot determine the order of operations,
the value with the higher timestamp wins. This is the only case where OS
time is used to resolve a conflict.

Here is an example where an update happening to the same key at a later
Active-Active databases support both strings and bitfields.

{{<note>}}
Active-Active **bitfield** support was added in RS version 6.0.20.
{{</note>}}

Changes to both of these data structures will be replicated across Active-Active member databases.

## Replication semantics

Except in the case of [string counters]({{< relref "#string-counter-support" >}}) (see below), both strings and bitfields are replicated using a "last write wins" approach. The reason for this is that strings and bitfields are effectively binary objects. So, unlike with lists, sets, and hashes, the conflict resolution semantics of a given operation on a string or bitfield are undefined.

### How "last write wins" works

A wall-clock timestamp (OS time) is stored in the metadata of every string
and bitfield operation. If the replication syncer cannot determine the order of operations,
the value with the latest timestamp wins. This is the only case with Active-Active databases where OS time is used to resolve a conflict.

Here's an example where an update happening to the same key at a later
time (t2) wins over the update at t1.

| **Time** | **Member CRDB1** | **Member CRDB2** |
| ------: | :------: | :------: |
| t1 | SET key1 “a” | |
| t2 | | SET key1 “b” |
| **Time** | **Region 1** | **Region 2** |
| :------: | :------: | :------: |
| t1 | SET text “a” | |
| t2 | | SET text “b” |
| t3 | — Sync — | — Sync — |
| t4 | SET key1 “c” | |
| t4 | SET text “c” | |
| t5 | — Sync — | — Sync — |
| t6 | | SET key1 “d” |
| t6 | | SET text “d” |

Bitfield methods like SETBIT are not supported in Active-Active databases.
### String counter support

### String data type with counter value in Active-Active databases

Counters can be used to implement distributed counters. This can be useful when counting total views of an
article or image, or when counting social interactions like "retweets"
or "likes" of an article in an Active-Active database distributed to multiple geographies.
When you're using a string as counter (for instance, with the [INCR](https://redis.io/commands/incr) or [INCRBY](https://redis.io/commands/incrby) commands),
then conflicts will be resolved semantically.

On conflicting writes, counters accumulate the total counter operations
across all member Active-Active databases in each sync. Here is an example of how counter
values can be initialized and maintained across two member Active-Active databases. With
across all member Active-Active databases in each sync.

Here's an example of how counter
values works when synced between two member Active-Active databases. With
each sync, the counter value accumulates the private increment and
decrements of each site and maintain an accurate counter across
concurrent writes.

| **Time** | **Member CRDB1** | **Member CRDB2** |
| ------: | :------: | :------: |
| t1 | INCRBY key1 7 | |
| t2 | | INCRBY key1 3 |
| t3 | GET key1<br/>7 | GET key1<br/>3 |
| **Time** | **Region 1** | **Region 2** |
| :------: | :------: | :------: |
| t1 | INCRBY counter 7 | |
| t2 | | INCRBY counter 3 |
| t3 | GET counter<br/>7 | GET counter<br/>3 |
| t4 | — Sync — | — Sync — |
| t5 | GET key1<br/>10 | GET key1<br/>10 |
| t6 | DECRBY key1 3 | |
| t7 | | INCRBY key1 6 |
| t5 | GET counter<br/>10 | GET counter<br/>10 |
| t6 | DECRBY counter 3 | |
| t7 | | INCRBY counter 6 |
| t8 | — Sync — | — Sync — |
| t9 | GET key1<br/>13 | GET key1<br/>13 |
| t9 | GET counter<br/>13 | GET counter<br/>13 |

{{< note >}}
Active-Active databases support 59-bit counters.
Expand Down