2024/12/1 Redis のはなし1
所属のあるアプリケーションで使用している Sidekiq の接続先である Redis インスタンスを変更するという作業がありました。やることとしては: 1. Sidekiq が接続する AWS Elasticache Redis インスタンスの向き先変更
Redis インスタンスは redis 6 から redis 7 に変わる
2. なお変更後の Redis は ACL でユーザが作成されている
ということは接続クライアントにわたす URI schema の変更もありそう
3. なお変更後の Redis はデータベースを複数使うので database id の指定が必要
ということは接続クライアントにわたす URI s(ry
4. Sidekiq 予約ジョブはメンテを入れてsrc->destへマイグレーション
といったものです。
正直 Redis について知らないことばかりでへえ〜となることが多かったので雑多に書いておきます
インスタンスの向き先の切り替えは別のアドベントカレンダーの記事で扱うので、ここではマイグレーションのみの話をすると:
redis-cli だけでやれればそれに越したことはないなという感覚
オペレーション用のサーバが2つのRedisと同じVPC内にありSGで許可されていればコマンドでの実行を考えたい
調べると redis-cli を使って dump ファイルを作成、それを新しいインスタンスへ restore することができそう
コマンドだけ書いておくと:
引越し元のインスタンスから app:schedule というキー名のデータを dump
code:dump.sh
redis-cli -u rediss://src-redis:6379 --raw dump app:schedule > backup.dump
※ 注意したいのは実はこれではうまくいかないのですがそれは追って触れます
引っ越し先のインスタンスへ dump を使い、ユーザ alice として databse 1 番へ schedule というキー名でリストアする
code:restore.sh
cat backup.dump | redis-cli --user alice -u rediss://dest-redis:6380/1 -x restore schedule 0
※ 補足しておくと Sidekiq は予約ジョブを schedule というキー名に入れます(引越し元は redis-namespace という gem を使っているので app:schedule prefix があります)
なんかいけそうな気がする
https://pbs.twimg.com/media/DmDZUixUwAAOrXV.jpg:small#.jpg
実際のマイグレーションを簡易的に再現するため redis-cli でホストから起動したコンテナの Redis に接続します
イメージ:
マイグレーションを実行する作業環境 → docker で Redis を起動したホストマシン
引越し元の Redis 6 → docker で起動したコンテナ (ホストの6379にポートフォワーディング)
引越したい Redis 7 → docker で起動したコンテナ (ホストの6380にポートフォワーディング)
イメージを pull してコンテナで redis を起動しておきましょう
code:接続中のredis6
docker run -dit --name src-redis -p 6379:6379 --init public.ecr.aws/docker/library/redis:6.2.14
code:今後接続したいredis7
docker run -dit --name dest-redis -p 6380:6379 --init public.ecr.aws/docker/library/redis:7.0.7
バージョンは作業当時に想定していたバージョンに準じています
code:接続確認
redis-cli -u redis://127.0.0.1:6379
127.0.0.1:6379> exit
redis-cli -u redis://127.0.0.1:6380
127.0.0.1:6380> exit
なんで docker hub (redis:7.4.1) じゃないの?みたいなのありそうなんですが、やってみると redis が起動してないのです
code:こんなメッセージが出る
Could not connect to Redis at 127.0.0.1:6379: Connection refused
redis-cli 周りから少し触れてきます
redis-cli 周り
データベースの確認
code:db
127.0.0.1:6379> config get databases
1) "databases"
2) "16"
pull したイメージではすでに16データベースがありました
公式ドキュメントに記載のあるredis.conf の例には 16 とあります
./redis-server で起動すると以下のメッセージがあるので config がなくても 16 な気はしています
38:C 28 Nov 2024 12:00:48.850 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
code:select
127.0.0.1:6379> select 1
OK
127.0.0.1:63791> select 0 OK
127.0.0.1:6379> select 16
(error) ERR DB index is out of range
127.0.0.1:6379> select 15
OK
ACL
Elasticache 内でのコントロールになるので直接ユーザを作成するのはAWSコンソールか aws-cli になるでしょう
概念は変わらないはずなのでここでは redis-cli で考えます
まずはヘルプを眺める
code:acl
127.0.0.1:6379> ACL HELP
1) ACL <subcommand> [<arg> value opt ...]. Subcommands are: 3) List all commands that belong to <category>, or all command categories
4) when no category is specified.
...snip...
23) Create or modify a user with the specified attributes.
24) USERS
25) List all the registered usernames.
26) WHOAMI
27) Return the current connection username.
28) HELP
29) Print this help.
データを移したい Redisはすでにユーザがいる想定なので、既存のユーザ確認とユーザ作成をします
code:acl list
127.0.0.1:6380> ACL LIST
1) "user default on nopass ~* &* +@all"
最初からデフォルトのユーザがいます
Redis can be configured so that new connections are already authenticated with a "default" user (this is the default configuration).
ユーザ作成
AWS Elasticache においてはユーザ管理でSREがすでに作成してくれていたユーザがいるのでアクセス文字列を確認 on ~* +@all -@dangerous +info が指定されていました
同じ権限を指定しユーザ alice を作成します
code:set_user
127.0.0.1:6380> ACL SETUSER alice on nopass ~* +@all -@dangerous +info
OK
ここでは面倒なのでnopassにしてます
code:確認
127.0.0.1:6380> ACL LIST
1) "user alice on ~* resetchannels +@all -@admin -flushdb -migrate -sort -keys -restore -swapdb -restore-asking -flushall -sort_ro"
2) "user default on nopass ~* &* +@all"
さて dump, restore を試してみるぞ〜というのはまた次の話です