Date post: | 21-Jan-2018 |
Category: |
Software |
Upload: | max-klymyshyn |
View: | 140 times |
Download: | 4 times |
Коллаборативные системы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
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
Ограничения сети
Задержки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 ∪ 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
У кого в проде?
FacebookTomTomLeague of LegendsSoundCloudBet265RIAK Distributed Database
Максим Климишин Коллаборативные системы 47 / 48