コネクションプールを持つ redis の erlang client を書いてみた

redis-erl

Eshell V5.8.2  (abort with ^G)
1> application:start(redis).
ok
2> redis_admin:make_pool(30).
ok
3> {ok, Connect} = redis_admin:get_connect().
{ok,redis_connect_1}
5> redis:set(Connect, "10", "30").
ok
6> redis:get(Connect, "10").      
"30"
7> redis_admin:release_connect(Connect).
ok

redis-server

[49277] 02 Jan 16:15:00 - 128 clients connected (0 slaves), 2013168 bytes in use

まだまだ模索中なのでバグはたっぷりある上に、仕様は大きく変わる可能性があります。
というか、もっとイイ実装は沢山あると思いますが、まずは動くこと重要ってことで。

https://github.com/voluntas/redis-erl

書いた理由

  • コネクションプールを書いたこと無かったので書いてみた
  • redis を使う際出来ればコネクションを使い回す仕様にしたかった
  • gen_server2 を使いたくなかった
  • rebar を使いたかった
  • コネクションプールを実際書いてみて、どれだけ運用が難しいのか知りたかった
  • コネクションプールのコネクションのリセットタイミングを知りたかった
  • 今年は redis を使っていくぞ、と気合いを入れたかった
  • rebar の template 機能を使ってみたかった
  • データベースの接続やら TCP と並列といえばコネクションプールだよねということで、まずは書いてみる必要があると考え、今後のために書いてみた

概要

  • コネクションプールが使える
  • コネクションプールは queue にて管理
  • コネクションは redis_admin:get_connect/0 で取得
  • コネクションは redis_admin:release_connect/1 で解放
  • コネクション数は redis_admin:make_pool/1 で設定
  • redis 側で timeout 0 にしておく必要あり
  • gen_tcp:connect/3 + gen_server を使ってるので上手くいかないと supervisor が再起動かけるので、特に管理を意識する必要はないです

目標

  • redis_admin:get_connect/0 しなくてもいいようにする
    • redis:get(Key) だけで勝手にコネクションプールを使ってくれる ... とか
  • redis_admin:add_server/2 で複製サーバを自動で追加可能
    • コンシステントハッシュとかを使って勝手にサーバを見に行く仕様にしたい
  • コードは短く、機能も少なく
  • 気軽にコネクションプール
  • 気軽にサーバ追加
  • 気軽に redis を Erlang から使えるようにする

コネクションを意識しない実装

かなり限定された状況でしか使えませんが、get_connect と release_connect を隠蔽してみました。

Eshell V5.8.2  (abort with ^G)
1> redis:start().           
ok
2> redis_admin:make_pool(10).
ok
3> redis:set("voluntas", "10").
ok
4> redis:get("voluntas").
"10"
概要
  • get_connect と release_connect を 1 コマンド事にやっている
  • 速度的には 1 コマンド事にコネクションを変えているので遅くなる可能性はある
  • index(database) が 0 しか指定できない
    • select コマンドを使うと全てに影響する(予定)
    • そのため汎用的ではまったくない
    • db pool みたいなのを持つ必要はあるかもしれないけどそうなると結局ナンかしら状態を意識する必要がある。
  • 1 redis 1 database の時のみ使える使用、ほとんど出番はないかも