2019年5月20日月曜日

redis-rb を使えば Sentinel の failover が発生しても常に master にアクセスしてくれる

概要

前回 docker 上に redis + Sentinel 環境を構築してみました
問題点として failover が発生した場合には常に master の IP アドレスを追跡する仕組みがアプリ側に必要だということがわかりました
Ruby には redis を操作するライブラリに redis-rb があります
実はこれを使えばライブラリ側で master の追跡をしてくれます
今回は簡単なアプリを作成して挙動を確認してみました

環境

  • macOS 10.14.4
  • docker 18.09.2
  • Redis 5.0.3

アプリ作成

  • bundle init
  • vim Gemfile
gem "sinatra"
gem "redis"
  • vim app.rb
require 'sinatra'
require 'redis'

class MyApp < Sinatra::Base
  SENTINELS = [{ host: "sentinel", port: 26379 }]
  redis = Redis.new(url: "redis://mymaster", sentinels: SENTINELS, role: :master)

  get '/get' do
    key = params['key']
    redis.get(key)
  end

  get '/set' do
    key = params['key']
    value = params['value']
    redis.set(key, value)
  end
end

SENTINELS で指定するホスト名は docker-compose.yml で指定する Sentinel のサービス名を指定します
Redis.new で指定する URL は常に master になるように sentinel.conf で指定した master 名を指定します

  • vim config.ru
require './app.rb'
run MyApp

アプリは動作確認しやすいように Sinatra を使って Web アプリにしています
getset を実装することで常に master にアクセスできているかを確認します

Dockerfile 作成

アプリ用の Dockerfile を作成します

  • vim Dockerfile_app
FROM ruby

ADD . /home
WORKDIR /home
RUN gem install bundler
RUN bundle install --path vendor

EXPOSE 9292

CMD ["bundle", "exec", "rackup", "config.ru", "-o", "0.0.0.0"]

docker-compose.yml 修正

作成したアプリを docker-compose.yml に追加します

  • vim docker-compose.yml
version: '2'
services:
  master:
    image: redis
  slave:
    image: redis
    command: redis-server --slaveof master 6379
    links:
      - master
  sentinel:
    build:
      context: .
      dockerfile: Dockerfile
    links:
      - master
      - slave
  app:
    build:
      context: .
      dockerfile: Dockerfile_app
    ports:
      - 9292:9292
    links:
      - sentinel
      - master
      - slave

app サービスを追加しています
それ以外は前回 の設定と同じです

sentinel.conf と Sentinel 用の Dockerfile

これは前回と同様なのでそちらを参照してください

ビルド

アプリと Sentinel 用のイメージをビルドします

  • docker-compose build

コンテナ起動

ではコンテナを起動します

  • docker-compose up -d

動作確認

まずはこれで get/set できることを確認しましょう

  • curl localhost:9292/set?key=a&value=a
  • curl localhost:9292/get?key=a

=> a

set した値が取得できれば問題なく動作しています
では failover させても問題なく動作するか確認しましょう
まずは Sentinel と slave をスケールさせます

  • docker-compose scale sentinel=3
  • docker-compose scale slave=4

そして master をダウンさせてみましょう

  • docker-compose stop master

master と salve の一覧が変わっていることを確認します

  • docker-compose exec sentinel redis-cli -p 26379 sentinel get-master-addr-by-name mymaster
  • docker-compose exec sentinel redis-cli -p 26379 sentinel slaves mymaster | grep -A 1 'name'

master が failover したのを確認できたら再度 get/set できるか確認してみましょう

  • curl localhost:9292/set?key=a&value=b
  • curl localhost:9292/get?key=a

=> b

という感じで値が更新できると思います
以上から redis-rb 経由で Sentinel 環境にアクセスすれば master の failover を自動で追跡してくれることがわかります

最後に

redis-rb を使って Sentinel 環境にアクセスしてみました
failover にも対応しているので Ruby + Sentinel 環境の場合には必須かなと思います
ただ、docker の世界のサービス名と redis の世界の master/slave のロールは相変わらず齟齬が発生しているのでそこは注意が必要です
現在どれが master でどれが slave か確認するには Sentinel API の get-master-addr-by-nameslaves を使うようにしましょう

0 件のコメント:

コメントを投稿