仕事でRedisを使いそうなのでScala用のRedisクライアントについて調べてみました。
READMEに書いてある内容とソースコードを流し読みして書いてますので実際に動かしての感想ではありません。使用例もREADMEに書いてあるものからの抜粋です。
Sedis
- Jedis(Java用のRedisクライアント)のScalaラッパー
- 1ファイルのみで構成されており処理はJedisを呼んでるだけなので非常にシンプル
- ブロッキングAPIのみ
- コネクションプール装備(Jedisのもの)
- パイプラインは未対応?(JedisのAPIを直接呼び出せばよい??)
- Play2のプラグイン(キャッシュAPIでRedisを使えるようにするもの)はこれを使っている
import org.sedis._ import redis.clients.jedis._ val pool = new Pool(new JedisPool(new JedisPoolConfig(), "localhost", 6379, 2000)) pool.withJedisClient { client => Dress.up(client).get("single").isDefined.must(be(true)) Dress.up(client).get("single").get.must(be("foo")) val r: List[String] = Dress.up(client).lrange("test",0,2)· r.size.must(be(2)) r.toString.must(be("List(bar, foo)")) val s: List[String] = Dress.up(client).sort("test") s.size.must(be(2)) s.toString.must(be("List(bar, foo)")) } //or using implicits import Dress._ pool.withClient { client => client.get("single").isDefined.must(be(true)) client.get("single").get.must(be("foo")) client.lindex("test",0).must(be("bar")) val r: List[String] = client.lrange("test",0,2) r.size.must(be(2)) r.toString.must(be("List(bar, foo)")) val s: List[String] = client.sort("test") s.size.must(be(2)) s.toString.must(be("List(bar, foo)")) }
scala-redis
- プーリング機能装備(Commons Pool)
- IOはSocketベースで自前実装
- Luaスクリプトの呼び出しも可能
- パイプライン対応
- ブロッキングAPIなのにAkkaが必要なのはなんでだろう?と思ったらPub/Subに使っている模様
import com.redis._ import com.redis._ val r = new RedisClient("localhost", 6379) r.set("key", "some value") // => true r.get("key") // => Some(some value)
- Akka IOベースのノンブロッキング版もある
// Akka setup implicit val system = ActorSystem("redis-client") implicit val executionContext = system.dispatcher implicit val timeout = Timeout(5 seconds) // Redis client setup val client = RedisClient("localhost", 6379) // Set val numKeys = 3 val (keys, values) = (1 to numKeys map { num => ("key" + num, "value" + num) }).unzip val writes = keys zip values map { case (key, value) => client.set(key, value) } Future.sequence(writes).futureValue
rediscala
- Akka IOベースのノンブロッキングなRedisクライアント
- コネクションプール装備
- パイプライン対応
- Luaスクリプトの呼び出しも可能
- 基本ノンブロッキングだけどブロッキング版のList APIにアクセスするためのクライアントが別に用意されている
import redis.RedisClient import scala.concurrent.Await import scala.concurrent.duration._ import scala.concurrent.ExecutionContext.Implicits.global implicit val akkaSystem = akka.actor.ActorSystem() val redis = RedisClient() val futurePong = redis.ping() println("Ping sent!") futurePong.map(pong => { println(s"Redis replied with a $pong") }) Await.result(futurePong, 5 seconds) akkaSystem.shutdown()
結論
どのライブラリもすでにあまりやることがないのかコミットは活発ではありませんが、メンテは継続されているように見えます。最も最近コミットされているのはSedisですがしょぼい機能追加のPRなので参考にならなそう。scala-redisは今年5月、rediscalaは今年2月がそれぞれ最後のコミットになっています。
Sedisは機能面ではダントツで貧弱ですが、Play2でキャッシュAPIの範囲内での利用で済むのであればPlay2プラグイン経由でSedisを使うのがよいかもしれません。
scala-redisとrediscalaは機能面ではだいたい同じような感じ。ブロッキングならscala-redis、ノンブロッキングならscala-redis-nbもしくはrediscalaのどちらかを選べばよさそうです。