Pocket

Redis4.0のUNLINKを使ってみる

こんにちは、サーバーサイドエンジニアの菅原です。
今回は今更ながらRedis4系から追加されたUNLINKコマンドについて調べて検証してみました。

背景

Webアプリケーションのパフォーマンスを向上しようとするときRedisは強力なツールです。
ですがRedisを運用する注意点としてRedisの容量の懸念が見込まれます。
キーがどんどん積み上がるとRedisの容量を大きく圧迫し、そうなるとRedisはキーの検索に時間を要するのとキーを削除するときもサーバーに負荷がかかりサーバーダウンしてしまうことも考えられます。

setした時に設定したexpireが切れたキーも完全に消えることは確証されなく、
ゴミのデータが残る場合があるのでDELコマンドで定期的に掃除が必要になります。
しかしRedis3までのDELコマンドは一度に指定されたキーを全てアクセスして削除しようとするのでその間はRedisは他の処理を受け付けないため
Redisに膨大なサーバー負荷がかかり、Redisが落ちてしまったり、クラスターダウンの影響にも繋がります。
今回はその問題を解決するためにRedis4系で新たに追加されたUNLINKコマンドについて紹介します。

Redis4とは

Redis4は2017年7月14日にリリースされました。現在は4.0.10までのバージョンが出ています。
4系で追加された仕様の中でもっとも気になったのはモジュール機能とUNLINKコマンドの追加です。

モジュール機能はRedisの型やコマンドなどを拡張できる機能で
UNLINKコマンドは非同期にキーのデータを削除してくれることで
スレッドの待ち時間なしにデータを順に削除することができる機能です。
今回は実際にUNLINKコマンドを扱って挙動を確認してみましょう。

今回の目標とゴール

  1. Redis Clusterを構築する
  2. Redis Clusterにデータをセットする
  3. UNLINKコマンドで容量が大きいキーTOP10を削除するシェル作成
  4. 実際に登録したデータが反映されているか確認する

環境

  • Mac OS
  • redis-4.0.9

Redis Clusterを構築する

まずは公式HPから自分のマシンにRedis 4をダウンロードして解凍します。

https://redis.io/download

以前に環境構築した記事で細かい設定などを執筆してあるのでそちらも参考にしてください。

初めてRedisを使うための環境構築

上記インストールが完了したら
redis-serverを立ち上げましょう(brew)など/usr配下のredisを起動したい場合はそのパスに合わせてredis-serverコマンドを入力します。

redisが立ち上がったらredisのコマンドラインを立ち上げます

無事立ち上げることができたら成功です。デフォルトでは6379のポート番号でredisが立ち上がっていることがわかります。

そして早速Redis Clusterを構築するためのCluster構成を設計しましょう
今回はClusterを構成するための最低限のCluster構成(master: 3台, slave: 3台)で設計して構築します。
図で表すとこんな感じです。

Caching Cluster Architecture (2)

Port(7000~7005)までのRedisでクラスターを構築していきます。
まずは先ほど立ち上げたredisサーバーを閉じてcluster-testディレクトリを作成します。
作成が完了したらその中に(7000~7005)までのディレクトリの部屋を用意してあげます。
用意ができたらそれぞれの部屋にRedisの設定ファイル(redis.conf)を用意してあげます。ポート番号は各自変更してください。
シェルで配布もできそうなのでそこらへんもまた作っていけたらと思います。

各ディレクトリに配布が完了したら各Redisを立ち上げていきましょう。

無事立ち上がったら次にクラスターで各nodeをclusterとして連携させていきます。
今回は redis-trib.rbというrubyで作られたクラスター管理ツールで構築していきます。
(あらかじめgemなどでインストールしておきます)

clusterは3系以降しか構築できないためgemでインストールするredisは3系以上のインストールをお願いします。

redis-trib.rbのバイナリが入ることがわかるので実行していきましょう。
redis-tribはクラスターを構築したり、nodeを追加したり、クラスターやノードの状態をチェックすることもできます。
今回は各MASTERノードにSLAVEを1 対 1 で構築してあげたいのでreplicas 1のコマンドをコマンド内に入れて実行していきましょう

実行が完了するとコンバートしたよとクラスターの構成ができたことがわかります。
[OK] All 16384 slots covered

実際にクラスターの状態を確認します。

これでクラスターが構築されたことがわかります。

Redisにデータをセットする

それでは構築したClusterにデータを投入していきましょう

最初に設定したwp-cluster1のキーバリューは7000(master)のredisに格納され、
そのあとのwp-cluster2はポート7004のredis(master)にリダイレクトで格納されて分散されていることがわかります。

次に先ほど自動的に格納されて切り替わったポート7004のコマンドラインから7000に格納したキー(wp-cluster1)の値を取り出してみます。

7000ポートのredisを参照しに行ってることがわかります!これでredis clusterへのデータの投入ができました。

しかし、上記方法でデータの追加をしてUNLINKを扱うにはかなり面倒です。
Redisにはダミーデータを登録するコマンドがあるのでそれを使いましょう。
ダミーデータはDEBUGコマンドから投入することができます。
それでは1000件のダミーデータを投入していきましょう。

*Clusterではこのダミーデータはslaveへの同期が行われないので注意

登録が完了できたら実際に投入されているか確認します。

1000件のデータが投入されていることがわかります。

それでは実際にこのキーの中でサイズが大きいTOP10を出力してUNLINKするためのシェルを書いていきます。

UNLINKコマンドで容量が大きいキーTOP10を削除するシェル作成

unlink_scan_big_keys.shファイルを作成し、以下のシェルを記載します。

コマンド一つ一つの意味は解説しませんが
7000のredisサーバにあるキーバリューをSCANで読み出し、読み出したデータの情報を加工して
result.outファイルに吐き出します。
result.outに記載しているキーのデータサイズを昇順に並び替え、そのトップ10をUNLINKで削除します。

unlink-keys.sh は別シェルで叩いてますが同一シェル上で問題ありません。

実際に完成したらこのシェルを実行してあげましょう

消す対象に上がったキーのバックアップファイルを参照してそのキーが本当に消されているのか確認します。

nilが返ってきたのでデータが削除されていることがわかります。

今回はトップ10のデータをunlinkで削除しました。

実際にDELコマンドで削除するよりも非同期で安全に削除することができるため
バッチのように定期的に取り扱うことも簡単にできそうです。

まとめ

Redis4系のUNLINKが気になったので軽く触ってみました。
大量にデータをUNLINKしてる場合にも別ターミナルからRedisへデータを投入なども可能で
DELではできなかった操作でデータ量と頻度によってはUNLINKがおすすめであることがわかりました!
redis4.0ではさらに可用性で追加された仕様もあるので皆さんも是非使ってみてください。

Pocket

Join Us !

ウエディングパークでは、一緒に働く仲間を募集しています!
ご興味ある方は、お気軽にお問合せください(カジュアル面談から可)

採用情報を見る