Redis で Sharding してみた
Redis の Sharding は現状クライアントサイド、つまりライブラリ依存で実現されています。
ここでは Ruby と Java のライブラリで実際に Sharding を試してみました。
redis-rb
redis/redis-rb · GitHub
https://github.com/redis/redis-rb
Ruby から Redis を使うための標準的なライブラリです。
gem コマンド一発でインストールできます。
# gem install redis --no-rdoc --no-ri
redis-rb で Sharding するには Redis::Distributed クラスを使います。
Redis::Distributed を使って Sharding するサンプルコードは以下のようになります。
# -*- coding: utf-8 -*- require 'redis' require 'redis/distributed' redis_hosts = %W( redis://192.0.2.1:6379/0 redis://192.0.2.1:6380/0 redis://192.0.2.1:6381/0 ) redis = Redis::Distributed.new(redis_hosts) KEYS = ('a'..'z').map {|c| c * 3} VALUES = (100..1000).to_a # ランダムな値を Redis に設定 KEYS.each { |key| p "#{key} : #{redis.node_for(key).id}" redis.set(key, VALUES[rand(VALUES.size)]) } # 設定した値を取得 KEYS.each { |key| p "#{key} : #{redis.get(key)}" }
java
xetorthio/jedis · GitHub
https://github.com/xetorthio/jedis
Java から Redis を使うためのライブラリとしては Jedis があります。
Jedis を使って Sharding するサンプルコードは以下のようになります。
import java.util.ArrayList; import java.util.List; import redis.clients.jedis.JedisShardInfo; import redis.clients.jedis.ShardedJedis; public class JedisExample3 { public static void main(String[] args) { // Redis サーバのリストを作成 List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); shards.add(new JedisShardInfo("192.0.2.1", 6379)); shards.add(new JedisShardInfo("192.0.2.1", 6380)); shards.add(new JedisShardInfo("192.0.2.1", 6381)); // サーバのリストから ShardedJedis オブジェクトを生成 ShardedJedis jedis = new ShardedJedis(shards); // 値を取得 for(char ch = 'a'; ch <= 'z'; ch++) { String key = new String(new char[3]).replace('\0', ch); System.out.printf("get result : %s\n", jedis.get(key)); } } }
上のサンプルコードを動かしてみるとわかりますが、redis-rb で登録したデータを Jedis から取得することが出来ません。
前述した通り、Redis の Sharding はクライアント依存なので、ライブラリの ConsistentHashing の実装方式が異なると、あるライブラリで登録したデータを別のライブラリを使って取り出す事が出来ません。
その場合、大抵のライブラリでは ConsistentHashing の実装クラスが差替え可能になっているので、その部分を自前で実装することになります。
ここでは Jedis から redis-rb で分散させたデータを取得するため、以下のようなクラスを書いてみました。
以下のようにこのクラスを使用するように変更すると redis-rb で登録したデータを Jedis 側で取得できるようになります。
import java.util.ArrayList; import java.util.List; import redis.clients.jedis.JedisShardInfo; public class JedisExample3 { public static void main(String[] args) { // Redis サーバのリストを作成 List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); shards.add(new JedisShardInfo("192.0.2.1", 6379)); shards.add(new JedisShardInfo("192.0.2.1", 6380)); shards.add(new JedisShardInfo("192.0.2.1", 6381)); // サーバのリストから ShardedJedis オブジェクトを生成 RubyCompatibleShardedJedis jedis = new RubyCompatibleShardedJedis(shards); // 値を取得 for(char ch = 'a'; ch <= 'z'; ch++) { String key = new String(new char[3]).replace('\0', ch); System.out.printf("get result : %s\n", jedis.get(key)); } } }
クライアントサイドの Sharding は導入は楽ですが、複数の言語やライブラリから使おうとすると意外と面倒臭そうですね。
色んな言語から使う可能性があるなら twemproxy を使った方が楽かも知れません。
Oreilly & Associates Inc
売り上げランキング: 27,988
Manning Pubns Co
売り上げランキング: 43,263