ニコニコ生放送に見る Redis 活用ノウハウ

第2回Redisの導入と基本機能

今回は実際にRedisをインストールしてみるところから、コマンドラインクライアントを使った基本的な操作方法、そして実際のアプリケーション開発時に重宝するDB選択やタイムアウトなどのRedis特有の仕様について説明します。

インストール

ダウンロード

本連載執筆時点の最新stableである、2.0.4をダウンロードします。

$ wget http://redis.googlecode.com/files/redis-2.0.4.tar.gz

コンパイル

RedisはANSI Cで書かれ、外部の依存ライブラリの必要ないシンプルな実装になっているため、コンパイルは以下のステップで完了します。

$ tar xzf redis-2.0.4.tar.gz
$ cd redis-2.0.4
$ make

「redis-server」「redis-cli」が生成されたのを確認してください。

設定の変更

Redisの設定ファイル「redis.conf」に最小限の設定をしておきます。以下の設定項目を環境に合わせて変更してください。

daemonize:
Redisサーバーをデーモンとして起動する場合は、daemonizeオプションを変更します。
dir:
メモリのダンプファイルが作成されるディレクトリを指定します。
maxmemory:
メモリ上に保持する最大サイズを指定します。Redisをキャッシュサーバーとして利用する場合や、開発環境で他のサーバープログラムと同居させる場合など、必要に応じて設定してください。

サーバーの起動

引数に設定ファイルを指定してRedisサーバーを起動します。設定ファイルを指定しないとデフォルトの設定が適用されるので注意してください。

$ ./redis-server redis.conf

以上でRedisのインストールとサーバーの起動が完了しました。

基本的な操作

コマンドラインクライアントの導入

Redisのコマンドラインクライアントである「redis-cli」を使うと、稼働中のRedisサーバーに接続して各種コマンドをインタラクティブに実行することができます。

Redisをコンパイルしたディレクトリで、次のようにredis-cliを起動してください。

$ ./redis-cli
redis>

自動的にローカルのサーバーに接続し、プロンプトが表示されてコマンドを入力できる状態になります。

文字列の格納と参照

まずは、GETコマンドとSETコマンドを実行してみてください。

redis> SET mykey hello
OK
redis> GET mykey
“hello”

これでキー⁠mykey⁠に文字列⁠hello⁠が格納されました。

なお、GETとSETコマンドは文字列を操作するコマンドであるため、他の型に対して実行するとエラーになります。このようにコマンドによっては操作できる型が限定されることがありますので注意してください。

キーの削除

キーの削除にはDELコマンドを使います。DELコマンドは型に関係なく、すべてのキーを削除できます。

redis> DEL mykey
(integer) 1
redis> GET mykey
(nil)

インクリメント・デクリメント

数値を表す文字列に対しては、INCR/DECRコマンドでインクリメントとデクリメントができます。

redis> GET mynum
(nil)
redis> INCR mynum
(integer) 1
redis> INCR mynum
(integer) 2
redis> DECR mynum
(integer) 1

増減の量を指定したい場合は、INCRBY/DECRBYコマンドを実行します。

redis> GET mynum
(nil)
redis> INCRBY mynum 100
(integer) 100
redis> INCRBY mynum 100
(integer) 200
redis> DECRBY mynum 100
(integer) 100

キーのタイムアウト

memcachedのexpireと同様の仕組みとして、既存のキーにタイムアウトを設定するEXPIREコマンドが用意されています。EXPIREコマンドでは、タイムアウトを秒単位で指定します。

次の例では、文字列をセットしてからタイムアウトを10秒で設定し、その後キーが消えるのを確認しています。

redis> SET mykey something
OK
redis> EXPIRE mykey 10
(integer) 1
redis> GET mykey
"something"
redis> GET mykey
"something"
redis> GET mykey
(nil)

この例のように、単純にSETと同時にEXPIREするだけであれば、SETEXコマンドも使用できます。

redis> SETEX mykey 10 something
OK

はまりどころとして、バージョン2.0では、タイムアウトを設定した値を変更しようとすると元の値がクリアされるという仕様があります。次の例を見てください。

redis> SET mynum 10
OK
redis> EXPIRE mynum 100
(integer) 1
redis> INCR mynum
(integer) 1
redis> GET mynum
"1"

“mynum⁠⁠10⁠の状態でタイムアウトを設定し、その後インクリメントしようとしています。直感的には最後の結果は⁠11⁠になりそうですが、タイムアウト設定後に値を変更しようとしているため、元の⁠10⁠はクリアされて、結果としてインクリメント後の結果は⁠1⁠になってしまいます。

この仕様は、Redisのレプリケーション機能がmasterとslaveでそれぞれタイムアウトを制御していることによる不整合を回避するためのものです。

バージョン2.2ではタイムアウトがmaster側で一元的に管理されるようになり、タイムアウト設定後のバリューも継続して変更可能となるようです。タイムアウトの詳細な仕様については公式のドキュメントを参照ください。

DBの選択

Redisのデータセットは、DB index(デフォルトでは0~15)で表されるDBによって分割されています。サーバーに接続した時点では必ず⁠0⁠のDBを参照するようになっており、参照先のDBを選択するにはSELECTコマンドを実行します。

次の例では、異なるDB(⁠⁠0⁠⁠2⁠⁠)に同じキー名⁠mykey⁠の値を格納しています。

redis> SET mykey ABCDEFG
OK
redis> SELECT 2
OK
redis> SET mykey 1234567
OK
redis> SELECT 0
OK
redis> GET mykey
"ABCDEFG"

DB選択の利用例としては、開発環境上で複数の開発メンバーでRedisサーバーを共有するために、各メンバーごとに個別のDBを割り当ててキーの干渉を防ぐことが挙げられます。

複数コマンドのアトミック実行

Redisは、複数のコマンドをアトミックに実行するMULTI/EXECという仕組みを備えています。次のケースを考えてみましょう。

  • ウェブページのアクセス数をカウントするキー“counter”がある。
  • このカウンタの現在値を取得し、同時に“0”にリセットしたい。

この場合、現在値を取得するGETと、⁠0⁠にリセットするSETがアトミックに処理されないと、カウントの取りこぼしが発生してしまいます[1]⁠。これをMULTI/EXECで実装すると次のようになります。

redis> MULTI
OK
redis> GET counter
QUEUED
redis> SET counter 0
QUEUED
redis> EXEC
1. "10000"
2. OK

MULTIに続くコマンドはすぐには実行されず、キューに積まれた状態になります(QUEUED⁠⁠。最後にEXECを実行することによって、キューに積まれたすべてのコマンドがアトミックに実行されます。この例ではEXECの結果が2つ返っていますが、一つ目が最初のGETの結果(⁠⁠counter⁠の現在値)で、二つ目がSETの結果になっています。

なお、MULTI/EXECはトランザクション処理として実装されているわけではありません。例えば、EXECで複数のコマンドを実行中にエラーが発生してもロールバックされず、単純に残りの処理が継続して実行されてしまう点に注意してください。

他のMULTI/EXEC関連のコマンドとしては、キューに積まれたコマンドをキャンセルするDISCARDや、バージョン2.1以降では、CAS操作を実現するWATCHなどがあります。

キーの検索

Redisに大量のデータを格納するようになると、キー名の一部が分かっていて、それに該当するキーを検索したいという場面がよくあります。KEYSコマンドを使えば、globスタイルのパターンマッチングによって現在のデータセットから該当するキー名の一覧を得ることができます。

例として、キー名が次のフォーマットで設計されているとします。

user:ユーザID:属性名

このとき、ユーザID ⁠123⁠に関するキーは次のように取得できます。

redis> KEYS user:123:*
1. "user:123:age"
2. "user:123:location"
3. "user:123:name"

次に、属性⁠location⁠に該当するキーを検索してみます。

redis> KEYS user:*:location
1. "user:123:location"
2. "user:456:location"
3. "user:252:location"

この例は小規模なものですが、本番稼働中の大規模なデータセットで実行した場合、全キーのスキャンにかかるコストが大きいため、サービスのパフォーマンスが低下する恐れがあります。あくまでも開発中や本番環境の調査時などの使用にとどめた方が良いでしょう。

まとめ

今回は、Redisサーバーのインストールから、コマンドラインクライアント「redis-cli」を使った基本的な操作、さらにタイムアウトやキー検索などRedis特有の重要な機能について説明しました。

次回からは、Redisの「data structure server」の側面である各種データ型について掘り下げていきます。

おすすめ記事

記事・ニュース一覧