PHPアプリケーションのセッション管理にAmazon DynamoDBを使う

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは。望月です。
先日のブログエントリで、冗長化されたWebアプリケーションでのセッション管理にAWS ElastiCacheを利用する方法を紹介しました。

PHPアプリケーションのセッション管理にAWS ElastiCacheを使う

前回のブログを書いた際に私も勘違いをしていたのですが、ElastiCacheのmemcachedを使う方法には一つ欠点があります。ElastiCacheのmemcachedではレプリケーション機能がサポートされていないため、セッション情報が保管されているElastiCacheノードが不調に陥ると、どちらのサーバからもセッション情報を読み取ることができなくなってしまいます。やはり重要なデータはレプリケーションをしたうえで、必ずRead/Writeができる状態で保管しておきたいものです。

そこで登場するのがAmazon DynamoDBです。DynamoDBはAmazonの提供するNoSQLデータベースです。Amazon DynamoDBでは、裏側でAZまたぎのレプリケーションが行われているため、データ損失することはありません。また、I/Oスループットを調節することができるため、高負荷なWebアプリケーションにも対応させることができます。

実は筆者はまだDynamoDBを使ったことがなかったので、DynamoDBをセッションストアとしてPHPから扱う方法にチャレンジしてみました。その方法をまとめておきます。

DynamoDBの構築

まずはManagement ConsoleからDynamoDBのページにアクセスしましょう。画面の中央にある、[Create Table]をクリックします。

Dynamo_1

テーブルの基本情報を入力します。テーブル名はわかりやすく[session]としておきます。次の[Primary Key Type]は"Hash and Range" と"Hash"から選択します。今回はセッション情報を保管するテーブルのため、単一キーでのアクセスになります。そんためRangeキーは必要ないので"Hash"を選択します。Attribute Nameは"id"としておきましょう。

Dynamo_2

次の画面ではSecondory Indexの設定を行います。Secondory Indexって何だろうと思ってドキュメントを読みました。ドキュメントによると、DynamoDBでは、データを取得する際には基本的に先ほど指定したPrimary Keyを設定するのですが、ここでSecondary Indexとして指定されたキーに関しても条件として指定することができるようになるようです。今回は指定しないため、[Continue]を押して次の画面に進みます。

dynamo_12

次の画面で、Read Capacity UnitとWrite Capacity Unitを選択します。Capacity Unitとは、DynamoDBのパフォーマンスの程度を指定する数値です。この数値を大きくすればするほど秒あたりのスループットが向上しますが、ここの数値が課金の対象となっているため注意が必要です。Unitの定義は以下の通りです。

  • 1 Read Capacity Unit = 1秒間あたりの強い整合性の読み込み4KB
  • 1 Write Capacity Unit = 1秒間あたりの書き込み1KB

今回は、Read/Writeともに1で進みます。実際に利用される際はここの数値設定が重要になりますが、後から変更可能な数値なので色々と試してみてください。

Dynamo_3

次の画面は、設定したRead/Write Capacityが限界に近づいてきた時にSNS通知を投げる設定を行うための画面です。今回はひとまず利用しないので、チェックをオフにして先に進みます。

dynamo_5

確認画面なので、先に進みましょう。テーブルが作成されます。

Dynamo_6

以上で、DynamoDBの作成は終了です。簡単ですね!

PHP側の実装

memcachedはネイティブセッションストアとして利用できましたが、DynamoDBをセッションストアとして利用するためには、AWS SDK for PHPに含まれているDynamoDB Session Handlerを利用します。 *1

まずは環境の準備です。以下の様なcomposer.jsonを作成してcomposer経由でAWS SDK for PHPをインストールします。

{
    "require": {
        "aws/aws-sdk-php": "2.*"
    }
}

では、前回も利用したコードを再利用します。以下のような形になりました。

<?php

// DynamoDB対応開始 //
require 'vendor/autoload.php';

use Aws\DynamoDb\DynamoDbClient;
use Aws\DynamoDb\Session\SessionHandler;

$dynamoDb = DynamoDbClient::factory(array(
    'region' => 'ap-northeast-1'
));

$sessionHandler = SessionHandler::factory(array(
    'dynamodb_client' => $dynamoDb,
    'table_name'      => 'session',
));
$sessionHandler->register();

// DynamoDB対応終了 // 

session_start();

echo "This is Web Server 1<br/>";

if (isset($_SESSION["username"])) {
	echo $_SESSION["username"];
} else {
	$_SESSION["username"] = "mochizuki01";
}

session_write_close()

SDKをロードし、DynamoDBSessionHandlerを利用してセッションハンドラに登録することで、php.iniのセッションハンドラ設定を上書きしています。その他の部分は前回と全く同じコードです。1台目のサーバにアクセスしたら"mochizuki01"がセッション情報として登録され、2台目の場合は"mochizuki02"が登録される流れです。

それでは同じ設定のサーバを2台用意し、動作を確認してみましょう。

dynamo_8 dynamo_9

2つのサーバ間でセッションが共有されていることが確認できました。しっかりとDynamoDBにデータが保存されているかどうか、Management Consoleから確認してみましょう。DynamoDBの画面の[Explore Table]ボタンを押すことで、テーブルに保存されている内容を確認することができます。

dynamo_11

DynamoDBにセッションデータが保管されていることが確認できました。

まとめ

今回はAmazon DynamoDBをセッションストアとして利用する方法について紹介しました。AWS SDK for PHPにセッションハンドラクラスが用意されているので、導入は非常に簡単です。DynamoDBをまだ利用されたことがない方も、ぜひ対障害性が高くハイパフォーマンスなDynamoDBを利用してみてはどうでしょうか。

脚注

  1. PHPのセッションハンドラは、SessionHandlerInterfaceを利用すれば、自作することが可能です。