Redisの使い方

Redisの使い方を書籍で勉強したので,まとめておく。

Redisとは

メモリ上にKey-Valueストア(KVS)を構築することができるソフトウェアの一つ。
KVSは任意の保存したいデータ(値:value)に対し,対応する一意の標識(キー:key)を設定し,これらをペアで保存するデータベースの一種で,Redisはコンピュータのメインメモリ上にKVSを構築し,外部のプログラムからデータの保存と読み出しができる。
保存する値(value)として様々なデータ構造を利用することができ,文字列,バイナリデータ,リスト,集合(セット),ハッシュなどを保存することができる。

型名格納されている情報データ構造の読み書き機能
STRING文字列,整数,浮動小数点数文字列全体,文字列の一部の操作,整数や浮動小数点数のインクリメント/デクリメント
LIST文字列の連結リスト両端の要素のプッシュ,ポップ,オフセットによるトリミング,個々/複数の要素の読み出し,値による要素の探索,削除
SET一意な文字列の順序のないコレクション個々の要素の追加,フェッチ,削除,メンバーかどうかのチェック,積集合,和集合,差集合,ランダムな要素のフェッチ
HASH順序のないキーと値のハッシュテーブル個々の要素の追加,フェッチ,削除,ハッシュ全体のフェッチ
ZSET浮動小数点数のスコア順に並べられた文字列メンバーからスコアへのマッピング個々の要素の追加,フェッチ,削除,スコアの範囲,メンバーの値に基づく要素のフェッチ

Redisの特徴と用途

Redisは,メモリ上で動作するキー・バリュー型の揮発性データベースである。揮発性と聞くと,Redis自身が停止したり,Redisが動作しているハードの電源が切れたりすると,Redisに保存されているデータは消失してしまうように思われるが,Redisはデータをディスクに書き込み,永続化させる機能も持ち合わせているのでそれを回避できる。特徴としては,メモリ上にデータを格納するので,非常に高速にデータの書き込み・読み込みを行うことができる。キャッシュ用のデータベースとしても優れているが,単体でもデータストアとして利用可能なように設計されており,100を超える様々なコマンドを備えている。

レプリケーションによる負荷分散

Redisには,他のコンピュータに複製を作る機能があり,更新が可能な1台の「マスター」と,その複製である読み出し専用の複数台の「スレーブ」という構成にすることで大規模化を図ることができる。この負荷分散の方法を「レプリケーション」と呼ぶ。

データの永続化

Redisには,データを永続化(ディスクへの書き込み)を行う仕組みとして,SnapshotとAppend Only Fileの2つの方法が用意されている。

スナップショット(Snapshot)

スナップショットでは,設定が有効な場合,Redisは定期的にデータベースの内容をディスクに出力する。Redisを再起動すると,このファイルからデータが読み込まれ復元される。一定回数の更新・一定間隔でディスクにファイルを出力する。ファイルの出力タイミングは設定ファイル,CONFIGコマンドで変更可能である。出力は非同期で行われるため,プロセスがクラッシュした場合には前回のスナップショット以降のデータが失われる可能性があるので,多少のデータロスは許容できる必要がある。手動でスナップショットを保存する場合は,SAVEコマンドまたはBGSAVEコマンドで行うことができる。出力されたファイルの形式はバイナリとなる。

スナップショットの設定項目(/etc/redis.conf)
設定項目内容書式
saveデータベースをディスクに保存するタイミングを設定することができる。与えられた秒数経過するか,指定された回数分,書き込み命令を受け付けるとデータベースを保存する。save seconds changes
rdbcompression.rdb形式のデータベースにダンプするときに,圧縮するかどうかを設定することができる。デフォルトでは’yes’になっており,常に圧縮するようになっている。もし保存時にCPUパワーを節約したい場合は’no’を設定する。rdbcompression yes
dbfilenameDBをダンプするときのファイル名を指定する。dbfilename dump.rdb
dir作業ディレクトリを設定します。DBは,このディレクトリ内に,dbfilename設定ディレクティブで設定された名前で書き出される。追記専用ファイルモードもこのディレクトリ内に作成される。dir ./

追記専用ファイル(Append Only File)

Append Only Fileは,書き込み操作を全てログファイルに記録する。スナップショットでのデータロスの可能性を許容できない場合にこれを使う。スナップショットと併用可能で,ドキュメントではAppend Only Fileの単体運用は推奨されていない。スナップショットと併用した場合,再起動時にはAppend Only Fileの方が使用される。ファイル出力タイミングは設定で変更可能で,デフォルトでは1秒毎となっている。出力されるファイルの形式はテキストで,ファイルサイズはどんどん肥大化していくので,定期的に再構成する必要がある。バージョン2.2までは手動でBGREWRITEAOFコマンドを実行し,再構成する必要があったが,バージョン2.4からは自動的に再構成を実行できるようになった。

設定項目内容書式
appendonlyもしデータが大切で,データを失いたくないのであれば,これを有効にすべきである。このモードが設定されると,Redisはappendonly.aofに書き込み操作を受け取るたびにすべて記録していく。このファイルは起動時に全データセットをメモリ内に構築していくときに読み込まれる。appendonly yes
appendfilename追記専用ファイルの名前を設定する。デフォルトはappendonly.aofである。appendfilename appendonly.aof
appendfsyncオペレーティングシステムに対して,出力バッファにデータが貯まるのを待つのではなく,データをディスクに書き出すように指示することができる。OSによっては実際にデータをディスクに書き出したり,なるべく速く書き出すようにしたりする。Redisは次の3つのモードをサポートしている。no:fsyncしない。データの書き出しはOSに任せるので,高速に動作する。always:追記専用ログに書き込むたびにfsyncを行う。低速だが安全に動作する。everysec:最後のfsyncから1秒経過するとfsyncを行う。上記の2つの中間に位置する。appendfsync everysec
no-appendfsync-on-rewriteAppend Only Fileのfsyncポリシーがalwaysかeverysecに設定されており,バックグラウンドのセーブ用のプロセス(バックグラウンドのセーブか,Append Only Fileのログのバックグラウンド書き込み)がディスクに対して大量のI/Oを発生していたとすると,Linuxの設定によっては,fsync()呼び出し時にRedisが長時間ブロックしてしまう可能性がある。現在では修正方法がないため,別スレッドのfsync呼び出しは,同期的な書き込みの呼び出しまでブロックさせてしまう。このオプションを使うと, BGSAVEやBGREWRITEAOFが実行中は,メインのスレッドではfsync()呼び出しが行われないようになり,この問題を回避することができる。これはつまり,他の子スレッドが保存している間は,appendfsync noneが設定されているのと同じ動作をするようになるため,利用者の視点で説明するとすれば,クラッシュした場合に,最悪のシナリオを想定すると,最大で30秒のログが失われる可能性があるということだ。もし遅延時間の問題を持っているのであれば,yesを設定する。そうでない場合には,安全性の観点からnoを選択して,この問題は放置するようにする。no-appendfsync-on-rewrite no
 

Redisの使い方

今回はredis-cliからの使用方法と,PHP言語からの使用方法の2つを説明する。redis-cliとは,Redisをインストールしたときに付属するクライアントプログラムである。ちなみにRedisには,redis-serverというサーバプログラムも付属している。

初めにyumコマンドやapt-getなどのコマンドを使ってRedisをインストールし,Redisを起動する。

#Redisがインストールされているか確認する
which redis
sudo find / -name redis

#インストールされていなければ,Redisをインストールする
sudo yum --enablerepo=epel install redis

#Redisを起動する
sudo redis-server /etc/redis.conf

#Redisが起動したことを確認する
ps aux | grep redis

#Redisが自動起動するように設定する
sudo chkconfig redis on

ちなみにRedisを終了させたいときはRedisをインストールしたときに付属するredis-cliというRedisのクライアントプログラムからshutdownコマンドを実行することで終了させることができる。

redis-cliからRedisを使ってみる

redis-cliからRedisを使う方法を説明する。

redis-cliからRedisに接続し,データの書き込み・読み込みを行う。

#Redisに接続する Redisはデフォルトでは,6379番ポートをリッスンしている
redis-cli

#データの保存
#set key value
set wanko bow-wow 
+OK

#データの読み出し
#get key
get wanko
"bow-wow"

#データの削除
#del key
del wanko
(integer) 1

#キーに有効期限を設定したい場合はsetexを利用する
#setex key expires value
setex wanwan 60 wow
+OK

get wanwan
wow

#60秒後にはデータが消えている
get wanwan
(nil)

単純な文字列型データだけではなく,リスト型のデータを操作することもできる

#dogというリストを作成し,先頭にfooというデータを追加
#lpush key value
lpush dog wan
:1

#dataというリストの先頭にbarというデータを追加
lpush dog wow
:2

#dataというリストの先頭(0)から末尾(-1)までを取得
#lrange key start end
lrange dog 0 -1
1) "wow"
2) "wan"

#dogというキーに紐付くデータを削除
del dog
(integer) 1

Redisで利用出来るコマンドには以下のようなものがある。

データ型コマンド名コマンド内容引数
文字列型SETkeyにvalueを保存するkey, value
文字列型SETEXkeyにvalueをexpires付きで保存するkey, expires, value
文字列型GETkeyに対応する値を取得するkey
リスト型LPUSHkeyに対応するリストの先頭にvalueを加えるkey, value
リスト型RPUSHkeyに対応するリストの末尾にvalueを加えるkey, value
リスト型LLENkeyに対応するリストの要素数を返すkey
リスト型LRANGEkeyに対応するリストの指定したindex範囲(start..end)の要素を返すkey, start, end
リスト型LTRIMkeyに対応するリストを指定したindex範囲(start..end)にトリムするkey, start, end
リスト型LINDEXkeyに対応するリストのindexにある要素を返すkey, index
セット型SADDkeyに指定されたmemberを保存するkey, member
セット型SCARDkeyに対応する要素の数を返すkey
セット型SMEMBERSkeyに対応するセット内のすべてのメンバを返すkey
セット型SUNION指定されたkey1, key2, …の和集合を返すkey1, key2, …
セット型SINTER指定されたkey1, key2, …の積集合(共通メンバ)を返すkey1, key2, …
ソート済みセット型ZADDkeyに対して,指定されたmemberをscoreに保存するkey, score, member
ソート済みセット型ZRANGEkeyに対応する要素のうち,指定したindex範囲(start..end)の要素を返すkey, start, end
ソート済みセット型ZRANGEBYSCOREkeyに対応する要素のうち,指定したスコア範囲(min..max)の要素を返すkey, min, max
ハッシュ型HSETkeyに対応するハッシュの指定されたfieldにvalueを保存するkey, field, value
ハッシュ型HGETkeyに対応するハッシュの指定されたfieldに対応する値を返すkey, field
ハッシュ型HKEYSglob形式のパターンを使って,存在するfieldの一覧を返すglob形式のfieldパターン
ハッシュ型HEXISTSkeyに対応するハッシュ内に指定したfieldがあれば1を,無ければ0を返すkey, field
ハッシュ型HDELkeyに対応するハッシュ内のfieldを削除するkey, field
型によらずDELkeyに対応するデータを削除するkey
型によらずKEYSglob形式のパターンを使って,存在するkeyの一覧を返すglob形式のパターン 例)user:*
型によらずEXISTS指定されたkeyが存在すれば”1″を,無ければ”0″を返すkey
型によらずRENAMEkeyをold_keyからnew_keyにリネームするold_key, new_key
型によらずTYPE指定されたkeyに対応するデータの型を返すkey
 

PHPからRedisを使ってみる

PHPからRedisを使う方法を説明する。PHPからRedisに接続するためのモジュールは,主にpredisとphpredisの2つがある。この2つの大きな違いは,predisはphpで普通に実装が行われているのに対し,phpredisはPHPのエクステンション(C言語)で実装されていることである。これらがやっていることが,ほとんど同じ内容なのであれば,C言語で作られたモジュールの方が動作が速いはずなので,今回はphpredisを使ってPHPからRedisを操作してみる。

#Cコンパイラが必要なのでgccをインストールする
sudo yum install gcc

#Gitでソースを取得する
git clone git://github.com/nicolasff/phpredis.git

cd phpredis

#phpizeとは,エクステンションを追加する際に,phpを最初からコンパイルし直す必要なく,追加するためのコマンド
phpize

#コンパイルする
./configure
make
make install

インストールが完了したら,エクステンションとして読み込ませるために,php.iniにextension=redis.soを追記する。

読み込まれたモジュールにRedisが追加されているかを確認する。

php -m | grep redis

これでphpredisの導入が完了した。
続いて,PHPでRedisの基本操作を行ってみる。

<?php
$redis = new Redis();
$redis->connect("127.0.0.1",6379);

//set(key, value)
$redis->set("dog","baw-baw");

//get(key)
$res = $redis->get("dog");

echo $res;

baw-bawと出力されれば,コードが上手く実行できている。
上記のコードは動作確認済みなので,そのままコピペして試すことができる。

参考
書籍 Redis入門 インメモリKVSによる高速データ管理
書籍 NoSQLデータベース ファーストガイド
書籍 NOSQLの基礎知識 ビッグデータを活かすデータベース技術
ec2にyumでredisをinstall – Qiita
Redisとは 【 Remote dictionary server 】 – 意味/解説/説明/定義 : IT用語辞典
redisドキュメント日本語訳 redis 2.0.3 documentation
PhpRedisでphpからredisを使う – 恥知らずのウェブエンジニア
phpredisのインストール – it-boyの日記