1 of 16

Composing and Decomposing Op-Based CRDTs with Semidirect Products

Matthew Weidner, Heather Miller, and Christopher Meiklejohn

Carnegie Mellon University

Pittsburgh, PA, USA

ICFP 2020

Virtual Jersey City, NJ, USA

8/24-26/2020

2 of 16

2

Composing and Decomposing Op-Based CRDTs with Semidirect Products

3 of 16

An alternative: CRDTs (Conflict-free Replicated Data Types)

3

// Using Legion CRDT library

var legion = new Legion(...);

legion.joinGroup(...); // sets objectStore

var shopping = objectStore.getOrCreate(

"Shopping", legion.Set

);

shopping.add("milk");

Update local state immediately

Lazily broadcast the operation to other users/replicas

A “PL” way of solving a systems problem.

Composing and Decomposing Op-Based CRDTs with Semidirect Products

4 of 16

Pros

Cons

  • Data shared in small groups only (<100)
  • Conflict resolution alg makes specific choices, which may not be right for every app
  • Need to design conflict-resolution alg for each data type (difficult & ad-hoc)
    • Restricted to a few common data types with restricted interfaces
  • Simple client-side programming model
  • Generic server (broadcast messaging)
  • Minimal latency
  • Works offline
  • Supports end-to-end encrypted webapps
  • Data shared in small groups only (<100)
  • Conflict resolution alg makes specific choices, which may not be right for every app
  • Not for data that needs locking (e.g. money)

4

Composing and Decomposing Op-Based CRDTs with Semidirect Products

5 of 16

In this work

Composition

Decomposition

We present a compositional design technique for (op-based) CRDTs, the semidirect product.

  • Counter → add mult ops
  • List → add reverse op
  • Dictionary → add functional map ops
  • Set → two simpler (commutative) data types
  • Generic resettable CRDT → original CRDT + simple reset-only data type

5

(same state type)

(union of supported ops)

Composing and Decomposing Op-Based CRDTs with Semidirect Products

6 of 16

6

Reason about Causality

  • Alice: “add(‘milk’)”
  • Bob (later): “remove(‘milk’), but only after applying Alice’s op”
  • Result: no one has “milk”.

Make Ops Commute

  • +3, +5 instead of =3, =5
  • Clever sequence types

Update local state immediately

Broadcast the op to other users

Alice: value = 3

Bob: value = 5

Conflict resolution techniques

Composing and Decomposing Op-Based CRDTs with Semidirect Products

7 of 16

Causality in detail

The causal order on operations is a natural partial order < on operations:

CRDTs can query the causal order. Ex. Add-Wins Set CRDT: x is in the set if there is an add(x) operation that is not < any remove(x) operation.

  • So milk stays on the list.

7

add(‘milk’)

add(‘eggs’)

add(‘bread’)

add(‘milk’)

Alice

Bob

Charlie

remove(‘milk’)

<

<

<

concurrent

Composing and Decomposing Op-Based CRDTs with Semidirect Products

8 of 16

8

Reason about Causality

  • E.g. for a set: specify “x is in the set if there is an add(x) operation that is not < any remove(x) operation.”

Make Ops Commute

  • +3, +5 instead of =3, =5
  • Clever sequence types

Conflict resolution techniques

Our semidirect product provides a uniform, reusable way of doing this, so you don’t have to.

New CRDT design workflow: Design commutative data types for simple subsets of operations → Glue together with semidirect products.

Our experience: works for most existing CRDT types, plus novel ones.

Composing and Decomposing Op-Based CRDTs with Semidirect Products

9 of 16

An example of our semidirect product

(int register w/ add ops) + (int register w/ mult ops) → int register with both

  • add operations alone are easy: they already commute.
  • Same for mult operations alone.
  • But they conflict with each other:

9

Dave

Mary

Composing and Decomposing Op-Based CRDTs with Semidirect Products

10 of 16

Observation: If we receive concurrent add and mult operations in the “wrong” order (mult before add), we get the right result if we act on the add with the mult.

Goal: Integer register CRDT supporting add and mult operations

Let us choose that in the face of concurrency, “adds go before mults”.

  • Works by distributive law:

10

Dave

Mary

Dave

Mary

Composing and Decomposing Op-Based CRDTs with Semidirect Products

11 of 16

Goal: Integer register CRDT supporting add and mult operations

When you receive an add operation, transform it by all concurrent mult operations you’ve already received.

  • So becomes , where are all of the operations you’ve previously received that are concurrent to .
  • Works more generally subject to algebraic constraints on the input CRDTs & action.

When you receive an add operation, transform it by all concurrent mult operations you’ve already received.

11

Dave

Mary

Composing and Decomposing Op-Based CRDTs with Semidirect Products

12 of 16

Recap

Thanks for watching :)

  • CRDTs are a nice “PL” way of building systems that act on shared state
    • Programmers just replace ordinary data types with CRDT versions
    • More info: https://crdt.tech/
  • Our semidirect product is a compositional design technique for CRDTs
    • Resolve conflicts between ops by reasoning about causality in a uniform, reusable way - so CRDT designers don’t have to
    • New CRDT design workflow: Design commutative data types for subsets of ops → Glue together with semidirect products

12

Questions?

Image credits: zombo.com, openclipart.org

Composing and Decomposing Op-Based CRDTs with Semidirect Products

13 of 16

13

Composing and Decomposing Op-Based CRDTs with Semidirect Products

14 of 16

Relation to Operational Transformation

Recall: OT is a competing approach to eventually consistent replicated data types. Instead of making concurrent operations commute, you define a transformation function tf_1: O x O -> O.

  • Received operations are transformed against previously-received concurrent operations using the (somewhat complicated) adOPTed algorithm (Ressel et al. ‘96).
  • Eventual consistency follows from 2 Transformation Properties, which are hard to verify (esp. TP2).

The semidirect product is the special case of OT when O = O_1 \sqcup O_2 and tf_1(p, q) = p except when p \in O_1, q \in O_2. (O_2 ops transform concurrent O_1 ops, but that’s it.)

  • With these restrictions, adOPTed becomes the simple algorithm described for the add/mult integer register, and TP2 is typically trivial to verify.

It is interesting that we get common CRDT semantics from this special case of OT.

14

Composing and Decomposing Op-Based CRDTs with Semidirect Products

15 of 16

Generality

Q: When can a CRDT be decomposed as a semidirect product of simpler CRDTs?

Let C be a CRDT in the POLog model of pure op-based CRDTs. I.e., C is defined by a function f mapping the partially ordered log of operations to a visible state.

Suppose the ops of C can be partitioned as O1 U O2 so that for any POLog L, f(L) = f(L’) whenever L = L’ except that we have added some edges o1< o2 with o1 ∊ O1, o2 ∊ O2. Then C is the semidirect product of a CRDT with only O1 ops and a CRDT with only O2 ops.

This expresses the rule that O1 ops “go before” concurrent O2 ops.

15

Composing and Decomposing Op-Based CRDTs with Semidirect Products

16 of 16

Name Origin: Semidirect Product of Groups

In abstract algebra, a group is a set G with a binary operation ∘ : G x G → G satisfying multiplication-like properties.

  • ∘ is associative (g ∘ (h ∘ k) = (g ∘ h) ∘ k); ∃ 1 ∊ G s.t. g ∘ 1 = 1 ∘ g = g; ∀g ∊ G ∃ g-1 ∊ G s.t. g ∘ g-1 = 1.
  • I.e., a monoid with inverses.

The semidirect product combines two groups G, H into a group with set G x H. It contains copies of G and H which commute as

h ∘ g = (h ⊳ g) ∘ h

for a suitable action ⊳ of H on G.

The semidirect product of CRDTs uses an analogous rule to reorder concurrent ops from the components.

16

Composing and Decomposing Op-Based CRDTs with Semidirect Products