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

CRDTs - The science behind Phoenix Presence

CRDTs - The science behind Phoenix Presence

Maciej Kaszubowski

May 25, 2017
Tweet

More Decks by Maciej Kaszubowski

Other Decks in Programming

Transcript

  1. Server
    Node 1
    Server
    Node 2

    View full-size slide

  2. Node A
    Node B
    [User]
    [User]
    [User]
    []
    [] [User]
    User connects
    User disconnects

    View full-size slide

  3. There's no global time

    View full-size slide

  4. Node A
    Node B
    [User]
    [User]
    [User]
    []
    [] [User]
    User connects
    User disconnects

    View full-size slide

  5. Node A
    Node B
    [User]
    [User]
    [User]
    []
    []
    [User]
    User connects
    User disconnects

    View full-size slide

  6. Node A Node B

    View full-size slide

  7. P.track(self, "users", "U1", %{})

    View full-size slide

  8. P.track(self, "users", "U1", %{})
    P.list("users")
    %{"U1"  %{metas: [%{phx_ref: "…"}]}}

    View full-size slide

  9. P.track(self, "users", "U1", %{})
    P.list("users")
    P.track(self, "users", "U2", %{})
    %{"U1"  %{metas: [%{phx_ref: "…"}]}}

    View full-size slide

  10. P.track(self, "users", "U1", %{})
    P.list("users")
    P.track(self, "users", "U2", %{})
    P.list("users")
    %{"U1"  %{metas: [%{phx_ref: "…"}]},
    "U2"  %{metas: [%{phx_ref: "…"}]}}
    %{"U1"  %{metas: [%{phx_ref: "…"}]}}

    View full-size slide

  11. P.track(self, "users", "U1", %{})
    P.list("users")
    P.track(self, "users", "U2", %{})
    P.list("users")
    %{"U1"  %{metas: [%{phx_ref: "…"}]},
    "U2"  %{metas: [%{phx_ref: "…"}]}}
    P.track(self, "users", "U1", %{})
    P.untrack(self, "users", "U1")
    %{"U1"  %{metas: [%{phx_ref: "…"}]}}

    View full-size slide

  12. P.track(self, "users", "U1", %{})
    P.list("users")
    P.track(self, "users", "U2", %{})
    P.list("users")
    %{"U1"  %{metas: [%{phx_ref: "…"}]},
    "U2"  %{metas: [%{phx_ref: "…"}]}}
    P.track(self, "users", "U1", %{})
    P.untrack(self, "users", "U1")
    P.list("users")
    %{"U1"  %{metas: [%{phx_ref: "…"}]},
    "U2"  %{metas: [%{phx_ref: "…"}]}}
    P.list("users")
    %{"U1"  %{metas: [%{phx_ref: "…"}]},
    "U2"  %{metas: [%{phx_ref: "…"}]}}
    %{"U1"  %{metas: [%{phx_ref: "…"}]}}

    View full-size slide

  13. CRDTs
    The science behind Phoenix Presence
    Maciej Kaszubowski

    View full-size slide

  14. Conflict-free
    Replicated
    Data
    Type

    View full-size slide

  15. Alternatives

    View full-size slide

  16. • Single source of truth (DB)
    • Consensus algorithm
    • Resolving conflicts manually

    View full-size slide

  17. Eventually consistent
    Highly available
    Easy to use

    View full-size slide

  18. Eventually consistent
    Highly available
    Easy to use
    Hard to create :(

    View full-size slide

  19. 1. Commutative
    2. Associative
    3. Idempotent
    x y = y x
    (x y) z = x (y z)
    x x = x

    View full-size slide

  20. Server
    Node 1
    Server
    Node 2
    Server
    Node 3

    View full-size slide

  21. Client
    Client Client
    Client
    Client
    Client
    Client
    Client
    Client
    Server

    View full-size slide

  22. Node A
    Node B
    +5
    5
    8
    -2
    3
    +5
    User connects
    User disconnects
    0
    0
    5 3
    8

    View full-size slide

  23. Node A
    Node B
    +5
    5
    8
    -2
    8
    +5
    User connects
    User disconnects
    0
    0
    5 3
    13
    10

    View full-size slide

  24. G-Counter
    Grow-only counter

    View full-size slide

  25. Node 2:
    3
    Value=8
    Node 1:
    5
    Node 3:
    1
    Merge

    View full-size slide

  26. Node 2:
    3
    Value=9
    Node 1:
    6
    Node 3:
    1
    +1
    Merge

    View full-size slide

  27. PN-Counter
    Positive-Negative Counter

    View full-size slide

  28. Node 2:
    P=2 N=2
    Value=7
    Node 1:
    P=5 N=2
    Node 3:
    P=4 N=0
    3 0 4
    Merge

    View full-size slide

  29. Node 2:
    P=2 N=2
    Value=6
    Node 1:
    P=5 N=3
    Node 3:
    P=4 N=0
    2 0 4
    +1
    Merge

    View full-size slide

  30. Node 2:
    P=2 N=2
    Value=8
    Node 1:
    P=5 N=3
    Node 3:
    P=6 N=0
    2 0 6
    +2
    +1
    Merge

    View full-size slide

  31. Node A
    Node B
    [User]
    [User]
    [User]
    []
    []
    [User]
    User connects
    User disconnects

    View full-size slide

  32. G-Set
    Grow-only set

    View full-size slide

  33. Node 2:
    [1,2]
    Value=[1,2,3,4]
    Node 1:
    [1]
    Node 3:
    [3,4]
    Merge

    View full-size slide

  34. Node 2:
    [1,2]
    Value=[1,2,3,4,5]
    Node 1:
    [1,5]
    Node 3:
    [3,4]
    Merge

    View full-size slide

  35. 2P-Set
    Two-phase set

    View full-size slide

  36. Node 2:
    [1,2],[]
    Value=[1,2,3,4]
    Node 1:
    [1],[]
    Node 3:
    [3,4],[]
    Merge

    View full-size slide

  37. Node 2:
    [1,2],[]
    Value=[1,2,3,4]
    Node 1:
    [1],[]
    Node 3:
    [3,4],[]
    Merge
    G-Set
    for adds

    View full-size slide

  38. Node 2:
    [1,2],[]
    Value=[1,2,4]
    Node 1:
    [1],[]
    Node 3:
    [3,4],[3]
    Merge G-Set
    for removals

    View full-size slide

  39. Elements cannot be re-added

    View full-size slide

  40. Node A
    Node B
    [ ]
    Add
    Remove
    [1]
    [ ]
    [1]

    View full-size slide

  41. Node A
    Node B
    [ ] [1]
    Add
    Remove
    [1] [1]
    [ ]
    [1]
    [ ]
    [1]

    View full-size slide

  42. Node A
    Node B
    [ ] [1]
    Add
    Remove
    [1] [1]
    [ ]
    [1]
    [ ]
    [1]

    View full-size slide

  43. Node A
    Node B
    [ ] [1]
    [1]
    Add
    Remove
    [1] [1] [1]
    [ ] [1]
    [1] [1]
    [ ]
    [1]

    View full-size slide

  44. OR-Set
    Observed-remove set

    View full-size slide

  45. Node A
    Node B
    [ ]
    Add
    Remove
    [{A,1}]
    [ ]
    [{A,1}]

    View full-size slide

  46. Node A
    Node B
    [ ] [ ]
    Add
    Remove
    [{A,1}] [{A,1}]
    [ ] [ ]
    [{A,1}] [{A,1}, ]

    View full-size slide

  47. Node A
    Node B
    [ ] [ 1 ]
    Add
    Remove
    [{A,1}] [{A,1}]
    [ ] [ ]
    [{A,1}] [{A,1},{A,2}]

    View full-size slide

  48. Node A
    Node B
    [ ] [ 1 ]
    Add
    Remove
    [{A,1}] [{A,1}]
    [ ] [ ]
    [{A,1}] [{A,1},{A,2}]

    View full-size slide

  49. Node A
    Node B
    [ ] [ 1 ]
    Add
    Remove
    [{A,1}] [{A,1}]
    [ ] [ ]
    [{A,1}] [{A,1},{A,2}]
    [ 1 ]
    [{A,1},{A,2}]
    [{A,1},{A,2}]
    [ 1 ]

    View full-size slide

  50. Node A
    Node B
    [ ] [ 1 ]
    Add
    Remove
    [{A,1}] [{A,1}]
    [ ] [ ]
    [{A,1}] [{A,1},{A,2}]
    [ 1 ]
    [{A,1},{A,2}]
    [{A,1},{A,2}]
    [ 1 ]
    [A]
    [A]

    View full-size slide

  51. Add 1000 Remove 1000 Add Remove …

    View full-size slide

  52. ORSWOT
    Observed-remove set without tombstones

    View full-size slide

  53. • Load balancing / routing
    • Mobile clients synchronisation
    • Temporary data on the servers
    • Avoiding work duplication
    • Collaborative editing

    View full-size slide

  54. lasp-lang.readme.io

    View full-size slide

  55. You're (almost) always
    designing a distributed system

    View full-size slide

  56. Think about failures

    View full-size slide

  57. Choose the correct tool
    for the job

    View full-size slide

  58. References
    • https://medium.com/@istanbul_techie/a-look-at-conflict-free-replicated-data-
    types-crdt-221a5f629e7e
    • http://basho.com/posts/technical/distributed-data-types-riak-2-0/
    • http://highscalability.com/blog/2014/10/13/how-league-of-legends-scaled-
    chat-to-70-million-players-it-t.html
    • https://hal.inria.fr/inria-00609399v1/document
    • https://developers.soundcloud.com/blog/roshi-a-crdt-system-for-
    timestamped-events

    View full-size slide