KharkivJS 2017: Коллаборативные системы и CRDT

48
Коллаборативные системы Collaborative systems and Conflict-Free Replicated Data Types Максим Климишин Head of Software Architecture at Takeoff Technologies 29 октября 2017 г. Максим Климишин Коллаборативные системы 1 / 48

Transcript of KharkivJS 2017: Коллаборативные системы и CRDT

Коллаборативные системыCollaborative systems and Conflict-Free Replicated Data Types

Максим Климишин

Head of Software Architecture at Takeoff Technologies

29 октября 2017 г.

Максим Климишин Коллаборативные системы 1 / 48

Работа

Head of Software Architecture, Takeoff Technologies, 2017CTO @ ZAKAZ.UA and CartFresh, 2012Team Lead @ oDesk (now Upwork), 2010Project Coordinator @ 42 Coffee Cups, 2009

Максим Климишин Коллаборативные системы 2 / 48

Организация

co-organizer of PapersWeLove Kyivco-founder of KyivJSco-founder of LvivJSco-organizer of PyCon Ukraineco-organizer of Hotcodejudge at UA Web Challenge

Максим Климишин Коллаборативные системы 3 / 48

Takeoff TechnologieseGrocery: Grocery Delivery startup with robotic warehouse

Максим Климишин Коллаборативные системы 4 / 48

Distributed systems & Groupware systems

Онлайн игрыКалендарь, контакты, напоминалкиСофт для конференцийРедактирование онлнай несколькими людьмиГрупповые чаты

Максим Климишин Коллаборативные системы 5 / 48

Распределенные приложения

Использование на разных устройствах в разное времяОдновременное использование на разных устройствахРабота офлайн

Максим Климишин Коллаборативные системы 6 / 48

Data and Consistency

Максим Климишин Коллаборативные системы 7 / 48

Serializability

serial schedule i.e. sequential with no operations overlap in time

Solution of a Problem in Concurrent Programming Control (E.W. Dijkstra,1965)

A Quorum-based Commit Protocol (Dale Skeen, 1982)

Максим Климишин Коллаборативные системы 8 / 48

Concurrency fundamentals

divergence или расхождение: ∪ni=1o

1i ̸= ∪m

j=1o2j

causality-violations или нарушение порядка операций:o1 → o3

intention-violations или нарушение намерений: o1||o2

Максим Климишин Коллаборативные системы 9 / 48

Что приходит в голову

LockingTransactionsTentative TransactionsSingle Active ParticipantDependency DetectionReversible Execution

Максим Климишин Коллаборативные системы 10 / 48

Good luck with thatThe Ultimate Guide to Becoming Your Best Self

Максим Климишин Коллаборативные системы 11 / 48

Consistency Models

Strong ConsistencyWeak ConsistencyRead Your WritesEventual ConsistencyStrong Eventual Consistency

Максим Климишин Коллаборативные системы 12 / 48

Replication Types

PessimisticOptimistic or Eventual Consistency

Максим Климишин Коллаборативные системы 13 / 48

Concurrency Control in Distributed Systems1989 by Ellis and Gibbs/GROVE editor

Операции должны быть коммутативными, чтобы удовлетворитьconvergence property:

op1 ⊙ op2 = op2 ⊙ op1

Максим Климишин Коллаборативные системы 14 / 48

Кто использует OT?Wave took 2 years to write and if we rewrote it today, it

would take almost as long to write a second time

on ShareJS

Максим Климишин Коллаборативные системы 15 / 48

Proving correctness of transformation functions incollaborative editing systems2006 Gerald Oster et al

Доказал что все алгоритмы некорректные (сконтрпримерами), упсПредложил TTF (Tombstone Transformation Functions)

Максим Климишин Коллаборативные системы 16 / 48

Operation Transformations on Google Scholar1989-2006

Максим Климишин Коллаборативные системы 17 / 48

OP DOH

Максим Климишин Коллаборативные системы 18 / 48

Conflict-Free Replicated Data TypesCRDTs

Максим Климишин Коллаборативные системы 19 / 48

Ограничения сети

ЗадержкиDrop пакетовПорядокДубликаты

Максим Климишин Коллаборативные системы 20 / 48

Conflict-free replicated data types (CRDT)2011 Shapiro et al

коммутативность – ∀x, y : x⊙ y = y ⊙ x

ассоциативность – x⊙ (y ⊙ z) = (x⊙ y)⊙ z

идемпотентность – x⊙ x = x

Максим Климишин Коллаборативные системы 21 / 48

Strong Eventual Consistency

C = [c1, ..., cn], ∀i, j : ci = cj ⇒ si ≡ sj

Максим Климишин Коллаборативные системы 22 / 48

Счетчик

1 + 1

Максим Климишин Коллаборативные системы 23 / 48

+ идемпотентность нарушена

1 + 1 ̸= 1

Максим Климишин Коллаборативные системы 24 / 48

∪ – ништяк с сетами

1 ∪ 1 = 1

Максим Климишин Коллаборативные системы 25 / 48

Прочие свойства в семантике множеств

(1 ∪ 2) ∪ 3 = 1 ∪ (2 ∪ 3)

1 ∪ 2 = 2 ∪ 1

Максим Климишин Коллаборативные системы 26 / 48

CRDT

ciCRDT State(convergent)

ConflictResolutionSemantics

Applicationaccess API

Si

Максим Климишин Коллаборативные системы 27 / 48

CRDT: GCounterGrowth-only counter: Interface

export class GCounter {constructor(counters) { this.counters = counters; }increment(id) { ... }query() { ... }merge(counter) { ... }

}

Максим Климишин Коллаборативные системы 28 / 48

CRDT: GCounter payloadCounter State on init

let counters = {1: 02: 0...N: 0}

Максим Климишин Коллаборативные системы 29 / 48

CRDT: GCounter increment op

export class GCounter {increment(id) {

return new GCounter(Object.assign({[id]: (this.counters[id] || 0) + 1}))}

}

Максим Климишин Коллаборативные системы 30 / 48

CRDT: GCounter query op

export class GCounter {query() {

return Object.values(this.counters).reduce((a, b) => a + b, 0);}

}

Максим Климишин Коллаборативные системы 31 / 48

CRDT: GCounter merge op

export class GCounter {merge(counter) {

let sites = Object.keys(counter.counters).concat(Object.keys(this.counters));

return new GCounter(sites.reduce((merged, site) => Object.assign(

merged, {[site]: Math.max(merged[site] || 0,counter.counters[site] || 0)}),

this.counters));}

}

Максим Климишин Коллаборативные системы 32 / 48

CRDT: GCounter sum it up

export class GCounter {constructor(counters) { this.counters = counters; }increment(id) {

return new GCounter(Object.assign({[id]: (this.counters[id] || 0) + 1}))}

query() {return Object.values(this.counters)

.reduce((a, b) => a + b, 0); }merge(counter) {

let sites = Object.keys(counter.counters).concat(Object.keys(this.counters));

return new GCounter(sites.reduce((merged, site) => Object.assign(

merged, {[site]: Math.max(merged[site] || 0,counter.counters[site] || 0)}),

this.counters));}

}

Максим Климишин Коллаборативные системы 33 / 48

CRDT: GCounter-testIncrement only counter

linenos function examples_GCounter() {linenos let log = (op, c1, c2) => console.log(linenos "[OP] " + op + ": c1=" + c1.query() + ",linenos c2=" + c2.query());linenos let counter1 = new GCounter({});linenos let counter2 = new GCounter({});linenoslinenos log("counter1", counter1, counter2);linenos counter1 = counter1.increment(0);linenos log("counter1++", counter1, counter2);linenos counter2 = counter2.merge(counter1);linenos log("counter1 U counter2", counter1, counter2);linenos }

Максим Климишин Коллаборативные системы 34 / 48

CRDT: GCounter example output

linenos node_modules/.bin/babel-node --presets es2016,es2015 main.jslinenos [OP] counter1: c1=0, c2=0linenos [OP] counter1++: c1=1, c2=0linenos [OP] counter1 U counter2: c1=1, c2=1

Максим Климишин Коллаборативные системы 35 / 48

CRDT: PNCounterPositive-Negative Counter

class PNCounter {constructor(p, n) { this.n = n; this.p = p}increment() { return new PNCounter(this.p.increment(), this.n); }decrement() { return new PNCounter(this.p, this.n.increment()); }query() { return this.p.query() - this.n.query(); }merge(pncounter) {

return new PNCounter(this.p.merge(pncounter.p),this.n.merge(pncounter.n)); }

}

Максим Климишин Коллаборативные системы 36 / 48

CRDT: MVRegisterMulti-Value Register

export class MVRegister {constructor(id, register) { this.id = id; this.register = register; }set(value) {

return new MVRegister(this.id,Object.assign(this.register, {[this.id]: value}))}

query() {return Object.values(this.register); }merge(register) {

let state = this.register[this.id] === undefined ?{} : {[this.id]: this.register[this.id]};

return new MVRegister(this.id,Object.assign(register.register, state))

}}

Максим Климишин Коллаборативные системы 37 / 48

CRDT: MVRegister Testconst repr = (arr) => arr.length === 0 ? '[]' :

'["' + arr.join('", "') + '"]';

function example_mvregister() {let log = (op, r1, r2) => console.log("[OP] " + op +

": r1=" + repr(r1.query()) +", r2=" + repr(r2.query()));

let r1 = new MVRegister(1, {});let r2 = new MVRegister(2, {});

log("register1", r1, r2);r1 = r1.set("key1")log("r1.set(key1)", r1, r2);r2 = r2.merge(r1);log("r1 U r2", r1, r2);r1.set("v1");log("r1.set(v1)", r1, r2)r2.set("v2")log("[CONCURRENT] r2.set(v2)", r1, r2)r2 = r2.merge(r1);log("[MERGED]", r1, r2);

}Максим Климишин Коллаборативные системы 38 / 48

CRDT: MVRegister Output

[OP] register1: r1=[], r2=[][OP] r1.set(key1): r1=["key1"], r2=[][OP] r1 U r2: r1=["key1"], r2=["key1"][OP] r1.set(v1): r1=["v1"], r2=["key1"][OP] [CONCURRENT] r2.set(v2): r1=["v1"], r2=["key1", "v2"][OP] [MERGED]: r1=["v1", "v2"], r2=["v1", "v2"]

Максим Климишин Коллаборативные системы 39 / 48

JSON CRDTA Conflict-Free Replicated JSON Datatype (August 15, 2017)

Максим Климишин Коллаборативные системы 40 / 48

JSON CRDTConcurrent mutation on same key with different types

Максим Климишин Коллаборативные системы 41 / 48

CRDT Shopping Cart2017: redesign of Shopping Cart API

Максим Климишин Коллаборативные системы 42 / 48

CRDTs: CvRDT, CmRDTstate-based and op-based replication

Рис.: State-basedConvergent Replicated Data

Type or CvRDT

Рис.: Op-based CommutativeReplicated Data Type or

CmRDT

Максим Климишин Коллаборативные системы 43 / 48

CRDT: TypesRegisters, Counters, Sets

Register: LWW or Multi-Value (Dynamo or Couchdb-like)Counter (growth-only) and Counter w/decrementingG-Set – growth-only set2P-Set – remove only once set (G-Set + Tombstones set)LWW-Element-Set – vector clocksOR-Set – unique-tagged elements and list of tags withinTombstones setWOOT, LOGOOT, Treedoc, RGA, LSEQ for ordered lists

Максим Климишин Коллаборативные системы 44 / 48

Инструменты

Y-js – framework for offline-first p2p shared editing on structureddataRiak 2.0: Counters, Flags, Sets, Registers, MapsRoshi by SoundcloudShareDB (and fall of Google Wave)Swarm (and forever-in-pre-alpha tool)OT.js (Operational Transformation for JS)CRDT – github.com/dominictarr/crdtreplikativ.io – p2p distributed system frameworkGUN framework: p2p distributed framework

Максим Климишин Коллаборативные системы 45 / 48

Cвой CRDT

+ Мало кода+ Относительно легко дополнять+ Предсказуемо работает+ Надежно при любом качестве связи+ Работа оффлайн- Сложная ментальная модель- Семантическое разрешение конфликтов- Сложно оптимально подобрать параметры GC- Реально сложно работать с большим количеством данных(δ-mutation)

Максим Климишин Коллаборативные системы 46 / 48

Thanks

@maxmaxmaxmax

Максим Климишин Коллаборативные системы 48 / 48