技術の犬小屋

Webプログラミングを餌に生きる犬のメモ帳

Posts in the データベース category

データベースのバックアップについて、あまり意識したことが無かったので、とりあえずメモしておく。
 

ダンプファイルとトランザクションログ

MySQLのデータを完全にバックアップするには、ダンプファイルとトランザクションログが必要である。
以下より、それぞれのファイルの役割について説明する。
 

ダンプファイル

ダンプファイルとは、メモリやレジスタ、ファイル、ディスクなどのある瞬間の中身を丸ごと記録したファイルである。
 
MySQLでは、mysqldumpコマンドを使って、データベースを丸ごとエクスポートすることが出来る。
mysqldumpコマンドは以下の様な書式で記述する。
 
DBのダンプファイルを作成するには、以下のようにする。

mysqldump -u ユーザ名 -p DB名 > 出力先ファイル名

 
ダンプファイルからデータを復元するには、以下のようにする。

mysql -u ユーザ名 -p DB名 < ダンプファイル名

 
通常、ダンプファイルはバッチ処理で定期的に作成する。
 

トランザクションログ

トランザクションログ(データベースログやバイナリログとも呼ばれる)とは、クラッシュやハードウェア故障があったとしてもデータベース管理システムのACID特性を保障するための操作履歴を指す。
定期的にバッチ処理でダンプファイルを作成していても、いざデータベースへの障害が起こった場合、ダンプファイルの作成から時間が経過していればしているほど、データの巻き戻りが多く発生してしまうが、トランザクションログを追いかけることで直近で発行されたSQLを調べることが出来、巻き戻りを無くすことが出来る。
 
MySQLでは、MySQLの設定ファイルであるmy.cnfファイルに以下の設定を追加することでトランザクションログを保存することが出来る。

log-bin=mysql-bin

 
追加で以下を書いておくと、直近の7日分のみを保存することが出来る。
トランザクションログが肥大化すると、かなり容量を食うので書いておくことを推奨する。

expire_logs_days=7

 
 
以上
 
 
参考
ダンプファイルとは 〔 .dmpファイル 〕 〔 dmpファイル 〕 – 意味/解説/説明/定義 : IT用語辞典
トランザクションログ – Wikipedia
mysql binlogからDB復旧 – Qiita
MySQLのdump(ダンプ)でデータをバックアップ/復元する MySQL基礎の基礎 – 久保清隆のブログ

Amazon DynamoDBでデータベースを構築する方法を勉強したのでメモしておく。
 

Amazon DynamoDBでデータベースを作成する

AWS Management Consoleにログインしたら,Amazon DynamoDBを選択する。
画面右上のメニューから使用するリージョンを選択する。今回はAsia Pacific (Tokyo)を選択する。
画面中央のCreate Tableを選択する。
 

PRIMARY KEYフェイズ

テーブル名とプライマリキー(主キー)についての情報を入力する。

入力項目 詳細
Table Name テーブルに付けたい名前を入力する。
Primary Key Type プライマリキーの型を選択する。Hashでは,キーだけで一意に決定して検索することができる。Hash and Rangeでは,キー + 範囲で一意に決定して検索することができる。
Hash Attribute Name Hashのカラム名を入力し,フィールドに格納出来る型を選択する。Range Attribute Nameの項目と同じカラム名を使用することは出来ない。
Range Attribute Name Rangeのカラム名を入力し,フィールドに格納出来る型を選択する。Hash Attribute Nameの項目と同じカラム名を使用することは出来ない。

 
各項目を入力し終わったら,Continueを選択する。
 

Add Indexesフェイズ

オプションとして,テーブルにインデックスを最大で5つまで追加することができる。

入力項目 詳細
Index Type インデックスの種類を選択する。Local Secondary Indexでは,特定のプライマリキーのハッシュ値に関連付けられるのに対し,Global Secondary Indexでは,このような制約はない。つまり,Local Secondary Indexは同じパーティション上に保存される項目だけを対象として実行するのに対し,Global Secondary Indexはテーブルのすべての項目が対象となる。
Index Hash Key Hashのキーに対してのインデックス値を設定する。
Index Range Key Rangeのキーに対してのインデックス値を設定する。
Index Name インデックスに付ける名前を入力する。
Projected Attributes 射影する属性(カラム名)を選択する。テーブルの属性の全て(All Attributes),もしくは一部(Table and Index Keys,Specify Attributes)を射影するかを選択することができる。Local Secondary Index(LSI)・Global Secondary Index(GSI)にコピーされる一連の属性を「射影」と呼ぶ。これはテーブルにある属性のうち,LSI・GSIに直接コピーされる属性のリストである。LSI・GSIにコピーされた属性は,テーブルの全項目を含むプライマリインデックスからデータを取得することなく,迅速に取得することができる。

 
各項目を入力し終わったら,Continueを選択する。
 

PROVISIONED THROUGHPUT CAPACITYフェイズ

DynamoDBの処理能力を設定することができる。

入力項目 詳細
Read Capacity Units 1秒間辺りの読み込み性能に影響する指標。
Write Capacity Units 1秒間辺りの書き込み性能に影響する指標。

 
上記の指標は以下のような式に基づいて,DynamoDBの性能に影響を与える。
 

Read Capacity Units

Read Capacity Units = 1秒間に読み込まれるアイテム数 * (アイテムのKB単位の容量 / 4)
 

Write Capacity Units

Write Capacity Units = 1秒間に書き込まれるアイテム数 * アイテムのKB単位の容量
 
上記2つの式では,どちらもアイテムのKB単位の容量は,最も近いKBに切り上げる必要がある。
 

THROUGHPUT ALARMSフェイズ

Amazon DynamoDBに設定されている,Read Capacity Units,もしくはWrite Capacity Unitsがスループットの限界に近づいた時に通知するかどうかを設定することができる。
 
Use Basic Alarmsにチェックを付けることで,メールアドレスへの通知設定を有効にする。
75%~95%の間で設定できる値は,読み込み・書き込みのキャパシティのどれくらいが使われている場合に通知するかを設定する。
Send notification toには通知先のメールアドレスを入力する。
ちなみに,Notification will be sent whenには,PROVISIONED THROUGHPUT CAPACITYフェーズで入力した,Read Capacity UnitsとWrite Capacity Unitsの値に基づいて,ユニット消費数の目安となる数値が反映されている。
 
各項目を入力し終わったら,Continueを選択する。
 

SUMMARYフェーズ

設定を確認し,Createを選択する。
 
 
以上
 
 
参考
DynamoDB の基礎知識とまとめ – Qiita
Pairy : チャットデータを Redis から Amazon DynamoDB に全移行した話(2) 〜DynamoDB導入事例〜 – Pairy Tech Blog
Amazon DynamoDB ~DynamoDBについて~ |dynamo db とは 意味 | ナレコムAWSレシピ
Amazon Web Services ブログ: 【AWS発表】 Amazon DynamoDBでグローバルセカンダリーインデックスを利用可能に
よくある質問 – Amazon DynamoDB (フルマネージドNo SQLデータベースサービス) | アマゾン ウェブ サービス(AWS 日本語)
Amazon DynamoDB(初心者向け 超速マスター編)JAWSUG大阪

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

Redisとは

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

Redisの5種類のデータ構造
型名 格納されている情報 データ構造の読み書き機能
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
dbfilename DBをダンプするときのファイル名を指定する。 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からは自動的に再構成を実行できるようになった。
 

Append Only Fileの設定項目(/etc/redis.conf)
設定項目 内容 書式
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-rewrite Append 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で利用できるコマンドの抜粋
データ型 コマンド名 コマンド内容 引数
文字列型 SET keyにvalueを保存する key, value
文字列型 SETEX keyにvalueをexpires付きで保存する key, expires, value
文字列型 GET keyに対応する値を取得する key
リスト型 LPUSH keyに対応するリストの先頭にvalueを加える key, value
リスト型 RPUSH keyに対応するリストの末尾にvalueを加える key, value
リスト型 LLEN keyに対応するリストの要素数を返す key
リスト型 LRANGE keyに対応するリストの指定したindex範囲(start..end)の要素を返す key, start, end
リスト型 LTRIM keyに対応するリストを指定したindex範囲(start..end)にトリムする key, start, end
リスト型 LINDEX keyに対応するリストのindexにある要素を返す key, index
セット型 SADD keyに指定されたmemberを保存する key, member
セット型 SCARD keyに対応する要素の数を返す key
セット型 SMEMBERS keyに対応するセット内のすべてのメンバを返す key
セット型 SUNION 指定されたkey1, key2, …の和集合を返す key1, key2, …
セット型 SINTER 指定されたkey1, key2, …の積集合(共通メンバ)を返す key1, key2, …
ソート済みセット型 ZADD keyに対して,指定されたmemberをscoreに保存する key, score, member
ソート済みセット型 ZRANGE keyに対応する要素のうち,指定したindex範囲(start..end)の要素を返す key, start, end
ソート済みセット型 ZRANGEBYSCORE keyに対応する要素のうち,指定したスコア範囲(min..max)の要素を返す key, min, max
ハッシュ型 HSET keyに対応するハッシュの指定されたfieldにvalueを保存する key, field, value
ハッシュ型 HGET keyに対応するハッシュの指定されたfieldに対応する値を返す key, field
ハッシュ型 HKEYS glob形式のパターンを使って,存在するfieldの一覧を返す glob形式のfieldパターン
ハッシュ型 HEXISTS keyに対応するハッシュ内に指定したfieldがあれば1を,無ければ0を返す key, field
ハッシュ型 HDEL keyに対応するハッシュ内のfieldを削除する key, field
型によらず DEL keyに対応するデータを削除する key
型によらず KEYS glob形式のパターンを使って,存在するkeyの一覧を返す glob形式のパターン 例)user:*
型によらず EXISTS 指定されたkeyが存在すれば”1″を,無ければ”0″を返す key
型によらず RENAME keyを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の日記

memcachedについて,書籍を読んで勉強したので使用方法をまとめておく。
 

memcachedとは

memcachedは,分散メモリキャッシュシステムを構築することができるソフトウェアの一つ。データベースの読み出し結果などをメモリに保存し、次に同じデータが参照されたときにメモリから即座に返すことができる。複数のコンピュータにまたがる巨大な分散キャッシュシステムを構築でき、台数を増やすことで性能を向上させることができるため、大規模なWebサービスなどでよく用いられる。
 

memcachedの特徴と用途

memcachedは,メモリ上で動作するキー・バリュー型の揮発性データベースである。揮発性なので,memcached自身が停止したり,memcachedが動作しているハードの電源が切れたりすると,memcachedに保存されているデータは消失してしまう。そのため,消えてしまっては困るようなデータを保存することはできない。memcachedはメモリ上にデータを格納するので,非常に高速にデータの書き込み・読み込みを行うことができる。
以上に挙げた特徴から分かるように,memcachedはキャッシュを行うような場面において,その真価を発揮する。memcachedの具体的な用途としては,MySQLやPostgreSQLのようなRDBと組み合わせて,キャッシュ用のデータベースとして使用することで,RDBにかかる負荷を抑えることができる。
 

コンシステント・ハッシングによる負荷分散

memcachedは,コンシステント・ハッシング(Consistent Hashing)と呼ばれるアルゴリズムによってデータ分割・割り当て(負荷分散)を行う。
このアルゴリズムでは,分散型システムを構成する各ノード(memcached)が,論理的にリング(輪)を形作るように配置される。
以下がコンシステント・ハッシングの図である。
 
コンシステント・ハッシングの図
 
図では,4つのノード(memcached)を均等に分散配置している。データのキーの値はハッシュ関数によって求められ,ハッシュ関数を使った演算は,不規則な発番(整理番号の付与)を行う方法として広く利用されている。このようにキーの値として,ハッシュ値を得ることによってキーの値が特定の値に偏ることなく,広く均等に拡散するようになる。
そして,その整理番号に従って,リングの各スペースにキーを割り当てる。キーが割り当てられたスペースを時計回りで進み,そこで最初に配置されているノードにデータを書き込む。コンシステント・ハッシングはこのようなルールのアルゴリズムである。
 

CAS操作によるアトミック性の実現

memcachedにおいて,アトミック性(原子性)を実現するにはCAS操作を行う必要がある。アトミック性とは,トランザクションに含まれるタスクが全て実行されるか、あるいは全く実行されないことを保証する性質をいう。このような性質は,MySQLやPostgreSQLのようなRDBでは標準的に対応しているが,memcachedにおいては,CAS操作と呼ばれる処理を行わなければ,対応することができない。
アトミック性(原子性)が保障されない場合,どのようなことが起こり得るか,簡単な例を示す。
以下の例では,「プロセス1」と「プロセス2」の2つのプロセスが1つのカウンタに対して数値を足している。
 
プロセス1 現在のカウンタの値を取得する …… カウンタの値:0
プロセス1 カウンタの値を1増やす ……………… カウンタの値:1
プロセス2 現在のカウンタの値を取得する …… カウンタの値:0
プロセス1 カウンタの値を保存する …………… カウンタの値:1
プロセス2 カウンタの値を1増やす …………… カウンタの値:1
プロセス2 カウンタの値を保存する …………… カウンタの値:1
 
上記の例では,本来はカウンタの値が2になることを期待しているが,最終的にカウンタの値は1になってしまっている。CAS操作を行わない場合はこのようなことが起こり得る。
 

memcachedの使い方

今回はtelnetからの使用方法と,PHP言語からの使用方法の2つを説明する。
初めに,yumコマンドやapt-getなどのコマンドを使って,memcachedをインストールし,memcachedを起動する。

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

#インストールされていなければ,memcachedをインストールする
sudo yum install -y memcached

#memcachedのリッスンするポートの変更やメモリの割り当てなどを変更することもできる
sudo vi /etc/sysconfig/memcached

#memcachedを起動する
sudo service memcached start

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

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

 

telnetからmemcachedを使ってみる

telnetからmemcachedを使う方法を説明する。まずは,yumやapt-getなどのコマンドを用いてtelnetのインストールを行う。

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

#インストールされていなければ,telnetをインストールする
sudo yum install -y telnet

 
telnetからmemcachedに接続し,データの書き込み・読み込みを行う。

#telnetでmemcachedに接続する memcachedはデフォルトでは,11211番ポートをリッスンしている
telnet localhost 11211

#データの保存
#set key,flag,expires,byte[改行]
#value
set foo 0 100 3
bar

#データの読み出し
get foo

 
いろいろ操作を行ってみる。

#データの保存
set counter 0 0 1
1

#加算(increment)
#+1
incr counter 1

#減算(decrement)
#-1
decr counter 1

#データの保存
set test 0 0 4
test

#データの先頭へ追加
prepend test 0 0 3
bow

#データの末尾へ追加
append test 0 0 5
wanko

#データの削除
delete test

#memcached上のすべてのデータを削除
flush_all

 

名前 説明 注意点
flag データを圧縮するかどうかの指定。0:非圧縮,1:圧縮
expires データをいつまで保持するかをUNIXタイムスタンプもしくは現在からの秒数で指定する 現在からの秒数は30日(60*60*24*30=2592000)を超えることはできない。0を指定すると有効期限無し(半永久的に保持)になる。
byte valueとして保存するデータのバイト数を指定する

 

PHPからmemcachedを使ってみる

PHPからmemcachedを使う方法を説明する。今回はApacheとPHPが既にインストールされているという前提で話を進める。
 
まずは,PECLのmemcachedライブラリをインストールする。

#PHPからmemcachedを使うためのライブラリをインストールする
sudo yum install -y php-pecl-memcached

 
続いて,memcachedにデータを書き込むPHPプログラムと,memcachedからデータを読み込むPHPプログラムを作成する。
 

<?php
//memcachedにデータを書き込むPHPプログラム
$m = new Memcached();
$m->addServer('localhost', 11211);
$m->set('key', 'wanko', 60); // キー,バリュー,有効期限(秒)

 

<?php
//memcachedからデータを読み込むプログラム
$m = new Memcached();
$m->addServer('localhost', 11211);
if ($val = $m->get('key')) {
    echo $val;
}

 
上記のプログラムでは,keyというキーに対して,wankoというバリューを格納し,1分間だけmemcachedが情報を保持している。
 

CAS操作の実践

CAS操作では,getsとcasという2つのコマンドを使ってデータの不整合を発生させないようにする。getsはデータを読み出すコマンド,casはデータを保存するコマンドである。まず,getsコマンドを使うとデータだけでなく,cas idと呼ばれる値も取得できる。cas idはそのデータ識別する一意の値であり,データが更新されると必ず変更される。そして,データの保存時にはcasコマンドに対して保存するデータと一緒にcas idを渡す。このとき,casコマンドに渡されたcas idと,現在のデータを表すcas idが一致したときのみ保存が行われる。cas idが一致しない場合には,getsコマンドで取得してからデータが変更されているということであり,データの保存は失敗する。このように,保存時にそのデータが別のプロセスによって変更されていないかを確認することで,データの不整合が発生しないようにしている。
 

telnetからCAS操作を行ってみる

telnetでCAS操作を行うと,以下のようになる。

#データの保存
#set key,flag,expires,byte[改行]
#value
set hoge 0 1500 10 
1111111111
STORED

#数値の1111111111とcas id(6)を取得できる
gets foo
VALUE hoge 0 10 6
1111111111
END

#cas idを渡して,新しい値に書き換える
cas foo 0 1500 10 6
2222222222
STORED

 
上記では,4~6行目にてデータの格納を行い,9~12行目でデータの取得とcas idの取得を行っている。更に15~17行目でkey, flag, expires, byte, cas idを渡し,値を書き換えている。
 

PHPからCAS操作を行ってみる

PHPでCAS操作を行うと,以下のようになる。

<?php
$m = new Memcached();
$m->addServer('localhost', 11211);

//memcachedからデータを取得
//キー,コールバック関数名,CASトークンを格納する変数
$data = $m->get('key', null, $cas);

//get()で,キーが見つからなかった場合は新たにキーとデータを追加する
if ($m->getResultCode() == Memcached::RES_NOTFOUND) {

    //キー,バリュー,有効期限(秒)
    $m->add('key', 'value', 60);

//get()で,キーが見つかった場合は,CASトークンを使ってデータを更新する
} else { 

    //CASトークン,キー,バリュー,有効期限(秒)
    $m->cas($cas, 'key', 'value', 60);

}

 
これはこちらのページにあったコードを,自分なりに読みやすく書き換えたものである。動作確認済みなので,このままコピペして試すことができる。Memcached::get()はコールバック関数の実行が行えたりと,少し変わった使い方もできるので,こちらのページを参考にして使い方を確認してみてほしい。
 
 
以上
 
 
参考
書籍 NoSQLデータベース ファーストガイド
書籍 NOSQLの基礎知識 ビッグデータを活かすデータベース技術
memcachedとは 【 memory cache daemon 】 – 意味/解説/説明/定義 : IT用語辞典
ACID (コンピュータ科学) – Wikipedia
[CentOS] memcachedをインストールして、PHPから使用する | HAPPY*TRAP
PHP: Memcached::cas – Manual
PHP: Memcached::get – Manual
PHP: Memcached::add – Manual
PHP: Read-through キャッシュコールバック – Manual

Amazon ElastiCacheでキャッシュサーバを作成する方法を勉強したのでメモしておく。
Amazon ElastiCacheでは,エンジンとしてmemcached,もしくはRedisを選択することができ,各キャッシュサーバをクラスタリングして運用することができる。ここでは,クラスタリングされた各キャッシュサーバをノードと呼ぶ。
 

キャッシュクラスタを作成する

AWS Management Consoleにログインしたら,ElastiCacheを選択する。
 
画面右上のメニュー(アカウント管理メニューの隣)から使用するリージョンを選択する。今回はAsia Pacific (Tokyo)を選択する。
 
Launch Cache Clusterを選択し,キャッシュクラスタの作成画面に入る。
 

CACHE CLUSTER DETAILSフェイズ

キャッシュクラスタの詳細情報を入力する。
 

入力項目 詳細
Name キャッシュサーバのクラスタに付けたい名前を入力する。
Engine エンジンとして使用するソフトウェアを選択する。memcached,もしくはredisを指定することができる。
Cache Port 使用するポート番号を指定する。通常はデフォルトのままでもよい。
Engine Version エンジンとして使用するソフトウェアのバージョンを指定する。デフォルトのままでもよい。
Number of Nodes エンジンがmemcachedの場合,クラスタ内で起動するノードの数を入力する。エンジンがredisの場合は入力する必要がない。その理由は,memcachedはレプリケーションをサポートしていないので,「読み取り性能の向上」をクラスタリングで実現しているのに対し,redisはレプリケーションをサポートしているので,クラスタリングをする必要自体が無いためだ。※redisのレプリケーション設定はメニューのReplication Groupsから行うことができる。
Preferred Zone アベイラビリティーゾーンのクラスター版。デフォルトのままでもよい。
Node type 使用するノード(エンジン)のスペックを選択する。
Cache Subnet Group VPCを使用している場合は,指定する必要がある。
Topic for SNS Notification 関連事項で何かがあった場合,指定されたメールアドレスに通知する。通知が必要ない場合は,Disable Notificationsを指定する。
Auto Minor Version Upgrade 指定したエンジンにマイナーバージョンのアップデートが行われた場合に,アップデートを自動的に適用するかを指定する。

 
各項目を入力し終わったら,Nextを選択する。
 

ADDITIONAL CONFIGURATIONフェイズ

キャッシュクラスタの追加情報を入力する。
 

入力項目 詳細
Cache Security Group(s) どのEC2インスタンスからのアクセスを許可するかを設定することができる。Cache Security GroupにEC2のSecurity Groupを登録することで,そのSecurity Groupを使用しているEC2インスタンスからのアクセスを許可することができる。デフォルトのCache Security Groupでは,基本的にアクセスは許可していないので,新たにCache Security Groupを作成する必要がある。
Cache Parameter Group エンジンに使用されるパラメータを設定することができる。デフォルトの状態でも問題ないが,運用するアプリケーションに合わせてチューニングすることが望ましい。
Maintenance Window ElastiCacheのメンテナンスが行われる時間を設定することができる。このメンテナンスは避けることができない。このメンテナンス中はDBエンジンのパッチ適用などが行われるので,メンテナンス中はサービスが停止する可能性がある。そのため,アクセスが少ない時間帯に設定することが望ましい。サービスが停止した場合はキャッシュしていた内容が消失する。

 
各項目を入力し終わったら,Nextを選択する。
 

REVIEWフェイズ

設定を確認し,Launch Cache Clusterを選択する。
 

補足

Amazon ElastiCacheのとっつきにくさは,エンジンの仕様の違いが大きいと思うので,以下にmemcachedとRedisの差異を挙げておく。

memcached Redis
負荷分散 クラスタリングを行うことで,コンシステント・ハッシングによって負荷分散する。 レプリケーションによって負荷分散する。リードレプリカを複数のアベイラビリティゾーンに配置することで高可用性も実現可能。
原子性 サポートされていないが,CAS操作によって実現可能。 サポートされている。
一貫性 サポートされている。 サポートされている。
独立性 不明。おそらくサポートされていない。 不明。おそらくサポートされていない。
永続性 サポートされていない。 Amazon ElastiCacheではサポートされていないが,EC2に配置することでRedisのスナップショットやAppend Only Fileを利用できるので実現可能

 
 
以上
 
 
参考
書籍 NoSQLデータベースファーストガイド
ACID (コンピュータ科学) – Wikipedia
Amazon RDSで仮想DBインスタンスを作成する
RDSインスタンスの設定を変更する
Amazon RDSによるレプリケーションについて理解する | Developers.IO
第1回 データベース・クラスタの概要 | Think IT
ElastiCache for redisを本番導入してみました – SSSSLIDE