6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

冗長構成にしたRedisをRubyから使う

Posted at

次のことの覚え書きです。

  • Redisを冗長構成で立ち上げる
  • Redis Sentinelでフェイルオーバーさせる
  • この環境をRubyで使う

Redisとは

インメモリKVSの一種。とっても速い。1台以上のスレーブへのレプリケーションによって、読み出しをスケールさせることができる。書き込みはマスターしかできないが、読み出しはスレーブからでもできる。

Redis Sentinelとは

Redisのフェールオーバーの仕組み。Sentinel同士で監視しあって、マスターが死んだ時に次のマスターを決める。Sentinelは、外部からRedisの設定を変更する。

Sentinelの投票によって、マスターが生きているか、マスターが死んだ場合にはどのスレーブを昇格させるかを決めている。通常は、3台以上のSentinelを稼働させる。

フェールオーバーをする際に、Redis SentinelがRedisの設定ファイル(redis.conf)を書き換えることに注意すること。

この記事の例では、Redisのポートは6379, Redis Sentinelのポートは26379を使っている。

この記事での構成

  • xxx.xxx.xxx.aaa - 初期設定でマスターになるホスト。Redis Sentinelを動かしている
  • xxx.xxx.xxx.bbb - 初期設定でスレーブになるホスト。Redis Sentinelを動かしている
  • xxx.xxx.xxx.ccc - 初期設定でスレーブになるホスト。Redis Sentinelを動かしている

インストール

CentOS 6.xで試した。

Redisのインストールにはjemallocが必要。EPELのリポジトリをenableにしてyumを叩けばいい(はず)。

$ yum install -y ftp://195.220.108.108/linux/remi/enterprise/6/test/i386/redis-3.0.0-2.el6.remi.i686.rpm --enablerepo=epel

Redisの設定

とりあえず /etc/redis.conf を書き換える

  • bind 127.0.0.1 があったらコメントアウトする。(他のホストからアクセスさせる場合)
  • slaveof xxx.xxx.xxx.aaa 6379 を指定する。(レプリケーションのスレーブになるホストだけ)
  • 必要に応じて、パスワードやiptablesなどを使ってセキュリティを確保する。

自動起動の設定

$ chkconfig redis on

Redisの起動

$ service redis start

Redis Sentinelの設定

通常、Redis Sentinelは3つ以上のホストで動かす。Redisを動かしていないノードでも構わない。
/etc/redis-sentinel.confを書き換える。

  • sentinel monitor mymaster xxx.xxx.xxx.aaa 6379 2 を書く (このアドレスとポートは、Redisマスターを示す)

自動起動の設定

$ chkconfig redis-sentinel on

Redis Sentinelの起動

$ service redis-sentinel start

動作確認

インストールと動作確認が全てのマシンで終わったら動作を確認してみる。

マスターでの確認

$ redis-cli info replication
# Replication
role:master
connected_slaves:2
slave0:ip=xxx.xxx.xxx.bbb,port=6379,state=online,offset=326322,lag=1
slave1:ip=xxx.xxx.xxx.ccc,port=6379,state=online,offset=326322,lag=2
master_repl_offset:326322
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:326321

スレーブでの確認

$ redis-cli info replication
# Replication
role:slave
master_host:xxx.xxx.xxx.aaa
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:301712
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

書き込んでみる

スレーブでは書き込み(set)ができないので、マスターにつなぐ必要がある。
読み出しはスレーブでもできる。

aaaがマスター、bbbが自分(スレーブ)、cccが別のホスト(スレーブ)。

$ redis-cli -h xxx.xxx.xxx.aaa set foo "FOO"  # マスターにつないで書く
OK
$ redis-cli -h xxx.xxx.xxx.aaa get foo  # マスターにつないで読む
"FOO"
$ redis-cli get foo  # ローカルにつないで読む
"FOO"
$ redis-cli -h xxx.xxx.xxx.ccc get foo  # 別のスレーブにつないで読む
"FOO"

フェイルオーバーを試してみる

マスターでRedisを止めると、いずれかのスレーブがマスターに昇格しているはず。

$ service redis stop
Stopping redis-server:                                     [  OK  ]
$ redis-cli info replication
Could not connect to Redis at 127.0.0.1:6379: Connection refused  # 止まっている

スレーブbbbで状態を見てみると、bbbがマスターになっていた。

$ redis-cli info replication
# Replication
role:master
connected_slaves:1
slave0:ip=xxx.xxx.xxx.ccc,port=6379,state=online,offset=16735,lag=1
master_repl_offset:17017
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:17016

スレーブcccで状態を見てみると、bbbがマスターになっていた。

$ redis-cli info replication
# Replication
role:slave
master_host:xxx.xxx.xxx.bbb
master_port:6379
master_link_status:up
master_last_io_seconds_ago:0
master_sync_in_progress:0
slave_repl_offset:40395
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

もともとマスターであったaaaを再起動して状態を見てみるが、bbbがマスターになっているのがそのままである。元マスターを再起動してもマスターにはならない。

$ service redis start
Starting redis-server:                                     [  OK  ]
$ redis-cli info replication
# Replication
role:slave
master_host:xxx.xxx.xxx.bbb
master_port:6379
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:57832
slave_priority:100
slave_read_only:1
connected_slaves:0
master_repl_offset:0
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

Rubyから使ってみる

RubyからRedisを使うためにredis Gemを使う。このGemはSentinelをサポートしている。Redis.newの引数にSentinelに関するパラメータを与えればいい。

require 'redis'

sentinels = [
             { host: 'xxx.xxx.xxx.aaa', port: 26379 },
             { host: 'xxx.xxx.xxx.bbb', port: 26379 },
             { host: 'xxx.xxx.xxx.ccc', port: 26379 },
            ]

redis = Redis.new(url:'redis://mymaster', sentinels: sentinels, role:'master')

p redis.get('foo') #=> "FOO"  # 読んでみる

redis.set('bar', 'BAR')  # 書いてみる
p redis.get('bar') #=> "BAR"
6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?