2016年12月7日水曜日

Erlangのマルチユーザ分散型DBMS「Mnesia」

Erlangのマルチユーザ分散型DBMS「Mnesia」 こんなDB があるんですねぇ。クエリやトランザクション機能を備えています。Elixirを勉強していなかったら、まず出会わなかったでしょうから、使えるかどうかは別として、素晴らしい出会いです(笑)。

Mnesiaの特徴

  • 高速リアルタイムkey-value検索
  • 複雑な非リアルタイムクエリ(操作および保守)
  • 分散アプリケーションのための分散データ
  • 高いフォールトトレランス
  • ダイナミックな再構成(Dynamic reconfiguration)
  • 複雑なオブジェクト

  • 高速リアルタイム操作
  • フォールトトレランス(レプリケーション)
  • システムを停止、または一時停止せずに再構成する機能
MnesiaはErlangで書かれているため、Erlangをデータベースプログラミング言語に変えています。 これには多くの利点がありますが、第一に、DBMSで使用されるデータ形式と、データを操作するために使用されるプログラミング言語で使用されるデータ形式との間のインピーダンスの不一致が全くないことです。
  • データベーススキーマは、実行時に動的に再構成できます。
  • テーブルは、場所、レプリケーション、永続性などのプロパティを持つように宣言できます。
  • フォールトトレランスを向上させるために、テーブルを複数のノードに移動または複製することができます。
  • テーブルの位置はプログラマにはわかりません。 プログラムではテーブル名を扱い、システムはテーブルの位置を追跡しています。
  • データベーストランザクションを分散することができ、多くの機能を1つのトランザクション内で呼び出すことができます。
  • 複数のトランザクションを同時に実行でき、その実行はDBMSによって完全に同期されます。 Mnesiaは、2つのプロセスが同時にデータを操作しないことを保証します。
  • トランザクションは、システム内のすべてのノードで実行されるか、または実行されないかのプロパティを割り当てることができます。



参考サイト
分散DBMS「Mnesia」の並列処理(インターネットコム)

2016年12月6日火曜日

Elixirで「GenServer」(その2)

Elixirで「GenServer」(その2)です。Cultttさんの「Understanding GenServer in Elixir」のブログを読んで、ようやく、どういうことか見えてきたような気がします。

/lib/kv/shopping_list.ex
defmodule ShoppingList do
  use GenServer
 
  # Client API
 
  def start_link do
    # 1. サーバーのコールバックが実装される場所(同じモジュール内に実装する場合は「__MODULE__」)
    # 2. モジュールの初期化引数(何もなければ「:ok」)
    # 3. オプションのリスト([])
    GenServer.start_link(__MODULE__, :ok, [])
  end
 
  def read(pid) do
    # callは、サーバーからの応答を受信するまでプロセスをブロック。
    # 1. プロセスのPID
    # 2. リクエスト
    GenServer.call(pid, {:read})
  end

  def add(pid, item) do
    # castは、サーバーからの応答を待たない。
    # 1. プロセスのPID
    # 2. リクエスト
    GenServer.cast(pid, {:add, item})
  end
 
  # Server Callbacks
 
  # サーバーを初期化
  def init(:ok) do
    {:ok, []}
  end
 
  # 1. リクエスト
  # 2. プロセスのPID
  # 3. 現在の状態
  def handle_call({:read}, from, list) do
    {:reply, list, list}
  end
 
  # 1. リクエスト
  # 2. 現在の状態
  def handle_cast({:add, item}, list) do
    {:noreply, list ++ [item]}
  end
end
実際に利用してみた例
$ iex -S mix

iex(1)> {:ok, pid} = ShoppingList.start_link
{:ok, #PID<0.123.0>}

iex(2)> ShoppingList.add(pid, "milk")
:ok

iex(3)> ShoppingList.add(pid, "bread")
:ok

iex(4)> ShoppingList.add(pid, "cheese")
:ok

iex(5)> ShoppingList.read(pid)
["milk", "bread", "cheese"]

参考サイト
Understanding GenServer in Elixir(Culttt)
Elixirでクライアント・サーバ関係を実装する「GenServer」

2016年12月5日月曜日

Elixirでクライアント・サーバ関係を実装する「GenServer」

Elixirでクライアント・サーバ関係を実装する「GenServer」 まあ、よくわかりませんが、雰囲気(?)だけは感じ取れます(笑)。
GenServerは他のElixirプロセスと同様のプロセスであり、状態の保持、コードの非同期実行などに使用できます。 このモジュールを使用して実装されたジェネリックサーバープロセス(GenServer)を使用する利点は、標準のインターフェイス関数セットを持ち、トレースとエラーレポートの機能を含むことです。 スーパービジョンツリー(supervision tree)にも適合します。
GenServerの動作は、共通のクライアントとサーバーの対話を抽象化します。 開発者は、コールバックと機能を実装するだけで済みます。
/lib/kv/stack.ex
defmodule Stack do
  use GenServer

  def handle_call(:pop, _from, [h | t]) do
    {:reply, h, t}
  end

  def handle_cast({:push, item}, state) do
    {:noreply, [item | state]}
  end
end
call は同期でサーバーからの返答を待ち、castは非同期で返答を待ちます。
$ iex -S mix

iex(1)> {:ok, pid} = GenServer.start_link(Stack, [:hello])
{:ok, #PID<0.123.0>}

iex(2)> GenServer.call(pid, :pop)
:hello

iex(3)> GenServer.cast(pid, {:push, :world})
:ok

iex(4)> GenServer.call(pid, :pop)
:world

参考サイト
Elixir の OTP (GenServer 編)(Qiita)
[Elixir]GenServerの基本を習得する(Code of Resistance!!さん)