86
#DevoxxFR Algorithmes distribués pour le Big Data saison 2 1

Algorithme distribués pour big data saison 2 @DevoxxFR 2016

Embed Size (px)

Citation preview

#DevoxxFR

Algorithmes distribués pour le Big Data

saison 2

1

#DevoxxFR

Un peu de moi Duy Hai DOAN

Evangéliste technique & consultant Apache Cassandra

•  talks, meetups, confs

•  projet open-source (Achilles, Apache Zeppelin)

•  Des questions sur Apache Cassandra/Apache Zeppelin ? ☞ [email protected] ☞ @doanduyhai

2

#DevoxxFR

Datastax •  Fondé en Avril 2010

•  Plus gros pourvoyeur de contributeur à Apache Cassandra™

•  Bureaux européens à Londres, Paris et Berlin

•  Datastax Enterprise = OSS Cassandra + fonctionnalités+++

3

#DevoxxFR

CRDT Marc Shapiro – 2011

#DevoxxFR

Le défi

5

Dans un système distribué, définir les conditions suffisantes à respecter pour garantir la convergence des données

potentiellement désynchronisées

#DevoxxFR

Le défi

6

Dans un système distribué, définir les conditions suffisantes à respecter

pour garantir la convergence des données potentiellement désynchronisées

#DevoxxFR

Le défi

7

Dans un système distribué, définir les conditions suffisantes à respecter pour garantir la convergence des données

potentiellement désynchronisées

#DevoxxFR

Le défi

8

Dans un système distribué, définir les conditions suffisantes à respecter pour garantir la convergence des données

potentiellement désynchronisées

#DevoxxFR

CRDT

9

Conflict-free Replicated Data Types

Définit les conditions suffisantes pour un système "strong eventually consistent"

Autorise une disponibilité extrême, N-1 nœuds en panne sur N nœuds au total

#DevoxxFR 10

Types de CRDT À état: Convergent Replicated Data Types (CvRDT) Par fonction: Commutative Replicated Data Types (CmRDT)

#DevoxxFR

CvRDT: conditions d’application

11

Tous les réplicas sont connectés (en général) Échange d’état au moins 1 fois, sur un médium ponctuellement fiable L’ensemble des états forme un demi-treillis borné Tous les changements d’état transitionnent vers un nouvel état en suivant l’ordre partiel

#DevoxxFR

CvRDT: conditions d’application

12

Tous les réplicas sont connectés (en général) Échange d’état au moins 1 fois, sur un médium ponctuellement fiable L’ensemble des états forme un demi-treillis borné Tous les changements d’état transitionnent vers un nouvel état en suivant l’ordre partiel

#DevoxxFR

CvRDT: conditions d’application

13

Tous les réplicas sont connectés (en général) Échange d’état au moins 1 fois, sur un médium ponctuellement fiable L’ensemble des états forme un demi-treillis borné Tous les changements d’état transitionnent vers un nouvel état en suivant l’ordre partiel

Ensemble d’éléments partiellement ordonnés ayant un borne supérieure (merci Wikipedia)

#DevoxxFR

CvRDT: conditions d’application

14

Tous les réplicas sont connectés (en général) Échange d’état au moins 1 fois, sur un médium ponctuellement fiable L’ensemble des états forme un demi-treillis borné Tous les changements d’état transitionnent vers un nouvel état en suivant l’ordre partiel

#DevoxxFR

Définition formelle

#DevoxxFR

CvRDT: définition

16

A join semilattice (or just semilattice hereafter) is a partial order ≤v equipped with a least upper bound (LUB) ⊔v, defined as follows:

Definition 2.4 m = x ⊔v y is a least upper bound of {x, y} under ≤v iff

x ≤v m and

y ≤v m and

there is no m′ ≤v m such that x ≤v m′ and y ≤v m′

It follows from the definition that ⊔v is: commutative: x ⊔v y =v y ⊔v x; idempotent: x ⊔v x =v x; and associative: (x⊔v y)⊔v z =v x⊔v (y⊔v z).

#DevoxxFR

CvRDT: spécification

17

#DevoxxFR

CvRDT: exemple G-Set

18

Payload Set S, initial value S := { }

Query(e)

e ∈ S ? Update

add(e): S := S ∪ {e} Merge(S’)

S := S ∪ S’

relation d’ordre ≤v = ∈ opérateur ⊔v = ∪ l’union ensembliste ∪ est commutative, associative et idempotente

#DevoxxFR

relation d’ordre ≤v = ∈ opérateur ⊔v = ∪ l’union ensembliste ∪ est commutative, associative et idempotente

CvRDT: exemple G-Set

19

Payload Set S, valeur initiale S := { }

Query(e)

e ∈ S ? Update

add(e): S := S ∪ {e} Merge(S’)

S := S ∪ S’

Problème: comment gérer les suppressions d’éléments dans le Set ?

#DevoxxFR

CvRDT: 2P-Set

20

Payload Set A, R initial value A := { } , R := { }

Query(e)

(e ∈ A) ∧ (e ∉ R) ? Update

add(e): A := A ∪ {e}, remove(e): R := R ∪ {e} Merge(A’, R’)

A := A ∪ A’, R := R ∪ R’

#DevoxxFR

CvRDT: LWW-Register

21

Payload (X, timestamp t), (∅, 0)

Query(e)

e = X ? Update

assign(e): X := e, t := now() Merge((X’, t’))

If t’ < t then (X, t) else (X’, t’) à take value of max(timestamp)

#DevoxxFR

Quelles applications ?

22

Systèmes "eventually consistent"

Compteurs distribués Graphes orientés a-cycliques Shopping Cart

#DevoxxFR

Quelques implémentations

23

Cassandra Last Write Win

Riak

GearPump RealTime Streaming Engine (LightBend)

SoundCloud Roshi

#DevoxxFR

Cassandra LWW

H

A

E

D

B C

G F

coordinateur

INSERT/UPDATE

1

2 3

(X, t1)

(X, t1)

(X, t1)

X

#DevoxxFR

Cassandra LWW

H

A

E

D

B C

G F

1

2 3 (X, t1)(X, t1)

(X, t1)

coordinateur

INSERT/UPDATEY

(Y, t2)

#DevoxxFR

Cassandra LWW

H

A

E

D

B C

G F

coordinateur

SELECT

1

2 3

(X, t1)(Y, t2)

(X, t1) Y

#DevoxxFR

Cassandra LWW Et si t1 == t2 ? (précision timestamp à la ms) 

Les DELETE sont prioritaires sur les INSERT/UPDATE

Comparer les valeurs par l’ordre de leur type (String, Date …) et prendre la valeur la plus élevée

#DevoxxFR

Et si t1 == t2 ? (précision timestamp à la ms) 

Les DELETE sont prioritaires sur les INSERT/UPDATE

Comparer les valeurs par l’ordre de leur type (String, Date …) et prendre la valeur la plus élevée

Cette règle est-elle ? - commutative - associative - idempotente

Cassandra LWW

#DevoxxFR

Cassandra LWW Associativité [("toto", t1), ("titi", t1)], ("tata",t1) à [("toto", t1), ("tata",t1)] à ("toto", t1)  ("toto", t1), [("titi", t1), ("tata",t1)] à [("toto", t1), ("titi",t1)] à ("toto", t1)

Commutativité ("toto", t1), ("tata",t1) à ("toto", t1) ("tata", t1), ("toto",t1) à ("toto", t1) Idempotence ("toto", t1), ("toto",t1) à ("toto", t1)

#DevoxxFR

Q & R

! "

#DevoxxFR

RAMP Transactions Peter Bailis – 2014

#DevoxxFR

Le défi

32

Dans un système distribué, définir un algorithme

garantissant des lectures atomiques sur des opérations multi-partitions

#DevoxxFR

Le défi

33

Dans un système distribué, définir un algorithme

garantissant des lectures atomiques sur des opérations multi-partitions

#DevoxxFR

Le défi

34

Dans un système distribué, définir un algorithme

garantissant des lectures atomiques sur des opérations multi-partitions

Pas de garantie d’isolation ou d’écriture atomique

#DevoxxFR

Le défi

35

Dans un système distribué, définir un algorithme

garantissant des lectures atomiques sur des opérations multi-partitions

#DevoxxFR

Solutions existantes

36

Lock global Multi-version concurrency control Optimistic concurrency control (Google F1)

#DevoxxFR

Un peu de théorie

37

Serializability

Repeatable Read

Cursor Stability

Read Commited

Read Uncommited

Snapshot Isolation Linearizability

Causal

PRAM (Pipelined RAM)

RYW (Read Your Write)

Eventual Consistency

#DevoxxFR

Un peu de théorie

38

Serializability

Repeatable Read

Cursor Stability

Read Commited

Read Uncommited

Snapshot Isolation Linearizability

Causal

PRAM (Pipelined RAM)

RYW (Read Your Write)

Eventual Consistency

Coordination synchrone

Sans Coordination

#DevoxxFR

Un peu de théorie

39

Serializability

Repeatable Read

Cursor Stability

Read Commited

Read Uncommited

Snapshot Isolation Linearizability

Causal

PRAM (Pipelined RAM)

RYW (Read Your Write)

Eventual Consistency

Coordination synchrone

Sans Coordination

RAMP Transactions

#DevoxxFR

Read Atomic Multi-Partitions Transaction

Fournit une "visibilité atomique"

☞ Soit toutes les mises à jour d’une transaction sont visibles, soit aucune ne l’est

RAMP Transaction

40

#DevoxxFR

Visibilité atomique par l’exemple

41

P1 P2

WRITE X = 1

WRITE Y = 1

READ X = 1

READ Y = 1

READ X = ∅

READ Y = ∅

Ou

#DevoxxFR

Visibilité atomique par l’exemple

42

P1 P2

WRITE X = 1

WRITE Y = 1

READ X = 1

READ Y = 1

READ X = ∅

READ Y = ∅

Ou

#DevoxxFR

Idépendance de Partition ☞ les clients n’ont besoin de contacter que les partitions impliquées dans la transaction Idépendance de Synchronisation ☞ la transaction d’un client ne peut bloquer les autres clients. ☞ si le client peut accéder aux partitions de la transaction, la transaction sera réussie à terme.

Garanties RAMP Transaction

43

#DevoxxFR

2PC avec méta-données + multi-versioning limité

Implémentation

44

#DevoxxFR

RAMP – Fast (Prepare)

45

Writer P1 P2

WRITE <X = 1,t1, {Y}>

Data=[ ], lastcommit=[ ] Data=[ ], lastcommit=[ ] WRITE X = 1

WRITE Y = 1

Prepare Data=[<X = 1,t1, {Y}>]

WRITE <Y = 1,t1, {X}>

Prepare Data=[<Y = 1,t1, {X}>]

#DevoxxFR

RAMP – Fast (Prepare)

46

Writer P1 P2 Data=[<Y = 1,t1, {X}>],

lastcommit=[ ] Data=[<X = 1,t1, {Y}>],

lastcommit=[ ]

Prepared

Prepared

#DevoxxFR

RAMP – Fast (Commit)

47

Writer P1 P2

t1

Commit lastcommit=[<X,t1>]

Commit

Data=[<Y = 1,t1, {X}>] Data=[<X = 1,t1, {Y}>]

t1 lastcommit=[<Y,t1>]

#DevoxxFR

RAMP – Fast (Commit)

48

Writer P1 P2 Data=[<Y = 1,t1, {X}>],

lastcommit=[<Y,t1>] Data=[<X = 1,t1, {Y}>],

lastcommit=[<X,t1>]

Committed

Committed

#DevoxxFR

RAMP – Fast (Get)

49

Reader P1 P2

(X, ∅)

Get lastcommit=[ <X,t1>]

Get

Data=[<Y = 1,t1, {X}>] Data=[<X = 1,t1, {Y}>]

(Y, ∅)

lastcommit=[ <Y,t1>]

#DevoxxFR

RAMP – Fast (Get)

50

Reader P1 P2

<X = 1,t1, {Y}>

lastcommit=[ <X,t1>]

Data=[<Y = 1,t1, {X}>] Data=[<X = 1,t1, {Y}>]

<Y = 1,t1, {X}>

lastcommit=[ <Y,t1>]

Max(t1, t1) = t1 Xt1 = 1 Yt1 = 1 ✔ ︎

#DevoxxFR

RAMP – Fast (Read & Write)

51

Writer1 P1 P2

WRITE <X = 1,t1, {Y}>

Data=[ ], lastcommit=[ ] Data=[ ], lastcommit=[ ] WRITE X = 1

WRITE Y = 1

Prepare Data=[<X = 1,t1, {Y}>]

WRITE <Y = 1,t1, {X}>

Prepare Data=[<Y = 1,t1, {X}>]

#DevoxxFR

RAMP – Fast (Read & Write)

52

Writer1 P1 P2 Data=[<Y = 1,t1, {X}>],

lastcommit=[ ] Data=[<X = 1,t1, {Y}>],

lastcommit=[ ]

Prepared

Prepared

#DevoxxFR

RAMP – Fast (Read & Write)

53

Writer1 P1 P2

t1

Commit lastcommit=[<X,t1>]

Data=[<Y = 1,t1, {X}>] Data=[<X = 1,t1, {Y}>]

lastcommit=[]

Reader1

(X, ∅)

Get Get (Y, ∅)

<X = 1,t1, {Y}>

<Y = ∅, 0>

lastCommit(X) = t1

lastCommit(Y) = 0

#DevoxxFR

RAMP – Fast (Read & Write)

54

Writer1 P1 P2

lastcommit=[<X,t1>]

Data=[<Y = 1,t1, {X}>] Data=[<X = 1,t1, {Y}>]

lastcommit=[]

Reader1

Max(t1, 0) = t1 Xt1 = 1 ,Yt1 = ? Get

<Y = 1,t1, {X}>

(Y, t1) Lookup t1 from Data

Max(t1, 0) = t1 Xt1 = 1,Yt1 = 1 ✔ ︎

Commit t1 lastcommit=[<Y,t1>]

#DevoxxFR

RAMP – Fast (Read & Write)

55

Writer1 P1 P2

lastcommit=[<X,t1>]

Data=[<Y = 1,t1, {X}>] Data=[<X = 1,t1, {Y}>]

lastcommit=[]

Reader1

Max(t1, 0) = t1 Xt1 = 1 ,Yt1 = ? Get

<Y = 1,t1, {X}>

(Y, t1) Lookup t1 from Data

Max(t1, 0) = t1 Xt1 = 1,Yt1 = 1 ✔ ︎

Commit t1 lastcommit=[<Y,t1>]

Si je vois une partition validée, j e p e u x v o i r t o u t e s l e s partitions liées, validées avec le même timestamp ! (Tout)

#DevoxxFR

RAMP – Fast (Read & Write)

56

Writer1 P1 P2

lastcommit=[]

Data=[<Y = 1,t1, {X}>] Data=[<X = 1,t1, {Y}>]

lastcommit=[]

Reader1

(X, ∅)

Get Get (Y, ∅)

<X = ∅, 0>

<Y = ∅, 0>

lastCommit(X) = O

lastCommit(Y) = 0

#DevoxxFR

RAMP – Fast (Read & Write)

57

Writer1 P1 P2

lastcommit=[]

Data=[<Y = 1,t1, {X}>] Data=[<X = 1,t1, {Y}>]

lastcommit=[]

Reader1

(X, ∅)

Get Get (Y, ∅)

<X = ∅, 0>

<Y = ∅, 0>

lastCommit(X) = O

lastCommit(Y) = 0

Si aucune partition n’est encore validée, toutes les partitions liées retournent leur ancienne valeur ! (Rien)

#DevoxxFR

RAMP – Fast (Cas d’erreur)

58

#DevoxxFR

RAMP – Fast (Cas d’erreur)

59

Le client tombe après commit(X, t1)

☞ processus de maintenance pour valider les autres partitions pas encore validées (force-commit)

Le client tombe après le dernier prepare

☞ processus de maintenance pour nettoyer Data[ ] après un timeout

#DevoxxFR

RAMP – Fast (Cas d’erreur)

60

Le client fait un rollback(ts) après le dernier prepare

☞ enlever les valeurs écrites à ts dans Data [ ]

#DevoxxFR

RAMP – Fast (Coût Disque)

61

La taille des méta-données est linéairement proportionnelle au nombre de partitions impliquées dans la transaction

0

1

2

3

4

5

6

7

8

Taille méta données

1 2 3 4 5 6 7 8

Nb de partitions

#DevoxxFR

RAMP – Fast Résumé

62

Algo RTT écriture RTT lecture (au mieux) RTT lecture (au pire) Taille méta-données RAMP – Fast 2 1 2 O(#partitions)

#DevoxxFR

RAMP – Small (Prepare)

63

Writer P1 P2

WRITE <X = 1,t1>

Data=[ ], lastcommit=[ ] Data=[ ], lastcommit=[ ] WRITE X = 1

WRITE Y = 1

Prepare Data=[<X = 1,t1]

WRITE <Y = 1,t1>

Prepare Data=[<Y = 1,t1>]

#DevoxxFR

RAMP – Small (Prepare)

64

Writer P1 P2 Data=[<Y = 1,t1>],

lastcommit=[ ] Data=[<X = 1,t1>],

lastcommit=[ ]

Prepared

Prepared

🔍 🔍

#DevoxxFR

RAMP – Small (Commit)

65

Writer P1 P2

t1

Commit lastcommit=[<X,t1>]

Commit

Data=[<Y = 1,t1>] Data=[<X = 1,t1]

t1 lastcommit=[<Y,t1>]

#DevoxxFR

RAMP – Small (Commit)

66

Writer P1 P2 Data=[<Y = 1,t1>], lastcommit=[<Y,t1>]

Data=[<X = 1,t1>], lastcommit=[<X,t1>]

Committed

Committed

#DevoxxFR

RAMP – Small (Get round1)

67

Reader P1 P2

(X, ∅)

Get

Get (Y, ∅)

lastcommit=[ <X,t1>]

Data=[<Y = 1,t1>, <Y = 2,t2>]

Data=[<X = 1,t1>, <X = 2, t2>]

lastcommit=[ <Y,t2>] 🔍 🔍

#DevoxxFR

RAMP – Small (Get round1)

68

Reader P1 P2

t1

lastcommit=[ <X,t1>]

Data=[<Y = 1,t1>, <Y = 2,t2>]

Data=[<X = 1,t1>, <X = 2, t2>]

t2

lastcommit=[ <Y,t2>]

#DevoxxFR

RAMP – Small (Get round2)

69

Reader P1 P2

(X, {t1,t2})

Get

Get (Y, {t1,t2})

lastcommit=[ <X,t1>]

Data=[<Y = 1,t1>, <Y = 2,t2>]

Data=[<X = 1,t1>, <X = 2, t2>]

lastcommit=[ <Y,t2>]

#DevoxxFR

RAMP – Small (Get round2)

70

Reader P1 P2

lastcommit=[ <X,t1>]

Data=[<Y = 1,t1>, <Y = 2,t2>]

Data=[<X = 1,t1>, <X = 2, t2>]

lastcommit=[ <Y,t2>]

tmatch= {t | t∈(t1, t2)∧X∈Data return X | tX = max(tmatch)

tmatch= {t | t∈(t1, t2)∧Y∈Data return Y | tY = max(tmatch)

X = 2

Y = 2

#DevoxxFR

RAMP – Small Résumé

71

Algo RTT écriture RTT lecture (au mieux) RTT lecture (au pire) Taille méta-données RAMP – Fast 2 1 2 O(#partitions)

RAMP – Small 2 2 2 0(1)

#DevoxxFR

RAMP – Small Résumé

72

Algo RTT écriture RTT lecture (au mieux) RTT lecture (au pire) Taille méta-données RAMP – Fast 2 1 2 O(#partitions)

RAMP – Small 2 2 2 0(1)

Peut-on faire mieux ?

#DevoxxFR

Bloom Filter Résumé

73

1 0 0 1* 0 0 1 0 1 1

Écriture X Y

Lecture Z ?

Faux positifsVrais négatifs

#DevoxxFR

RAMP – Hybrid (Prepare)

74

Writer P1 P2

WRITE <X = 1,t1, BFY>

Data=[ ], lastcommit=[ ] Data=[ ], lastcommit=[ ] WRITE X = 1

WRITE Y = 1

Prepare Data=[<X = 1,t1, BFY>]

WRITE <Y = 1,t1, BFX>

Prepare Data=[<Y = 1,t1, BFX>]

#DevoxxFR

RAMP – Hybrid (Get)

75

Reader P1 P2

(X, ∅)

Get lastcommit=[ <X,t1>]

Get

Data=[<Y = 1,t1, BFX>] Data=[<X = 1,t1, BFY>]

(Y, ∅)

lastcommit=[ <Y,t1>]

#DevoxxFR

RAMP – Hybrid (Get)

76

Reader P1 P2

<X = 1,t1, BFY>

lastcommit=[ <X,t1>]

Data=[<Y = 1,t1, BFX>] Data=[<X = 1,t1, BFY>]

<Y = 1,t1, BFX>

lastcommit=[ <Y,t1>]

Max(t1, t1) = t1 Xt1 = 1 Yt1 = 1 ✔ ︎

#DevoxxFR

RAMP – Hybrid (Get)

77

Reader P1 P2

<X = 2,t2, BFY>

lastcommit=[ <X,t1>]

Data=[<Y = 1,t1, BFX>, <Y = 2,t2, BFX>]

Data=[<X = 1,t1, BFY>, <X = 2,t2, BFY>]

<Y = 1,t2, BFX>

lastcommit=[ <Y,t2>]

t2 > t1 ∧ X ∈ BFX ?

(X, t2)

Get

#DevoxxFR

RAMP – Hybrid (Get)

78

Reader P1 P2

<X = 2,t2, BFY>

lastcommit=[ <X,t1>]

Data=[<Y = 1,t1, BFX>, <Y = 2,t2, BFX>]

Data=[<X = 1,t1, BFY>, <X = 2,t2, BFY>]

<Y = 1,t2, BFX>

lastcommit=[ <Y,t2>]

t2 > t1 ∧ X ∈ BFX ?

(X, t2)

Get Faux positif possible!!!

#DevoxxFR

RAMP – Hybrid Résumé

79

Algo RTT écriture RTT lecture (au mieux) RTT lecture (au pire) Taille méta-données RAMP – Fast 2 1 2 O(#partitions)

RAMP – Small 2 2 2 0(1)RAMP – Hybrid 2 1 + 𝜀 2 Taille Bloom Filter

𝜀 = taux de faux positif Proportionnel à la taille

du Bloom Filter

#DevoxxFR

Détails d’implémentation

80

Garbage collector

☞ limiter une transaction à N secondes. Effacer les versions anciennes après N secondes

Gestion du timestamp

☞ mécanisme pour garantir une croissance monotone stricte

#DevoxxFR

Détails d’implémentation

81

Réplication

☞ Attendre un ack pour N réplicas d’une partition (N configurable)

Tâche de maintenance

☞ pour forcer un commit sur les partitions impliquées dans une transaction ayant au moins 1 partition validée

#DevoxxFR

Quelles applications ?

82

Intégrité et contraintes de clés étrangères

Index secondaires globaux Vues matérialisées

#DevoxxFR

Quelques implémentations

83

#DevoxxFR

Quelques implémentations

84

#DevoxxFR

Q & R

! "

#DevoxxFR

Merci

86

@doanduyhai

[email protected]

http://academy.datastax.com/