Distributed Elixir

Distributed Elixir

Presentation about some of the tools for distributed programming in Elixir

373dd7c51433dc3c38436dcfdec79cdc?s=128

Maciej Kaszubowski

July 07, 2018
Tweet

Transcript

  1. It’s scary out there

  2. Organisational Matters

  3. None
  4. We’re 1 year old!

  5. Summer break (probably)

  6. We’re looking for speakers!

  7. It’s scary out there Distributed Systems in Elixir Poznań Elixir

    Meetup #8
  8. None
  9. Pid 1 Pid 2

  10. Pid 1 Pid 2 Node A Node B

  11. The basics

  12. iex --name n1@127.0.0.1 --cookie cookie -S mix

  13. Node.connect(:’n1@127.0.0.1')

  14. (DEMO)

  15. #PID<0.94.0>

  16. #PID<0.94.0> node identifier (relative to current node)

  17. #PID<0.94.0> node identifier (relative to current node) 0 =a local

    process
  18. #PID<0.94.0> Process id node identifier (relative to current node)

  19. How does it work?

  20. Pid 1 Node A Pid 2 Node B

  21. Pid 1 Node A Pid 2 Node B TCP Connection

  22. send(pid2, msg) Pid 1 Node A Pid 2 Node B

    TCP Connection
  23. send(pid2, msg) Pid 1 Node A Pid 2 Node B

    destination_node = node(pid) TCP Connection
  24. send(pid2, msg) Pid 1 Node A Pid 2 Node B

    destination_node = node(pid) :erlang.term_to_binary(msg) TCP Connection
  25. send(pid2, msg) Pid 1 Node A Pid 2 Node B

    destination_node = node(pid) :erlang.term_to_binary(msg) TCP Connection
  26. send(pid2, msg) Pid 1 Node A Pid 2 Node B

    destination_node = node(pid) :erlang.term_to_binary(msg) TCP Connection :erlang.binary_to_term(encode)
  27. send(pid2, msg) Pid 1 Node A receive msg Pid 2

    Node B destination_node = node(pid) :erlang.term_to_binary(msg) TCP Connection :erlang.binary_to_term(encode)
  28. Distributed Systems?

  29. Distributed Systems? Solved!

  30. Well, not exactly…

  31. Difficulties

  32. Node A Node B

  33. Node A Node B Node C

  34. Node A Node B Node C Node D

  35. None
  36. A lot of messages

  37. us-east-1 us-west-2

  38. 8 fallacies of distributed computing

  39. fallacies of distributed computing 1. The network is reliable 2.

    Latency is zero 3. Bandwidth is infinite 4. The network is secure 5. Topology doesn’t change 6. The is one administrator 7. Transport cost is zero 8. The network is homogenous
  40. CAP THEOREM

  41. CAP THEOREM us-west-2 us-east-1

  42. CAP THEOREM us-west-2 us-east-1 Set X=5

  43. CAP THEOREM us-west-2 us-east-1 Set X=5 Read X

  44. CAP THEOREM us-west-2 us-east-1 Set X=5 Set X = 7

  45. Consistency or Availability (under network partition)

  46. Consistency or Speed In practice

  47. Guarantees

  48. Pid 1 Pid 2 Pid3 Guarantees m1, m2, m3 m4,

    m5, m6 send(pid2, m1) send(pid2, m2) send(pid2, m3) send(pid2, m4) send(pid2, m5) send(pid2, m6)
  49. Pid 1 Pid 2 Pid3 Guarantees m1, m2, m3 m4,

    m5, m6 send(pid2, m1) send(pid2, m2) send(pid2, m3) send(pid2, m4) send(pid2, m5) send(pid2, m6) Ordering between two processes is preserved
  50. Pid 1 Pid 2 Pid3 Guarantees m4, m5, m6 send(pid2,

    m1) send(pid2, m2) send(pid2, m3) send(pid2, m4) send(pid2, m5) send(pid2, m6) m1, m2, m3 Delivery is not guaranteed
  51. Pid 1 Pid 2 Pid3 Guarantees m1, m2, m3 m4,

    m5, m6 send(pid2, m1) send(pid2, m2) send(pid2, m3) send(pid2, m4) send(pid2, m5) send(pid2, m6) Ordering between different processes is not guaranteed
  52. [m1, m2, m3, m4, m5, m6]

  53. [m1, m2, m3, m4, m5, m6] [m4, m5, m6, m1,

    m2, m3]
  54. [m1, m2, m3, m4, m5, m6] [m4, m5, m6, m1,

    m2, m3] [m1, m4, m2, m5, m3, m6]
  55. [m1, m2, m3, m4, m5, m6] [m4, m5, m6, m1,

    m2, m3] [m1, m4, m2, m5, m3, m6] [m1, m2, m3]
  56. [m1, m2, m3, m4, m5, m6] [m4, m5, m6, m1,

    m2, m3] [m1, m4, m2, m5, m3, m6] [m1, m2, m3] [m1, m3, m5, m6]
  57. [m1, m2, m3, m4, m5, m6] [m4, m5, m6, m1,

    m2, m3] [m1, m4, m2, m5, m3, m6] [m1, m2, m3] [m1, m3, m5, m6] []
  58. [m1, m2, m3, m4, m5, m6] [m4, m5, m6, m1,

    m2, m3] [m1, m4, m2, m5, m3, m6] [m1, m2, m3] [m1, m3, m5, m6] [] [m1, m3, m2, m4, m5, m6]
  59. [m1, m2, m3, m4, m5, m6] [m4, m5, m6, m1,

    m2, m3] [m1, m4, m2, m5, m3, m6] [m1, m2, m3] [m1, m3, m5, m6] [] [m1, m3, m2, m4, m5, m6] [M3, M3]
  60. Phoenix Request A User Logged In

  61. Phoenix Request A Phoenix Request B User Logged In User

    Logged OUT
  62. Phoenix Request A Phoenix Request B User Logged In User

    Logged OUT This Can arrive first
  63. Unfortunately, things tend to work fine locally

  64. The Tools

  65. :global

  66. Pid 1 Node A Node B Pid 2

  67. Pid 1 Node A Node B Pid 2 :global.register_name(“global”, self())

  68. Pid 1 Node A Node B Pid 2 :global.register_name(“global”, self())

    Register PId1 as “global”
  69. Pid 1 Node A Node B Pid 2 :global.register_name(“global”, self())

    Register PId1 as “global” Sure
  70. Pid 1 Node A Node B Pid 2 :global.register_name(“global”, self())

    Register PId1 as “global” Sure :global.whereis_name(“global”) = pid1
  71. Pid 1 Node A Node B Pid 2 :global.register_name(“global”, self())

    :global.register_name(“global”, self()) ?
  72. (DEMO)

  73. :global • single process registration (if everything works OK) •

    Favours availability over consistency • Information stored locally (reading is fast) • Registration is blocking (may be slow)
  74. :PG2

  75. Pid1 Pid3 Pid2 [] [] []

  76. Pid1 Pid3 Pid2 :pg2.create(“my_group”) [] [] []

  77. Pid1 Pid3 Pid2 [] [] [] join join :pg2.join(“my_group”, self()

  78. Pid1 Pid3 Pid2 [] [pid1] [] Monitor Monitor :pg2.join(“my_group”, self()

  79. Pid1 Pid3 Pid2 [pid1] [pid1] [pid1] Monitor Monitor :pg2.join(“my_group”, self()

  80. Pid1 Pid3 Pid2 [pid1] [pid1] [pid1]

  81. Pid1 Pid3 Pid2 :pg2.join(“my_group”, self() [pid1] [pid1, pid2] [pid1]

  82. Pid1 Pid3 Pid2 join :pg2.join(“my_group”, self() join [pid1, pid2] [pid1,

    pid2] [pid1, pid2]
  83. Pid1 Pid3 Pid2 [pid1] [pid2] [pid1]

  84. Pid1 Pid3 Pid2 [pid1] [pid2] [pid1]

  85. Pid1 Pid3 Pid2 [pid1] [pid2] [pid1]

  86. Pid1 Pid3 Pid2 [pid1, pid2] [pid1, pid2] [pid1, pid2]

  87. It will heal, but the state in inconsistent for some

    time
  88. What does it matter?

  89. Node A Pg2 Pg2 Pg2 Node B Node C

  90. Node A Pg2 Pg2 Pg2 Node B Node C Phoenix

    Channels
  91. Node A Pg2 Pg2 Pg2 Node B Node C Phoenix

    Presence
  92. Node A Pg2 Pg2 Pg2 Node B Node C Phoenix

    Channels
  93. :pg2 • Process groups • Favours availability over consistency •

    Information stored locally (reading is fast) • Registration is blocking (may be slow)
  94. Strongly consistent Solutions

  95. Strongly consistent Solutions • Consensus - Raft, Paxos, ZAB •

    Two-phase commit/THree-phase commit (2PC/3PC) • Read/Write quorums • Single database as a source of truth
  96. Summary

  97. Distributed Systems

  98. Well, not exactly…

  99. Asynchronous messages Distributed systems are all about

  100. Really, there’s no magic

  101. Just asynchronous messages between nodes

  102. Just asynchronous messages between nodes & node failures

  103. Just asynchronous messages between nodes & node failures & Communication

    failures
  104. Just asynchronous messages between nodes & node failures & Communication

    failures & Network partitions
  105. Tradeoffs Distributed systems are all about

  106. Where to go next

  107. Worth looking at • Riak_core • RAFT • Two-Phase Commit

    (2PC) / Three-Phase Commit (3PC) • CRDTs • LASP and Partisan
  108. Free online (click!) Elixir / Erlang

  109. Free PDF (Click!) Distributed Systems

  110. Theory (The hard stuff)

  111. • https://raft.github.io/ (Raft Consensus) • http://learnyousomeerlang.com/distribunomicon • https://www.rgoarchitects.com/Files/fallacies.pdf (Fallacies of

    distributed computing) • https://dzone.com/articles/better-explaining-cap-theorem (CAP Theorem) • https://medium.com/learn-elixir/message-order-and-delivery-guarantees-in-elixir- erlang-9350a3ea7541 (Elixir message delivery guarantees) • https://lasp-lang.readme.io/ (LASP) • https://arxiv.org/pdf/1802.02652.pdf (Partisan Paper) • https://bravenewgeek.com/tag/three-phase-commit/ (3PC)
  112. We’re looking for speakers!

  113. Thank You! Poznań Elixir Meetup #8