Upgrade to Pro — share decks privately, control downloads, hide ads and more …

AntidoteDB, a developer-friendly geo-replicated CRDT data store

AntidoteDB, a developer-friendly geo-replicated CRDT data store

The CAP theorem shows that, when the network partitions, a distributed database system cannot be both strongly consistent and available. Strong consistency (as in Spanner or CockroachDB) globally synchronises every update. This avoids the opportunity for error due to concurrency anomalies, but reduces availability, and increases latency. Conversely, eventually-consistent systems (e.g. Riak or Cassandra) are available and responsive, but the developer must compensate for the database's anomalies in order to avoid violating the application's invariants.
We propose a new approach that is based on application requirements, “Just-Right Consistency” (JRC), ensuring just enough synchronisation to ensure that the application remains correct.

This talk first presents the principles of JRC. Then we present the open-source Antidote database, designed accordingly. Antidote supports concurrent updates and merges them according to their semantics. It guarantees the Transactional Causal Consistency (TCC) model, by which the application can group related updates into an atomic transaction, and there are no ordering anomalies; TCC is the strongest model that does not compromise availability. Antidote encapsulates the synchronisation required by some numerical invariants into a data type (the Bounded Counter). Finally, we present the CISE tool that aids the developer select the consistency level of each update, synchronising only when strictly necessary to the application's semantics.

Presented at Paris Open Source Summit 2018http://www.opensourcesummit.paris/

Other Decks in Research

Transcript

  1. AntidoteDB The developer-friendly open- source cloud database Just-Right Consistency Marc

    Shapiro, UPMC-LIP6 & Inria Annette Bieniusa, U. Kaiserslautern Nuno Preguiça, Valter Balegas, U. Nova Lisboa Christopher Meiklejohn, U. Catholique de Louvain
  2. [AntidoteDB & Just-Right Consistency] Aynchronous updates 4 P Available under

    Partition Concurrency anomalies Eventual Consistency: hell for developers!
  3. [AntidoteDB & Just-Right Consistency] Synchronous updates 5 Consistent under Partition

    Conservative: one at a time Simple programming model Google Spanner
  4. [AntidoteDB & Just-Right Consistency] Synchronous updates 5 P Consistent under

    Partition Conservative: one at a time Simple programming model Expensive infrastructure Not available under partition Google Spanner
  5. [AntidoteDB & Just-Right Consistency] Byrum FMK Fælles Medicinkort 6 R

    X Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…)
  6. [AntidoteDB & Just-Right Consistency] Byrum FMK Fælles Medicinkort 6 R

    X Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…)
  7. [AntidoteDB & Just-Right Consistency] Byrum FMK Fælles Medicinkort 6 R

    X Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…)
  8. [AntidoteDB & Just-Right Consistency] Byrum FMK Fælles Medicinkort 6 R

    X Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…) get-med (…)
  9. [AntidoteDB & Just-Right Consistency] Byrum FMK Fælles Medicinkort 6 R

    X Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…) get-med (…) process (…) Causatin: 2 boxes ⟶ 1
  10. [AntidoteDB & Just-Right Consistency] Sequential FMKe 7 datatype doctor name:

    string prescriptions: set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: doctor patient: patient pharma: pharma med: set of (string, unsigned int) is_sealed: boolean num_processed: unsigned int create_Rx (doctor, patient, pharma) rx: Rx := new Rx() rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions ∪= {rx} return rx add_Rx_med (rx, med, qty) precond ¬rx . is_sealed rx.meds ∪= { (med, qty) } seal_Rx (rx: Rx) precond rx . meds ≠ emptyset rx.patient.prescriptions ∪= { rx }) rx.pharma.prescriptions ∪= { rx }) rx . is_sealed := true process_Rx (rx) precond rx.is_sealed precond rx.num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_meds (rx) rx . num_processed += 1 get_Rx_meds (rx) : set of (string, unsigned int) return rx . meds
  11. [AntidoteDB & Just-Right Consistency] Byrum FMK invariants 8 R X

    Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…) get-med (…) process (…) Causatin: 2 boxes ⟶ 1
  12. [AntidoteDB & Just-Right Consistency] Byrum FMK invariants 8 R X

    Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…) get-med (…) process (…) Causatin: 2 boxes ⟶ 1 relative order 2 1
  13. [AntidoteDB & Just-Right Consistency] Byrum FMK invariants 8 R X

    Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…) get-med (…) process (…) Causatin: 2 boxes ⟶ 1 all or nothing
  14. [AntidoteDB & Just-Right Consistency] Byrum FMK invariants 8 R X

    Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…) get-med (…) process (…) Causatin: 2 boxes ⟶ 1 pre- condition
  15. [AntidoteDB & Just-Right Consistency] Byrum Geo-distrib: invariants? 9 R X

    Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…) get-med (…) process (…) Causatin: 2 boxes ⟶ 1 pre- condition relative order 2 1 all or nothing
  16. [AntidoteDB & Just-Right Consistency] Byrum Geo-distrib: invariants? 9 R X

    Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…) get-med (…) process (…) Causatin: 2 boxes ⟶ 1 pre- condition relative order 2 1 all or nothing EC does not maintain!
  17. [AntidoteDB & Just-Right Consistency] Byrum Geo-distrib: invariants? 9 R X

    Dr Alice Aalborg Hospital Patient: Mr Bob Pharmacy: Byrum Causatin: 2 boxes ⟶ 1 Transactol: 1 box Dr Alice Patient Bob Byrum pharma create (…) add-med (…) get-med (…) process (…) Causatin: 2 boxes ⟶ 1 pre- condition relative order 2 1 all or nothing EC does not maintain! CP is overkill!
  18. [AntidoteDB & Just-Right Consistency] The developer-friendly open-source alternative Preserve sequential

    data invariant patterns Transactional Causal Consistency (TCC) • Maintains AP-compatible invariants • Strongest form of consistency that is AP CAP-sensitive: Synchronise only when strictly necessary for application ⟹ tools No specialised infrastructure, no lock-in 10 .org
  19. [AntidoteDB & Just-Right Consistency] Data model: registers? Concurrent, asynchronous updates

    • Standard register model: assignments ⟹ CP • AP ⟹ concurrent updates merged CRDT: register, counter, set, map, sequence • Extends sequential type • Encapsulates convergent merge 11 meds = ∅ meds≔{aspirin} meds = ∅
  20. [AntidoteDB & Just-Right Consistency] Data model: registers? Concurrent, asynchronous updates

    • Standard register model: assignments ⟹ CP • AP ⟹ concurrent updates merged CRDT: register, counter, set, map, sequence • Extends sequential type • Encapsulates convergent merge 11 meds = ∅ meds≔{aspirin} meds≔{chamomile} meds = ∅
  21. [AntidoteDB & Just-Right Consistency] Data model: registers? Concurrent, asynchronous updates

    • Standard register model: assignments ⟹ CP • AP ⟹ concurrent updates merged CRDT: register, counter, set, map, sequence • Extends sequential type • Encapsulates convergent merge 11 meds = ∅ meds≔{aspirin} meds≔{chamomile} {aspirin} {chamomile} meds = ∅
  22. [AntidoteDB & Just-Right Consistency] AP data model: CRDTs Concurrent, asynchronous

    updates • Standard register model: assignments ⟹ CP • AP ⟹ concurrent updates merged CRDT: register, counter, set, map, sequence • Extends sequential type • Encapsulates convergent merge 12 meds = ∅ meds.add(aspirin) meds = ∅
  23. [AntidoteDB & Just-Right Consistency] AP data model: CRDTs Concurrent, asynchronous

    updates • Standard register model: assignments ⟹ CP • AP ⟹ concurrent updates merged CRDT: register, counter, set, map, sequence • Extends sequential type • Encapsulates convergent merge 12 meds = ∅ meds.add(aspirin) meds.add(chamomile) meds = ∅
  24. [AntidoteDB & Just-Right Consistency] AP data model: CRDTs Concurrent, asynchronous

    updates • Standard register model: assignments ⟹ CP • AP ⟹ concurrent updates merged CRDT: register, counter, set, map, sequence • Extends sequential type • Encapsulates convergent merge 12 meds = ∅ meds.add(aspirin) meds.add(chamomile) {aspirin, chamomile} {aspirin, chamomile} meds = ∅
  25. [AntidoteDB & Just-Right Consistency] datatype doctor name: write-once register of

    string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications FMKe with CRDTs 13 .o
  26. [AntidoteDB & Just-Right Consistency] datatype doctor name: write-once register of

    string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter datatype doctor name: write-once register of string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications FMKe with CRDTs 13 .o
  27. [AntidoteDB & Just-Right Consistency] datatype doctor name: write-once register of

    string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter datatype doctor name: write-once register of string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications FMKe with CRDTs 13 .o datatype doctor name: write-once register of string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter
  28. [AntidoteDB & Just-Right Consistency] datatype doctor name: write-once register of

    string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications FMKe with CRDTs 14 .o
  29. [AntidoteDB & Just-Right Consistency] add_Rx_medication (rx, med, qty) precond ¬

    rx . is_sealed rx . medications . add ((med, qty)) datatype doctor name: write-once register of string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications FMKe with CRDTs 14 .o
  30. [AntidoteDB & Just-Right Consistency] add_Rx_medication (rx, med, qty) precond ¬

    rx . is_sealed rx . medications . add ((med, qty)) datatype doctor name: write-once register of string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications FMKe with CRDTs 14 .o add_Rx_medication (rx, med, qty) precond ¬ rx . is_sealed rx . medications . add ((med, qty))
  31. [AntidoteDB & Just-Right Consistency] Relative order: AP-Compatible create-Rx ⟶ add-Rx-med

    ⟶ seal-Rx Relative-order invariant pattern: • ref exists ⟹ object exists • Rx sealed ⟹ Rx full • Make RHS true; then LHS true If delivered in wrong order, havoc! • Cassandra, Riak, SER, ... Solution: Causal Consistency 15 1=RHS!
  32. [AntidoteDB & Just-Right Consistency] Relative order: AP-Compatible create-Rx ⟶ add-Rx-med

    ⟶ seal-Rx Relative-order invariant pattern: • ref exists ⟹ object exists • Rx sealed ⟹ Rx full • Make RHS true; then LHS true If delivered in wrong order, havoc! • Cassandra, Riak, SER, ... Solution: Causal Consistency 15 1=RHS! 2=LHS!
  33. [AntidoteDB & Just-Right Consistency] Relative order: AP-Compatible create-Rx ⟶ add-Rx-med

    ⟶ seal-Rx Relative-order invariant pattern: • ref exists ⟹ object exists • Rx sealed ⟹ Rx full • Make RHS true; then LHS true If delivered in wrong order, havoc! • Cassandra, Riak, SER, ... Solution: Causal Consistency 15 1=RHS! 2=LHS! P >1
  34. [AntidoteDB & Just-Right Consistency] datatype doctor name: write-once register of

    string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications FMKe under CC 16 .o
  35. [AntidoteDB & Just-Right Consistency] datatype doctor name: write-once register of

    string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications FMKe under CC 16 .o No change!
  36. [AntidoteDB & Just-Right Consistency] Joint update: AP-Compatible create-Rx updates doctor,

    patient & pharmacy record Transmit joint updates together • write-atomic + Read from common set of txns • snapshot property = All-or-Nothing (A of ACID) AP-compatible 17 P pharma! patient!
  37. [AntidoteDB & Just-Right Consistency] Joint update: AP-Compatible create-Rx updates doctor,

    patient & pharmacy record Transmit joint updates together • write-atomic + Read from common set of txns • snapshot property = All-or-Nothing (A of ACID) AP-compatible 17 P pharma! patient! Atomic update
  38. [AntidoteDB & Just-Right Consistency] Joint update: AP-Compatible create-Rx updates doctor,

    patient & pharmacy record Transmit joint updates together • write-atomic + Read from common set of txns • snapshot property = All-or-Nothing (A of ACID) AP-compatible 17 P pharma! patient! pharma! patient! Atomic update
  39. [AntidoteDB & Just-Right Consistency] Joint update: AP-Compatible create-Rx updates doctor,

    patient & pharmacy record Transmit joint updates together • write-atomic + Read from common set of txns • snapshot property = All-or-Nothing (A of ACID) AP-compatible 17 P pharma! patient! pharma! patient? pharma? patient! Atomic update
  40. [AntidoteDB & Just-Right Consistency] patient? pharma? Joint update: AP-Compatible create-Rx

    updates doctor, patient & pharmacy record Transmit joint updates together • write-atomic + Read from common set of txns • snapshot property = All-or-Nothing (A of ACID) AP-compatible 17 P pharma! patient! pharma! patient! Atomic update
  41. [AntidoteDB & Just-Right Consistency] patient? pharma? Joint update: AP-Compatible create-Rx

    updates doctor, patient & pharmacy record Transmit joint updates together • write-atomic + Read from common set of txns • snapshot property = All-or-Nothing (A of ACID) AP-compatible 17 P pharma! patient! pharma! patient! Atomic update Snapshot
  42. [AntidoteDB & Just-Right Consistency] datatype doctor name: write-once register of

    string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx transaction rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) transaction precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) transaction precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) transaction precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications FMKe with AP- transactions 18 .o
  43. [AntidoteDB & Just-Right Consistency] transaction transaction transaction datatype doctor name:

    write-once register of string prescriptions: CRDT_G_set of Rx datatype patient ... datatype pharma ... datatype Rx doctor: write-once register of doctor patient: write-once register of patient pharma: write-once register of pharma medications: CRDT_G_set of (string, int) is_sealed: CRDT_flag num_processed: CRDT_G_counter create_Rx (doctor, patient, pharma) : Rx transaction rx := new Rx(); rx . doctor := doctor rx . patient := patient rx . pharma := pharma rx.doctor.prescriptions . add (rx) return rx add_Rx_medication (rx, med, qty) transaction precond ¬ rx . is_sealed rx . medications . add ((med, qty)) seal_Rx (rx) transaction precond rx . medications ≠ emptyset rx.patient.prescriptions . add (rx) rx.pharma.prescriptions . add (rx) rx . is_sealed := true process_Rx (rx) transaction precond rx . is_sealed precond rx . num_processed = 0 assert rx . medications ≠ ∅ print get_Rx_medications (rx) rx . num_processed . inc() get_Rx_medications (rx) : set of (string, integer) return rx . medications transaction FMKe with AP- transactions 18 .o
  44. [AntidoteDB & Just-Right Consistency] Txnl Causal Consistency Transactional Causal Consistency

    (TCC) = strongest AP model Guarantees AP-compatible invariant patterns Antidote: first industrial-strength TCC database • alpha Guarantees Relative-Order and Joint-Update invariant patterns 19 .org
  45. [AntidoteDB & Just-Right Consistency] process_Rx () transaction precond num_processed =

    0 precond stock[rx.med] ≥ rx.qty num_processed . inc () stock[rx.med] . dec (rx.qty) CAP-sensitive pattern 20 process_Rx() precond = true num_processed = 0 stock[aspirin] = 100
  46. [AntidoteDB & Just-Right Consistency] process_Rx () transaction precond num_processed =

    0 precond stock[rx.med] ≥ rx.qty num_processed . inc () stock[rx.med] . dec (rx.qty) CAP-sensitive pattern 20 process_Rx() precond = true num_processed = 0 stock[aspirin] = 100 num.inc() stock.dec()
  47. [AntidoteDB & Just-Right Consistency] process_Rx () transaction precond num_processed =

    0 precond stock[rx.med] ≥ rx.qty num_processed . inc () stock[rx.med] . dec (rx.qty) CAP-sensitive pattern 20 process_Rx() precond = true num_processed = 0 stock[aspirin] = 100 num_processed = 1 stock[aspirin] = 99 num_processed = 1 stock[aspirin] = 99 num.inc() stock.dec()
  48. [AntidoteDB & Just-Right Consistency] process_Rx () transaction precond num_processed =

    0 precond stock[rx.med] ≥ rx.qty num_processed . inc () stock[rx.med] . dec (rx.qty) CAP-sensitive pattern 21 process_Rx() precond = true num_processed = 0 stock[aspirin] = 100 num_processed = 1 stock[aspirin] = 102 num_processed = 1 stock[aspirin] = 102 num.inc() stock.dec() replenish (aspirin, 3) stock.inc(3)
  49. [AntidoteDB & Just-Right Consistency] process_Rx () transaction precond num_processed =

    0 precond stock[rx.med] ≥ rx.qty num_processed . inc () stock[rx.med] . dec (rx.qty) CAP-sensitive pattern 21 process_Rx() precond = true num_processed = 0 stock[aspirin] = 100 num_processed = 1 stock[aspirin] = 102 num_processed = 1 stock[aspirin] = 102 num.inc() stock.dec() replenish (aspirin, 3) stock.inc(3) Precondition of process_Rx() stable under concurrent replenish()
  50. [AntidoteDB & Just-Right Consistency] process_Rx () transaction precond num_processed =

    0 precond stock[rx.med] ≥ rx.qty num_processed . inc () stock[rx.med] . dec (rx.qty) CAP-sensitive pattern 22 process_Rx() precond = true num_processed = 0 stock[aspirin] = 100 num_processed = 2 stock[aspirin] = 98 num_processed = 2 stock[aspirin] = 98 num.inc() stock.dec() process_Rx() num.inc()
  51. [AntidoteDB & Just-Right Consistency] process_Rx () transaction precond num_processed =

    0 precond stock[rx.med] ≥ rx.qty num_processed . inc () stock[rx.med] . dec (rx.qty) CAP-sensitive pattern 22 process_Rx() precond = true num_processed = 0 stock[aspirin] = 100 num_processed = 2 stock[aspirin] = 98 num_processed = 2 stock[aspirin] = 98 num.inc() stock.dec() process_Rx() num.inc() Precondition of process_Rx() not stable under concurrent process_Rx()
  52. [AntidoteDB & Just-Right Consistency] Addressing CAP- sensitive pattern If precondition

    of f(x) stable under concurrent g(y), and vice-versa, then f(x) || g(y) OK Otherwise: • Either concurrency control (CP, safe) • or weaken precondition, invariant (AP, unsafe) Ex. FMK does not forbid double delivery 23
  53. [AntidoteDB & Just-Right Consistency] Addressing CAP- sensitive pattern If precondition

    of f(x) stable under concurrent g(y), and vice-versa, then f(x) || g(y) OK Otherwise: • Either concurrency control (CP, safe) • or weaken precondition, invariant (AP, unsafe) Ex. FMK does not forbid double delivery 23 Tractable: pairwise
  54. [AntidoteDB & Just-Right Consistency] Bounded Counter Specific but common case

    Shared counter: • x ≥ 0 • increment (n) • decrement (n) // precondition x ≥ n Escrow: • Local share, decrement share –= n • Synchronise only when share < n • Donate share Encapsulated, proven correct (CISE) Mostly AP 24
  55. [AntidoteDB & Just-Right Consistency] Bounded Counter Specific but common case

    Shared counter: • x ≥ 0 • increment (n) • decrement (n) // precondition x ≥ n Escrow: • Local share, decrement share –= n • Synchronise only when share < n • Donate share Encapsulated, proven correct (CISE) Mostly AP 24 AP
  56. [AntidoteDB & Just-Right Consistency] Bounded Counter Specific but common case

    Shared counter: • x ≥ 0 • increment (n) • decrement (n) // precondition x ≥ n Escrow: • Local share, decrement share –= n • Synchronise only when share < n • Donate share Encapsulated, proven correct (CISE) Mostly AP 24 AP CP
  57. [AntidoteDB & Just-Right Consistency] Bounded Counter Specific but common case

    Shared counter: • x ≥ 0 • increment (n) • decrement (n) // precondition x ≥ n Escrow: • Local share, decrement share –= n • Synchronise only when share < n • Donate share Encapsulated, proven correct (CISE) Mostly AP 24 AP CP AP
  58. [AntidoteDB & Just-Right Consistency] CISE tools Static analysis of any

    application: • Operations, invariants • Does each individual op maintain invariant? • Do concurrent updates converge? • Is precondition of u stable w.r.t. concurrent v? If not: ‣ Change specification (invariant) ‣ or Synchronise ‣ Designer decision, per pair (u, v) Ex: medication count= inc||inc, inc||dec, dec||dec 25
  59. [AntidoteDB & Just-Right Consistency] AntidoteDB Rich interface with concurrent abstract

    data types (CRDTs) Geo-replication Low latency, Available under Partition (AP) New, growing community Active development • Secondary Indexes, configurable back-ends and protocols, partial replication, clients in many languages, SQL interface, etc. 26 .org
  60. [AntidoteDB & Just-Right Consistency] Creative Commons Attribution-ShareAlike 4.0 Intl. License

    You are free to: • Share — copy and redistribute the material in any medium or format • Adapt — remix, transform, and build upon the material for any purpose, even commercially, under the following terms: Attribution — You must give appropriate credit, provide a link to the license, and indicate if changes were made. You may do so in any reasonable manner, but not in any way that suggests the licensor endorses you or your use. ShareAlike — If you remix, transform, or build upon the material, you must distribute your contributions under the same license as the original. 28