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

Consistent, Distributed Elixir

Consistent, Distributed Elixir

An explanation of consistency guarantees in erlang and what we might be able to do with a consistency protocol like Raft.

Avatar for Chris Keathley

Chris Keathley

February 23, 2018
Tweet

More Decks by Chris Keathley

Other Decks in Programming

Transcript

  1. defmodule Demo.Lock do use GenServer def init(:ok) do state =

    {:unlocked, nil} {:ok, state} end def handle_call({:lock, client}, _from, {:unlocked, nil}) do {:reply, :ok, {:locked, client}} end end
  2. defmodule Demo.Lock do use GenServer def init(:ok) do state =

    {:unlocked, nil} {:ok, state} end def handle_call({:lock, client}, _from, {:unlocked, nil}) do {:reply, :ok, {:locked, client}} end def handle_call({:lock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end end
  3. defmodule Demo.Lock do use GenServer def init(:ok) do state =

    {:unlocked, nil} {:ok, state} end def handle_call({:lock, client}, _from, {:unlocked, nil}) do {:reply, :ok, {:locked, client}} end def handle_call({:lock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end def handle_call({:unlock, client}, _from, {:locked, client}) do {:reply, :ok, {:unlocked, nil}} end def handle_call({:unlock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end end
  4. Some problems need consistency Distributed Locking Databases Distributed scheduling and

    coordination Configuration and metadata storage Transactions
  5. defmodule Demo.Lock do use GenServer def init(:ok) do {:ok, {:unlocked,

    nil}} end def handle_call({:lock, client}, _from, {:unlocked, nil}) do {:reply, :ok, {:locked, client}} end def handle_call({:lock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end def handle_call({:unlock, client}, _from, {:locked, client}) do {:reply, :ok, {:unlocked, nil}} end def handle_call({:unlock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end end
  6. defmodule Demo.Lock do use Raft.StateMachine def init(:ok) do {:ok, {:unlocked,

    nil}} end def handle_call({:lock, client}, _from, {:unlocked, nil}) do {:reply, :ok, {:locked, client}} end def handle_call({:lock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end def handle_call({:unlock, client}, _from, {:locked, client}) do {:reply, :ok, {:unlocked, nil}} end def handle_call({:unlock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end end
  7. defmodule Demo.Lock do use Raft.StateMachine def init(:ok) do {:unlocked, nil}

    end def handle_call({:lock, client}, _from, {:unlocked, nil}) do {:reply, :ok, {:locked, client}} end def handle_call({:lock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end def handle_call({:unlock, client}, _from, {:locked, client}) do {:reply, :ok, {:unlocked, nil}} end def handle_call({:unlock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end end
  8. defmodule Demo.Lock do use Raft.StateMachine def init(:ok) do {:unlocked, nil}

    end def handle_write({:lock, client}, _from, {:unlocked, nil}) do {:reply, :ok, {:locked, client}} end def handle_call({:lock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end def handle_call({:unlock, client}, _from, {:locked, client}) do {:reply, :ok, {:unlocked, nil}} end def handle_call({:unlock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end end
  9. defmodule Demo.Lock do use Raft.StateMachine def init(:ok) do {:unlocked, nil}

    end def handle_write({:lock, client}, {:unlocked, nil}) do {:reply, :ok, {:locked, client}} end def handle_call({:lock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end def handle_call({:unlock, client}, _from, {:locked, client}) do {:reply, :ok, {:unlocked, nil}} end def handle_call({:unlock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end end
  10. defmodule Demo.Lock do use Raft.StateMachine def init(:ok) do {:unlocked, nil}

    end def handle_write({:lock, client}, {:unlocked, nil}) do {:ok, {:locked, client}} end def handle_call({:lock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end def handle_call({:unlock, client}, _from, {:locked, client}) do {:reply, :ok, {:unlocked, nil}} end def handle_call({:unlock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end end
  11. defmodule Demo.Lock do use Raft.StateMachine def init(:ok) do {:unlocked, nil}

    end def handle_write({:lock, client}, {:unlocked, nil}) do {:ok, {:locked, client}} end def handle_write({:lock, client}, {:locked, other_client}) do {:error, {:locked, other_client}} end def handle_call({:unlock, client}, _from, {:locked, client}) do {:reply, :ok, {:unlocked, nil}} end def handle_call({:unlock, client}, _from, {:locked, other_client}) do {:reply, :error, {:locked, other_client}} end end
  12. defmodule Demo.Lock do use Raft.StateMachine def init(:ok) do {:unlocked, nil}

    end def handle_write({:lock, client}, {:unlocked, nil}) do {:ok, {:locked, client}} end def handle_write({:lock, client}, {:locked, other_client}) do {:error, {:locked, other_client}} end def handle_write({:unlock, client}, {:locked, client}) do {:ok, {:unlocked, nil}} end def handle_write({:unlock, client}, {:locked, other_client}) do {:error, {:locked, other_client}} end end
  13. Raft.start_peer(Demo.Lock, name: :s1) Raft.start_peer(Demo.Lock, name: :s2) Raft.start_peer(Demo.Lock, name: :s3) Raft.set_configuration(:s1,

    [:s1, :s2, :s3]) :ok = Raft.write(:s1, {:lock, :s1}) :error = Raft.write(:s2, {:lock, :s2}) :error = Raft.write(:s2, {:unlock, :s2})
  14. Raft.start_peer(Demo.Lock, name: :s1) Raft.start_peer(Demo.Lock, name: :s2) Raft.start_peer(Demo.Lock, name: :s3) Raft.set_configuration(:s1,

    [:s1, :s2, :s3]) :ok = Raft.write(:s1, {:lock, :s1}) :error = Raft.write(:s2, {:lock, :s2}) :error = Raft.write(:s2, {:unlock, :s2}) :ok = Raft.write(:s1, {:unlock, :s1})
  15. Raft.start_peer(Demo.Lock, name: :s1) Raft.start_peer(Demo.Lock, name: :s2) Raft.start_peer(Demo.Lock, name: :s3) Raft.set_configuration(:s1,

    [:s1, :s2, :s3]) :ok = Raft.write(:s1, {:lock, :s1}) :error = Raft.write(:s2, {:lock, :s2}) :error = Raft.write(:s2, {:unlock, :s2}) :ok = Raft.write(:s1, {:unlock, :s1}) :ok = Raft.write(:s2, {:lock, :s2})