Redis ClusterをJavaで使ってみる


概要

使用するライブラリ

こちらの星がついているクライアントを選びました。

  • jedis
  • lettuce
  • reddison

試すこと

  • 文字列のset/get
  • 文字列のmset/mget
  • リクエストが最適なノードに届くか?
  • 一部のマスタが死んでも適切に対応するか?
  • 非同期APIを持つか?

Redisクライアントの仕組みのおさらい

クラスタは複数のマスタでデータを分散して管理しており、対象のデータを持っていないマスタへのリクエストは別マスタへリダイレクトされる。
また、クラスタの現在の状態はCLUSTER INFOコマンドで知ることができる。

賢いクライアントであれば、

  • 定期的にクラスタの状態を監視して、マスタやその保持するslotに変更があればそれを反映する。
  • リダイレクトされないように現在のクラスタの状態をキャッシュしておく

などをしてくれるはず。

試してみる

今回は簡単な例で以下を調べてみた。

  • get/set/mget/mset/expire
  • フェイルオーバーに自動で対応
  • 非同期・同期APIの速度検証

get/set/mget/mset/expire

コード例

Jedis、Lettuceは問題なし。

Redissonは現行の安定版ではmget/msetができなかったので、SNAPSHOTを使ってみた。

どんなリクエストが来てるか知りたければMONITORコマンドを使うと良い。
(クラスタ組んだ時は全リクエストが同一ノードに来てるように表示されるのはなぜ?)

フェイルオーバーに自動で対応

コード例

マスタ3台、スレーブ3台でクラスタを組んでいる状態でマスタを一台落としてみてフェイルーバーする際にクライアントが対応できるかを調べる。

  1. クライアントプログラムを走らせる。
  2. マスタを落とす。
  3. リトライを試みていることを確認し、フェイルオーバー完了後に元に戻っていることを確認する。

どのクライアントも普通にできていました。

非同期・同期APIの速度検証

コード例

大量のリクエストを同期、非同期で送ってみて速度を測る。

  • Jedisはまだ非同期APIをサポートしていないので、裏で同期と同じことをしている。 →https://github.com/xetorthio/jedis/issues/241  (2011年からずっと検討中。もう組み込まれてるっぽいけどAPIがまだ?)
  • クライアントとサーバーが同一マシン(ホスト上でDocker立てた)なので、ネットワーク遅延がほぼないと思われる。(同期APIに有利な条件?)
  • asyncを正しく測るのが難しいので、とりあえず全リクエストを別スレッドに送り終えた時点で計測している。
  • asyncの前後に処理を入れることで結果が変わりそうなので、両方の順番を試してみた。

結果:

Jedis

# 一回目
async: 5502
sync: 4116

# 二回目
sync: 5217
async: 4109

Lettuce

# 一回目
async: 4105
sync: 8986

# 二回目
sync: 10769
async: 1667

Redisson

# 一回目
async: 4897
sync: 12705

# 二回目
sync: 11290
async: 3091

まとめ

  • 普通に使うならJedisが無難(他のはSNAPSHOT使ってるし。。)
  • 非同期APIを使いたい、さらに速く使いたい、場合にはLettuceがいいかも。
  • Redissonは個人的にはAPIがわかりにくくて好きじゃない。。。
  • 速度測定なんだか当てにならないっぽい?