Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
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
TinyGo 開発サイクルを高速化する:Go で作るエミュレータ入門
zozotech
PRO
1
740
OpenTelemetryのメトリクスをCloudWatchに送ってPromQLで見てみた
ota1022
0
150
技術的負債から考える、AI時代のエンジニアリング投資 — ビズリーチの技術的負債と向き合った経験から、変更し続けられるソフトウェアを考える/ technical-debt-con2026
visional_engineering_and_design
3
2.9k
10Xに技術的負債をもたらした「2つの境界の歪み」その構造と解消への営み
10xinc
0
1.9k
新機種発売前に見直そう!端末移行で再ログインが要るアプリ・要らないアプリは何が違うのか 〜シームレスに再開できる設計と実装〜
zozotech
PRO
0
200
バイブコーディング時代のWebアプリ開発入門~Cloud Runで学ぶセキュアなビルドとデプロイ
waiwai2111
1
130
顧客に向き合う開発組織へ。リアーキテクチャとフィーチャーチーム化で挑む組織改革
safie
0
1.9k
aws-iot-platform-architecture-use-cases.pdf
ma2shita
0
150
iOSDC Japan 2026 day1 TrackC 10:50
feedtailor
1
160
Deploying a Full-Stack Bun-Native Framework on Cloudflare Workers
7nohe
0
170
目の前の楽しいが人生を変える - コミュニティの螺旋の歩き方と楽しむコツ / change your life
soudai
PRO
4
610
事業課題から技術的負債に向き合う
sansantech
PRO
2
1.8k
Featured
See All Featured
Navigating Weather and Climate Data
rabernat
0
520
HU Berlin: Industrial-Strength Natural Language Processing with spaCy and Prodigy
inesmontani
PRO
0
700
Technical Leadership for Architectural Decision Making
baasie
3
570
Stop Working from a Prison Cell
hatefulcrawdad
274
21k
4 Signs Your Business is Dying
shpigford
187
23k
Abbi's Birthday
coloredviolet
4
10k
Marketing to machines
jonoalderson
1
5.8k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
49
3.6k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
50
10k
BBQ
matthewcrist
89
10k
Future Trends and Review - Lecture 12 - Web Technologies (1019888BNR)
signer
PRO
0
3.7k
DBのスキルで生き残る技術 - AI時代におけるテーブル設計の勘所
soudai
PRO
68
57k
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