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
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
【CEDEC2026】ゲームシナリオライターを支援するAIツール開発の実践 ― 設計とプロンプトの工夫 ―
cygames
PRO
1
830
FPGAが実現する遠方宇宙の高空間分解能天体撮影 -大型地上望遠鏡の視力を補正する「補償光学」とは?-
komei_mt
0
240
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
4
24k
強化学習「理論」入門
enakai00
3
3.6k
Webアクセシビリティ入門 2026
recruitengineers
PRO
3
560
LLM・AIエージェントシステムベストプラクティス
shibuiwilliam
6
1.2k
侵入は突然に 〜 IoTマルウェアと悪用される家庭の機器 ~ / When Intrusion Strikes: IoT Malware and the Abuse of Home Devices
nttcom
0
1.6k
サイバー捜査員研修(後半)
nomizone
1
870
AIコーディングの次。コードレビューと理解負荷を解消して組織の開発生産性を高める
moongift
PRO
2
2.5k
老害フォレンジッカーはAI羊の夢を見るか?
tadmaddad
0
320
変化の早いClaude Codeを 書籍に落とし込む
oikon48
7
1.4k
Agent 時代の Kaggle 展望 / kaggle-in-the-agentic-era
upura
1
710
Featured
See All Featured
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
760
Noah Learner - AI + Me: how we built a GSC Bulk Export data pipeline
techseoconnect
PRO
0
380
What’s in a name? Adding method to the madness
productmarketing
PRO
24
4.1k
HTML-Aware ERB: The Path to Reactive Rendering @ RubyCon 2026, Rimini, Italy
marcoroth
3
430
The Mindset for Success: Future Career Progression
greggifford
PRO
0
440
SEO Brein meetup: CTRL+C is not how to scale international SEO
lindahogenes
1
2.8k
A Modern Web Designer's Workflow
chriscoyier
698
190k
The Curse of the Amulet
leimatthew05
2
14k
Building a A Zero-Code AI SEO Workflow
portentint
PRO
0
660
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
630
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.3k
Exploring the Power of Turbo Streams & Action Cable | RailsConf2023
kevinliebholz
37
6.5k
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