Help us understand the problem. What is going on with this article?

redis-sentinelをperlから使う

More than 1 year has passed since last update.

この記事の内容

  • redisの準備
  • redis-sentinelの準備
  • perlから利用する方法

を記載します。

sentinelをアプリからどう使うか、がキモです。
sentinelの詳細については、Redis Sentinel Documentationを御覧ください。

はじめに

今回は、1台のサーバに、

  • redis 2セット(master / slave)
  • sentinel 3セット

を準備します。

OSはCentOS 7系を想定します。

商用では、最低限

  • master(redis + sentinel)
  • slave(redis + sentinel)
  • sentinel(sentinel)

サーバの3台が必要です。
sentinelプロセスは、各サーバで1つずつ動作させます。

redisのセットアップ

パッケージをインストールします。

$ sudo yum install redis

/etc/redis.confと、/etc/redis-sentinel.confが生成されます。

今回は実験なので、ホームディレクトリ配下にworking directoryを作成します。

$ cd 
$ mkdir redis-work
$ cd redis-work

master/slave用のコンフィグを2つ作ります。
最初は16379をmaster, 16380をslaveにします。
(master / slaveはsentinelにより動的に変更されます)

$ vim 16379.conf
16379.conf
bind 127.0.0.1
port 16379
daemonize yes

pidfile /tmp/redis_16379.pid

slave-read-only yes
$ vim 16380.conf
16380.conf
bind 127.0.0.1
port 16380
daemonize yes

pidfile /tmp/redis_16380.pid

slaveof 127.0.0.1 16379
slave-read-only yes

この設定ファイルを用いて、起動します。

$ redis-server 16379.conf
$ redis-server 16380.conf

正常にmaster / slaveになっているか確認しましょう。

$ redis-cli -p 16379 info replication
# Replication
role:master
connected_slaves:1
slave0:ip=127.0.0.1,port=16380,state=online,offset=1,lag=1
master_repl_offset:1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:2
repl_backlog_histlen:0

$ redis-cli -p 16380 info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:16379
master_link_status:up
master_last_io_seconds_ago:8
master_sync_in_progress:0
slave_repl_offset:15
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

正常に動いていますね。

redis sentinelのセットアップ

yumでredisをインストールすると、redis-sentinelというコマンドも
インストールされます。
実態はただのredis-serverへのsymlinkです。

つまり動くバイナリは同じものです。

redisは起動時のargv[0]をみて、動作モードを変えるため、sentinelを起動するときには、

  • redis-sentinelコマンドを使う
  • redis-server --sentinel オプションを使う

のどちらかで起動する必要があります。

以上蛇足でした。

設定に入ります。

同じworking directoryで、sentinel用のコンフィグを3つ作ります。
(違うのはportとpidだけです)

$ cd ~/redis-work/
$ vim sentinel1.conf
sentinel1.conf
bind 127.0.0.1
port 26379
daemonize yes

pidfile /tmp/redis_sentinel1.pid


# sentinel monitor <master-name>  <ip>       <redis-port>  <quorum>
sentinel monitor   servers1       127.0.0.1  16379         2

sentinel down-after-milliseconds servers1 2500
sentinel failover-timeout servers1 10000
$ vim sentinel2.conf
sentinel2.conf
bind 127.0.0.1
port 26380
daemonize yes

pidfile /tmp/redis_sentinel2.pid


# sentinel monitor <master-name>  <ip>       <redis-port>  <quorum>
sentinel monitor   servers1       127.0.0.1  16379         2

sentinel down-after-milliseconds servers1 2500
sentinel failover-timeout servers1 10000
$ vim sentinel3.conf
sentinel3.conf
bind 127.0.0.1
port 26381
daemonize yes

pidfile /tmp/redis_sentinel3.pid


# sentinel monitor <master-name>  <ip>       <redis-port>  <quorum>
sentinel monitor   servers1       127.0.0.1  16379         2

sentinel down-after-milliseconds servers1 2500
sentinel failover-timeout servers1 10000

さて、この後起動するのですが、
sentinelはコンフィグを自動的に書き換えますので、
その点は留意しておく必要があります。

$ redis-sentinel sentinel1.conf
$ redis-sentinel sentinel2.conf
$ redis-sentinel sentinel3.conf

ちょっと経つと、3ファイルともコンフィグが書き換わってます。

$ cat sentinel1.conf
bind 127.0.0.1
port 26379
daemonize yes

pidfile "/tmp/redis_sentinel1.pid"

# sentinel monitor <master-name>  <ip>       <redis-port>  <quorum>
sentinel myid 15c12113c628851836e39a1de9bf579879fd5005

sentinel deny-scripts-reconfig yes
sentinel monitor servers1 127.0.0.1 16379 2
# Generated by CONFIG REWRITE
dir "/home/vagrant/redis-work"
maxclients 4064
sentinel down-after-milliseconds servers1 2500
sentinel failover-timeout servers1 10000
sentinel config-epoch servers1 19
sentinel leader-epoch servers1 19
sentinel known-slave servers1 127.0.0.1 16380
sentinel known-sentinel servers1 127.0.0.1 26381 d00ffb8bb57f4c78f825dba247f0d18d155d2de2
sentinel known-sentinel servers1 127.0.0.1 26380 2b79180a7f9ba77012461d0e522a27d838927ea5
sentinel current-epoch 19

こんな感じで、もとの設定ファイルでは、masterの接続先のみを記述したにもかかわらず、
自分以外のsentinelとslaveの情報がconfigに追記されていることがわかります。

これでsentinelの準備は完了です。

redis-sentinelの利用

今回はperlのRedisモジュールである、Redis::Fastを用います。
処理速度的にはRedis::Jetが早いのですが、sentinel対応していないので・・・。

ということで、sentinelを使う場合は通常の接続方法と違って、
sentinelサーバの接続先を記載します。

test-sentinel.pl
use strict;
use warnings;
use 5.020;
use Redis::Fast;

my $redis   = Redis::Fast->new(
    sentinels   => [qw/
        127.0.0.1:26379
        127.0.0.1:26380
        127.0.0.1:26381
    /],
    service     => "servers1",
    sentinels_write_timeout => 1,
    sentinels_read_timeout  => 1,
    sentinels_cnx_timeout   => 0.1,
    reconnect => 10, every  => 300_000
);


my $i   = 0;
my $key = "hoge";
while (1) {
    eval {
        $redis->set($key, $i);
        say $redis->get($key);
    };

    if ($@) {
        warn "$@";
        next;
    }
    $i++;
    sleep(1);
}

キモとなるのは、

  • new時にsentinelsでsentilelサーバ群の接続先を書くこと
    • redis-serverではない。
  • serviceに、sentinelで指定したを指定すること
  • reconnect(秒数), every(ミリ秒)を適切に設定すること
    • 設定しないと再接続しない

です。

実験

プログラムを動かします。

$ perl test-sentinel.pl
0
1
2
...

別シェルを起動して、現在のmasterをkillします。

$ redis-cli  -p 26379 SENTINEL get-master-addr-by-name servers1
1) "127.0.0.1"
2) "16379"

$ pkill -f 127.0.0.1:16379 

すると、3秒程度で、

$ redis-cli  -p 26379 SENTINEL get-master-addr-by-name servers1
1) "127.0.0.1"
2) "16380"

と、もう方系がmasterに昇格します。
次に、落としたredisを再起動します。

$ redis-server 16379.conf

$ redis-cli -p 16379 info replication                              
# Replicationn
role:master
connected_slaves:0
master_replid:621891c20bbffd2019a2980976ca212c792ca39f
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:0
second_repl_offset:-1
repl_backlog_active:0
repl_backlog_size:1048576
repl_backlog_first_byte_offset:0
repl_backlog_histlen:0

このように、最初はmasterで立ち上がってきますが、
ちょっと経って再度チェックすると、

$  redis-cli -p 16379 info replication
# Replication
role:slave
master_host:127.0.0.1
master_port:16380
master_link_status:up
master_last_io_seconds_ago:1
master_sync_in_progress:0
slave_repl_offset:97189
slave_priority:100
slave_read_only:1
connected_slaves:0
master_replid:4fc10a2b219a9dcaf13a14cbc41652032733706a
master_replid2:0000000000000000000000000000000000000000
master_repl_offset:97189
second_repl_offset:-1
repl_backlog_active:1
repl_backlog_size:1048576
repl_backlog_first_byte_offset:90363
repl_backlog_histlen:6827

このように、slaveとなっています。

このときのプログラムの出力を確認してほしいのですが、
途切れなく数値が続いているはずです。

注意点

方系を落とし、落とした方を再起動したあと、
slaveになる前にもう方系をkillすると、うまくfailoverしません。
実験時には、2台のredisがmaster / slave の状態になっていることを確認し、
master側をkillしましょう。

終わりに

redis-sentinelは、sentinelサーバがつなぐべきmasterを教えてくれるため、
例えばkeepalivedでVIPをもたせて、アプリ側でそちらにつなぐ、
ようなことは不要です。slaveのmaster化も勝手にやってくれますし。

sentinel対応してくれている、モジュールの開発者様様ですね。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした