Redisのデータ構造を扱う
目標
Redisの6つのデータ構造をそれぞれ目的に合わせて使い、運用で絶対に使ってはいけないコマンドとその代替手段を、体で覚えます。
なぜ重要なのか
RedisをStringだけで使うコードは、どこにでもあります。すべてJSONにシリアライズして入れ、取り出します。動作はしますが、1つのフィールドだけ変えたくても全体を読み、パースし、書き直す必要があり、同時に2つのリクエストがそうすると、片方が静かに上書きします。Hashを使えば、フィールド1つだけがアトミックに変わります。データ構造の選択1つが、競合状態をなくすのです。そして、このラボで必ず体に残すべきことがもう1つあります。Redisはコマンドを単一スレッドで処理するので、O(N)のコマンド1つが全面停止を起こします。キーが数百万個あるインスタンスでKEYS *1回が、数秒間すべてのリクエストを止めます。ステップ7のSCANは、そのためにあります。
ステップ
redis-cli PINGの結果を/root/rd/ping.txtに保存します。app:hitsを3回増やします。値が3になっている必要があります。user:42ハッシュにname、email、planの3つのフィールドを入れます。HLEN user:42が3になります。feed:42リストにアクティビティを12件入れ、最近の10件だけが残るように切り詰めます。LLEN feed:42が10になります。tag:redisとtag:cacheの2つの集合を作り、積集合を/root/rd/inter.txtに保存します。積集合の要素は2個である必要があります。score:game1ソート済み集合にメンバー5個をスコアと一緒に入れます。ZCARDが5で、ZSCORE score:game1 p3が30です。/root/rd/scan.shでuser:*パターンのキーをSCANですべて見つけ、/root/rd/scan.outに書きます。スクリプトにKEYSという文字列が入っていてはいけません。/root/rd/mem.mdにMarkdownの表を作ります。行の見出しはstring、hash、list、set、zsetの5つで、bytes列にMEMORY USAGEの結果を書きます。
参考
- リストの切り詰め:
LTRIM feed:42 0 9 - 積集合:
SINTER tag:redis tag:cache - SCANのループ: カーソル0から始め、返されたカーソルが0になるまで繰り返します
- よくある間違い1は、
KEYS *を使うことです。開発用の機械では速く、運用では障害になります。 - よくある間違い2は、巨大なキーを
DELで消すことです。UNLINKはバックグラウンドで回収します。
接続を確認する
redis-cli PINGの結果を/root/rd/ping.txtに保存してください。
redis-cliは、引数なしで実行すると対話モードになります。スクリプトでは、コマンドを引数として渡すほうがよいです。
Stringでカウンターを作る
app:hitsを3回増やしてください。値が3になっている必要があります。
増加コマンドは、キーがなくても0から始まります。アトミックであることが、このデータ構造をカウンターにする理由です。
Hashでオブジェクトを保存する
user:42ハッシュにname、email、planの3つのフィールドを入れてください。HLEN user:42が3になります。
フィールド単位で入れて取り出します。JSONを丸ごと入れるのと何が違うか、考えてみてください。
Listで最近のアクティビティを保つ
feed:42リストにアクティビティを12件入れ、最近の10件だけが残るように切り詰めてください。LLEN feed:42が10になります。
新しい項目は先頭に入れ、リストが長くならないように切り捨てます。切り詰めるコマンドが別にあります。
Setでタグの積集合を求める
tag:redisとtag:cacheの2つの集合を作り、積集合を/root/rd/inter.txtに保存してください。積集合の要素は2個である必要があります。
2つの集合の共通要素を求めるコマンドがあります。アプリケーション側のループでやってはいけません。
ZSetでスコアを管理する
score:game1ソート済み集合にメンバー5個をスコアと一緒に入れてください。ZCARDが5で、ZSCORE score:game1 p3が30です。
スコアとメンバーを一緒に入れます。入れたあと、特定のメンバーのスコアだけを取得できます。
KEYSの代わりにSCANで走査する
/root/rd/scan.shでuser:*パターンのキーをSCANですべて見つけ、/root/rd/scan.outに書いてください。スクリプトにKEYSという文字列が入っていてはいけません。
カーソルが0に戻るまで繰り返します。パターンマッチのオプションもあります。
データ構造ごとのメモリ比較表を作る
/root/rd/mem.mdにMarkdownの表を作ってください。行の見出しはstring、hash、list、set、zsetの5つで、bytes列にMEMORY USAGEの結果を書きます。
同じデータを別の構造で保存して、実際の使用量を測ります。キーごとの使用量を教えてくれるコマンドがあります。