redis をちょっと試してみた, master と slave を使う.
redis という メモリ上で作動する noSQLなデータベースについての調査。
予想外だったこと
master と slave を動かしたときに、 master → slave はデータベースの内容シンクロする。 しかし、slave → master へはシンクロしなかった。(少なくとも自動的には)
したがって、slaveに対して新規にデータ追加してもその内容が master に反映されない。
slaveにも普通に追加できるのでこれはちょっとどうなの? (といいますか何か slave → master へシンクロさせる方法があるのかもしれない。設定または明示的な命令を発する等)
※twitterのようなサービスを考えた場合、データの追加/更新より読み出しの方が圧倒的に 多いので、slaveはReadOnlyでも別に問題ないのかもしれない。
その他わかったこと
http://code.google.com/p/redis/wiki/ReplicationHowto を読めばわかることですが...
- master ← slave1 ← slave2 のようにぶら下げることができる
- slave は master の内容をシンクロするので slave に対して重い処理すれば負荷分散できる
- たとえばソートのように重い処理は slave で実行する
- たとえば、slave の一つにディスクへの保存を担当させ、master は常にメモリだけで動かすなど
テストした内容
STEP1) master/slave 2つのredis-serverを動かす
redis-server と redis.conf を用意する
- http://code.google.com/p/redis/ から tar.gz をとってきて展開し make する
- redis-server ができているのでとりあえず ./redis-server して動かす
- 一度動かすと 同じディレクトリに redis.conf ができている
master を準備
redis-server と redis.conf を ./master/ 以下に配置
slave を準備
redis-server と redis.conf を ./slave/ 以下に配置
redis.conf をslaveとして作動するように編集する。 編集ポイント
- ポートを デフォルトの6379 から変更し 6378 に変える
- 「slaveof localhost 6379 」を追加 (masterデータベースのホストとポートを指定)
diff master/redis.conf slave/redis.conf の結果
24c24,25
< port 6379
---
> #port 6379
> port 6378
98c99
< # slaveof <masterip> <masterport>
---
> slaveof localhost 6379
master と slave を起動
cd ./master
./redis-server ./redis.conf > log 2>&1 &
cd ..
cd ./slave
./redis-server ./redis.conf > log 2>&1 &
Step2) クライアントからデータベースにデータを追加
今回は jredis を使います。 話を単純にするため、jredis-1.0-rc2.jar を ~/.groovy/lib/ に配置しておきます。
master に データを追加して取得
import org.jredis.*
import org.jredis.ri.alphazero.*
def db_master = new JRedisClient('localhost',6379)
def key = 'foo1'
def value = 'bar1'
db_master.set(key,value)
def v = db_master.get(key)
if(v)
println new String(v)
slave に データを追加して取得
import org.jredis.*
import org.jredis.ri.alphazero.*
def db_slave = new JRedisClient('localhost',6378)
def key = 'foo2'
def value = 'bar2'
db_slave.set(key,value)
def v = db_slave.get(key)
if(v)
println new String(v)
slave に追加したデータを master から取得を試みる
import org.jredis.*
import org.jredis.ri.alphazero.*
def db_master = new JRedisClient('localhost',6379)
def db_slave = new JRedisClient('localhost',6378)
def key = 'foo3'
def value = 'bar3'
db_slave.set(key,value)
def v = db_master.get(key)
if(v)
println new String(v)
else
println 'error'
assert new String(db_slave.get(key)) == value
以上