Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Scalable dist-sys from grounds up
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
udit
April 28, 2019
Technology
210
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Scalable dist-sys from grounds up
udit
April 28, 2019
More Decks by udit
See All by udit
Road to masterless multi-node distributed system in Elixir
yudistrange
0
58
Other Decks in Technology
See All in Technology
新しいVibe Codingと”自走”について
watany
5
290
LLMにもCAP定理があるという話
harukasakihara
0
300
Dario Amodi『Policy on the AI Exponential』を理解する
nagatsu
0
220
protovalidate-es を導入してみた
bengo4com
0
170
Djangoユーザが知っ得なPostgreSQL機能 - 設計の選択肢を増やす / Djang-use-PostgreSQL
soudai
PRO
1
230
Claude Code の Sandbox 機能を Anthropic Sandbox Runtime(srt) で試そう!/lets-play-anthropic-sandbox-runtime
tomoki10
1
540
就職⽀援サービスにおけるキャリアアドバイザーのシフトスケジューリング
recruitengineers
PRO
1
140
LLMと共に進化するプロセスを目指して
ymatsuwitter
13
4k
日本 Fintech 未来予測レポート 2027〜2028年(手動編集版)
8maki
0
2k
チームで進めるAI駆動アジャイル×ウォーターフォール
kumaiu
0
150
AIのReact習熟度を測る
uhyo
1
180
作って終わりにしない タイミーのセマンティックレイヤー育成の現在地
chanyou0311
4
2.2k
Featured
See All Featured
Reality Check: Gamification 10 Years Later
codingconduct
0
2.2k
Dominate Local Search Results - an insider guide to GBP, reviews, and Local SEO
greggifford
PRO
0
190
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.1k
AI in Enterprises - Java and Open Source to the Rescue
ivargrimstad
0
1.3k
Lessons Learnt from Crawling 1000+ Websites
charlesmeaden
PRO
1
1.3k
A designer walks into a library…
pauljervisheath
211
24k
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
840
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Information Architects: The Missing Link in Design Systems
soysaucechin
0
970
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
Darren the Foodie - Storyboard
khoart
PRO
3
3.4k
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.7k
Transcript
scalable dist-sys from the grounds up in Elixir
whoami udit @ nilenso
agenda why elixir/erlang under the hood build you a live
game for great good build you a better live game for greater good
why elixir / erlang
why dist-sys are hard? state computation reliability order . .
.
why elixir/erlang asynchronous message passing no sharing fault tolerance
why elixir/erlang distributed out of the box primitives for concurrency
under the hood
beam Bjorn’s erlang abstract machine bytecode ~ erlang / Elixir
/ Gleam / LFE etc
process light weight - green thread communicate via message passing
single threaded
process process control board heap stack
process garbage collection when: heap meets stack runs on process
schedule compaction vs full copy
process schedulers process queues soft pre-emptive
process defmodule RcDemo.Echo do def start() do receive do :exit
-> IO.puts("Shutting down") x -> IO.inspect(x, label: "Received Message on #{inspect(self())}: ") start() end end end
process registration noname :local :global pg2 swarm Registry (elixir)
supervisor reliability monitor other process
gen_server generic server better abstraction over state still a process
defmodule RcDemo.EchoGenServer do use GenServer def start(), do: GenServer.start(__MODULE__, nil) def init(nil), do: {:ok, %{}} def handle_cast(message, state) do IO.inspect(message, label: "Cast:") {:noreply, state} end def handle_call(message, from, state) do IO.inspect(message, label: "Call:") :timer.sleep(2000) {:reply, :called, state} end end
gen_server call GenServer.call(pid, :hi, 1000) cast GenServer.cast(pid, :hello) info send(pid,
:info)
distributed nodes fully connected mesh network heartbeat
None
a live game for great good
listener def receive_message(socket, receive_callback) do case :gen_tcp.recv(socket, 0) do {:ok,
message} -> :gen_tcp.send(socket, "Message received\n") {m, f, a} = receive_callback apply(m, f, a ++ [message]) receive_message(socket, receive_callback) _otherwise -> IO.inspect("Shutting down the socket") end end def listen(port, accept_callback) do {:ok, socket} = :gen_tcp.listen(port, [:binary, reuseaddr: true]) accept_connection(socket, accept_callback) end def accept_connection(listen_socket, accept_callback) do {:ok, accept_socket} = :gen_tcp.accept(listen_socket) spawn(fn -> {m, f, a} = accept_callback receive_callback = apply(m, f, a ++ [accept_socket]) receive_message(accept_socket, receive_callback) end) accept_connection(listen_socket, accept_callback) end
one for all defmodule RcDemo.Game.OneToAll.SingleActor do def start (port), do:
GenServer.start_link( __MODULE__, port, name: {:global, Single}) def init(port) do spawn(fn -> TcpListner.listen(port, {__MODULE__, :noop, []}) end) {:ok, %{}} end def noop(_), do: {__MODULE__, :incoming, []} def incoming(message), do: GenServer.cast(Single, {:incoming, message}) def handle_cast({:incoming, message}, state) do IO.inspect(message, label: "Received in GenServer with pid #{inspect self()}") {:noreply, state} end
one for all
one for all 1 : n single thread of execution
for all incoming message message queue build up no fault tolerance
one for one defmodule RcDemo.Game.OneToOne.Master do def start(port), do: GenServer.start_link(__MODULE__,
port, name: Master) def init(port) do spawn(fn -> TcpListner.listen(port, {__MODULE__, :new_connection, []}) end) {:ok, %{}} end def new_connection(socket) do {:ok, pid} = Worker.start(socket) {Worker, :incoming, [pid]} end end defmodule RcDemo.Game.OneToOne.Worker do def start(_socket), do: GenServer.start_link(__MODULE__, []) def init(_), do: {:ok, %{}} def incoming(pid, message), do: GenServer.cast(pid, {:incoming, message}) def handle_cast({:incoming, message}, state) do IO.inspect(message, label: "Received in Worker with pid: #{inspect self()}") {:noreply, state} end end
one for one 1 : 1 can process responses from
players faster large process queue on schedulers
n to m defmodule RcDemo.Game.Balanced.Master do def init(port) do worker_pids
= Enum.reduce(1..2, [], fn _x, acc -> {:ok, pid} = Worker.start() [pid] ++ acc end) spawn(fn -> TcpListner.listen(port,{__MODULE__, :new_connection, [[worker_pids]]}) end) {:ok, %{}} end def new_connection([worker_pids], socket) do worker_index = hash_socket(socket) worker_pid = Enum.at(worker_pids, worker_index) {Worker, :incoming, [worker_pid]} end defp hash_socket(_socket), do: :rand.uniform(2) – 1 end defmodule RcDemo.Game.Balanced.Worker do def init(_params), do: {:ok, %{}} def incoming(pid, message), do: GenServer.cast(pid, {:incoming, message}) def handle_cast({:incoming, message}, state) do IO.inspect(message, label: "Received in Worker with pid: #{inspect self()}") {:noreply, state} end end
n to m n : m shard player
None
a live game for greater good
addendum supervision
addendum differentiate processes
addendum distributed processes
addendum islands
fin
references Erlang Garbage Collection Details and Why It Matters The
beam book Discord Blog Whatsapp’s island architecture Elixir School Elixir Official Documentation Demo code repo Slides
thank you @yudistrange