ClojureからRedisを扱う(with Carmine)

こんにちは。
今回はClojureからNoSQLのRedisを利用する環境をどうこうしていたのでここにメモしておこうと思います。
ちなみにNoSQLを扱うのは初めてです。今までMySQLでやりくりしてきたのですが, 対話システムを構築している上で書き込みと参照処理が高速のものが必要になったので, Redisを試してみようと思います。
ちなみに対話のログを残す部分で使おうと思っています。堅牢性はある程度は犠牲にしてもいいというトレードオフで速さを得たことになりますね。
ではさっそく行きましょう。

$ redis-server
...省略...
... The server is now ready to accept connections on port 6379

Redisが起動しましたね。デフォルトでは6379のポート番号で起動されるみたいです。

簡単にRedisを試してみます。別のタブで開いてRedis付属のクライアントから操作してみます。

$ redis-cli
redis 127.0.0.1:6379> set a "B"
OK
redis 127.0.0.1:6379> get a
"B"
redis 127.0.0.1:6379> set 日本語 "カナ"
OK
redis 127.0.0.1:6379> get 日本語
"\xe3\x82\xab\xe3\x83\x8a"

以上は簡単なサンプルです。redis-cliから使うと日本語はわかりにくいですが, Clojureから使う分には読める形で表示されるので大丈夫でしょう。 次はリストを試してみます。

redis 127.0.0.1:6379> lpush list "A"
(integer) 1
redis 127.0.0.1:6379> lpush list "B"
(integer) 2
redis 127.0.0.1:6379> lrange list 0 -1
1) "B"
2) "A"

リストの返り値は要素数になっているみたいですね。0 ~ -1で指定することで要素全てを取得できるようです。

次にclojureからcarmineを使ってRedisサーバにアクセスします。

本家githubのページを参考にしてますのでこちらも是非覗いてみてください。 https://github.com/ptaoussanis/carmine

まずproject.cljの:dependenciesに以下を追加します。

[com.taoensso/carmine "2.2.1"]  ;(現時点での最新 2013/09/30)

次にredis.cljを用意して以下のスクリプトを書き込んでみましょう。

(ns redis  
  (:require [taoensso.carmine :as car :refer (wcar)]))  

(def server1-conn {:pool {} :sepc {:host "127.0.0.1" :port 6379}})  
(defmacro wcar* [& body] `(car/wcar server1-conn ~@body))

(defn setter  
  [key value]  
  (wcar* (car/set key value)))  

(defn getter  
  [key]  
  (wcar* (car/get key)))  

(defn add-list
  [key value]
  (wcar* (car/lpush key value)))

(defn all-list
  [key]
  (wcar* (car/lrange key 0 -1)))

ソースコードを少し眺めていただくとわかるのですが, Redisのコマンドがそのままの名前で関数名になってるようです。

次に読み込んで, 実行してみます。

=> (use 'redis)
nil
=> (setter "コーヒー" "美味")
"OK"
=> (getter "コーヒー" )
"美味"
=> (add-list "mylist" "value1")
1
=> (add-list "mylist" "value2")
2
=> (add-list "mylist" "value3")
3
=> (add-list "mylist" "value4")
4
=> (add-list "mylist" "こんなものか")
5
=> (all-list "mylist")
["こんなものか" "value4" "value3" "value2" "value1"]

リストの後ろに要素を詰めて行きたければrpushを使うだけですね。
とりあえずリストを使いたいだけなのでサンプルはこれだけですが, 他にsetやsorted-setなどのデータ構造が扱えるはずです!

また今度簡易な処理速度の比較も行ってみたいと思います。