17
Conflict-free Replicated Data Type Функциональный подход к распределённым системам Сергей Укустов

Expert Fridays - Сергей Укустов: "CRDT"

Embed Size (px)

Citation preview

Page 1: Expert Fridays - Сергей Укустов: "CRDT"

Conflict-free ReplicatedData Type

Функциональный подход к распределённым системам

Сергей Укустов

Page 2: Expert Fridays - Сергей Укустов: "CRDT"

«Умные структуры данных и тупой код работают куда лучше, чем наоборот»

Эрик Раймонд

Page 3: Expert Fridays - Сергей Укустов: "CRDT"

Распределённые системы

• Много общающихся машин

• Общее состояние• Бывает разное

• CAP теорема• Consistency, Availability, Partitioning – выберите любые два

• CALM теорема• Consistency as logical monotonicity – система может быть распределённой,

если она не удаляет исторические факты

Page 4: Expert Fridays - Сергей Укустов: "CRDT"
Page 5: Expert Fridays - Сергей Укустов: "CRDT"

CRDT

• Тип структур данных для eventually consistent систем

• Формально доказано: состояние системы сходится

• CAP теорема: выкидываем строгую consistency

• CALM теорема: строгая гарантия eventual consistency

Page 6: Expert Fridays - Сергей Укустов: "CRDT"

CRDT: State-based

• Множество <A, combine>• a combine (b combine c) == (a combine b) combine c

• a combine b == b combine a

• a combine a == a

• Необходимо есть нулевой элемент• Ограниченная полурешетка AKA коммутативный идемпотентный моноид

• Частичный порядок

Page 7: Expert Fridays - Сергей Укустов: "CRDT"

G-Counter

• Можно только увеличивать счётчик

case class GCounter[R, E](state: Map[R, E])(implicit num: Numeric[E])

import com.machinomy.crdt.state._import cats.syntax.all._import cats._

val counter = Monoid[GCounter[Int, Int]].empty // empty G-Counterval firstReplica = counter + (1 -> 1) // increment replica 1val secondReplica = counter + (2 -> 2) // increment replica 2val firstReplicacombined = firstReplica |+| secondReplica // combineval secondReplicacombined = secondReplica |+| firstReplica // combine

firstReplicacombined == secondReplicacombined // the result is independent of combine order

Page 8: Expert Fridays - Сергей Укустов: "CRDT"

PN-Counter

• Можно делать инкремент и декремент

class PNCounter[K, E: Numeric](increments: GCounter[K, E], decrements: GCounter[K, E])

import com.machinomy.crdt.state._import cats.syntax.all._import cats._

val counter = Monoid[PNCounter[Int, Int]].emptyval firstReplica = counter + (1 -> 1) // increment replica 1val secondReplica = counter + (2 -> -2) // decrement replica 2val firstReplicacombined = firstReplica |+| secondReplica // combineval secondReplicacombined = secondReplica |+| firstReplica // combine

firstReplicacombined == secondReplicacombined // the result is independent of combine order

Page 9: Expert Fridays - Сергей Укустов: "CRDT"

G-Set

• Только добавление, `combine` объединяет множества

• class GSet[E](val state: Set[E])

import com.machinomy.crdt.state._import cats.syntax.all._import cats._

val counter = Monoid[GSet[Int]].empty // empty G-Setval firstReplica = counter + 1 // add elementval secondReplica = counter + 2 // add elementval firstReplicacombined = firstReplica |+| secondReplica // combineval secondReplicacombined = secondReplica |+| firstReplica // combine

firstReplicacombined == secondReplicacombined // the result is independent ofcombine order

Page 10: Expert Fridays - Сергей Укустов: "CRDT"

И ещё…

• GT-Set

• MC-Set

• OR-Set

• TP-Set

• LWW-Element-Set

• LWW-Register

• …

Page 11: Expert Fridays - Сергей Укустов: "CRDT"

CRDT: Op-based

• Передаём операции по сети, а не состояниеS · f · g = S · g · f

• Можно эмулировать поверх state-based, и наоборот

Page 12: Expert Fridays - Сергей Укустов: "CRDT"

Op-based Counter

case class Counter[E: Numeric](value: E)

def update[E: Numeric](counter: Counter[E], update: Update[E]): Counter[E] = update match {

case Counter.Increment(i) => Counter(num.plus(counter.value, i))case Counter.Decrement(i) => Counter(num.minus(counter.value, i))

}

Page 13: Expert Fridays - Сергей Укустов: "CRDT"

Op-based ORSet

case class ORSet[E, T: TombStone](state: Map[E, Set[T]])

Page 14: Expert Fridays - Сергей Укустов: "CRDT"

2P2P-Graph

case class TPTPGraph[A, V <: VertexLike[A], E <: EdgeLike[A, V]]

(va: Set[V], vr: Set[V], ea: Set[E], er: Set[E])

• Можно добавлять и удалять элементы

• Но никаких гарантий!

Page 15: Expert Fridays - Сергей Укустов: "CRDT"

Monotonic DAG

Page 16: Expert Fridays - Сергей Укустов: "CRDT"

Monotonic DAG

case class MonotonicDag[V, E[X] <: DiEdgeLikeIn[X], G <: Graph[V, E]](graph: G)

type UpdateResult[V, E[X] <: DiEdgeLikeIn[X], G <: Graph[V, E]] = (MonotonicDag[V, E, G], Option[Update[V, E, G]])

def add(e: E[V] with OuterEdge[V, E]): MonotonicDag.UpdateResult[V, E, G] = {val from = graphLike.fromVertex(graph, e)val to = graphLike.toVertex(value, e)val containsSource = graphLike.contains(value, from)val containsDestination = graphLike.contains(value, to)val effective = graphLike.addEdge(value, e)if (containsSource && containsDestination && graphLike.existsPath(effective, from, to)) {(MonotonicDag[V, E, G](effective), Some(MonotonicDag.AddEdge[V, E, G](e)))

} else {(this, None)

}}

Page 17: Expert Fridays - Сергей Укустов: "CRDT"

Pro et Contra

• Простая логика

• Стабильное теоретическое обоснование

• Лучше, чем OT

• Социальное доказательство

• Непонятно, что делать с BFT

• Необходимо обеспечить стабильный канал

• Сложно найти подходящую реализацию

https://github.com/machinomy/crdthttps://www.mendeley.com/groups/9275881/crdt/papers/

[email protected]