Ubuntu20.04でPHPを使用してMySQLのキャッシュとしてRedisを設定する方法
著者は、 Write for DOnations プログラムの一環として、 Girls WhoCodeを選択して寄付を受け取りました。
序章
Redis(リモートディクショナリサーバー)は、高速なオープンソースのインメモリデータベースであり、高度にスケーラブルでパフォーマンス指向のシステムのキーバリューストアとして使用できます。 Redisのユースケースには、キャッシング、高速トランザクション、リアルタイム分析、ライブ通知、機械学習、検索、キュー/ジョブ処理などがあります。 Redisはメモリ内のKey-Valueストアであるため、そのパフォーマンスにより、アプリケーションでデータをキャッシュするのに適しています。
Caching は、データを一時的に高速ストレージレイヤー(たとえば、コンピューターのRAM)に保存して、クライアントが同じ将来の要求を行ったときにデータをより高速に提供します。 これにより、ディスクから毎回データをフェッチするのではなく、以前に計算されたデータの再利用が強化されます。
PHPおよびMySQLを使用している場合、Redisはハードディスク(HDD)の数倍の速度でデータをRAMに保存するため、キャッシュとしてRedisを使用するとアプリケーションのパフォーマンスが向上します。またはソリッドステートドライブ(SSD)。 キャッシュはまた、データベースのコスト(つまり、バックエンドデータベースに対して行われるラウンドトリップの数)を削減し、バックエンドの過負荷を回避します。
データのキャッシュは、書き込みよりも読み取りが多いWebアプリケーションを設計する場合に不可欠な設計機能です。 このようなアプリケーションには、ブログ、オンラインストア、ソーシャルメディアサイトが含まれます。
このチュートリアルでは、Redisを使用して、Ubuntu20.04でPHPを使用してMySQLデータをキャッシュします。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- sudo権限を持つroot以外のユーザーがいるUbuntu20.04サーバー。 Ubuntu 20.04を使用したサーバーの初期設定ガイドに従って、これを設定します。
- LAMPスタック。 Linux、Apache、MySQL、PHP(LAMP)スタックをUbuntu20.04チュートリアルにインストールする方法に従ってください。 このガイドでは、ステップ4 —Webサイトの仮想ホストの作成をスキップできます。
- Ubuntu20.04にRedisをインストールして保護する方法-クイックスタートチュートリアルに従ってセットアップされたRedisサーバー。
ステップ1—PHP用のRedisライブラリをインストールする
まず、php-redis拡張機能をインストールします。これにより、PHPを使用してRedisと通信できるようになります。 次のコマンドを実行してサーバーを更新し、拡張機能をインストールします。
sudo apt update sudo apt install php-redis
インストールを確認し、Apache Webサーバーを再起動して、拡張機能をロードします。
sudo systemctl restart apache2
依存関係をインストールしたので、データベースをセットアップします。
ステップ2—テストデータベース、テーブル、およびサンプルデータを設定する
このステップでは、データを永続的にディスクに保存するためのMySQLデータベースを作成します。 また、データベースに対する完全な権限を持ついくつかのテーブルとユーザーアカウントを作成します。
まず、rootユーザーとしてMySQLサーバーにログインします。
sudo mysql -u root -p
LAMP前提条件で設定したMySQLサーバーのrootパスワードを入力します。 次に、ENTERを押して続行します。
次に、次のコマンドを使用してtest_storeデータベースを作成します。
CREATE database test_store;
出力を確認して、アクションが成功したことを確認します。
OutputQuery OK, 1 row affected (0.00 sec)
次に、データベースのユーザーを作成します。 このチュートリアルでは、このユーザーをtest_userと呼びます。 PASSWORDも強力なパスワードに置き換えます。
CREATE USER 'test_user'@'localhost' IDENTIFIED WITH mysql_native_password BY 'PASSWORD';
次に、test_userにtest_storeデータベースへの完全な権限を次のように付与します。
GRANT ALL PRIVILEGES ON test_store.* TO 'test_user'@'localhost';
最後に、次のコマンドを実行して、MySQLで許可テーブルを再ロードします。
FLUSH PRIVILEGES;
コマンドが成功するたびに、次の出力が得られることを確認してください。
OutputQuery OK, 0 rows affected (0.01 sec)
MySQLルートセッションを終了します。
quit;
Byeという単語が表示され、サーバーのコマンドラインインターフェイスに戻ります。
作成したtest_userの資格情報を使用してMySQLサーバーに再度ログインします。
mysql -u test_user -p
test_userのパスワードを入力して続行します。 次に、mysql>プロンプトが表示されたら、test_storeデータベースに切り替えます。
USE test_store;
次の出力が表示されることを確認してください。
OutputDatabase Changed.
次に、3列のproductsテーブルを作成します。 product_id列を使用して、各製品を一意に識別します。 IDを手動で割り当てないようにするには、AUTO_INCREMENTキーワードを使用します。 次に、product_id列のBIGINTデータ型を使用して、大きなデータセットをサポートします。 BIGINTデータ型は、最小値-2^63および最大値2^63-1を保持できます。
product_nameフィールドには、アイテムの実際の名前が保持されます。 この場合、50文字の長さのVARCHARデータ型で十分です。 productsテーブルの最後の列はpriceです。DOUBLEデータ型を使用して、小数の価格(たとえば、16.33)に対応します。
productsテーブルを作成するには、次のコマンドを実行します。
CREATE table products ( product_id BIGINT PRIMARY KEY AUTO_INCREMENT, product_name VARCHAR(50), price DOUBLE ) Engine = InnoDB;
次の出力が表示されます。
OutputQuery OK, 0 rows affected (0.01 sec)
次に、テスト用にproductsテーブルにいくつかのレコードを入力します。
AUTO_INCREMENT列がこれを完了するため、product_id列にデータを手動で入力する必要はありません。 次のコマンドを1つずつ実行します。
INSERT INTO products(product_name, price) VALUES ('Virtual Private Servers', '5.00');
INSERT INTO products(product_name, price) VALUES ('Managed Databases', '15.00');
INSERT INTO products(product_name, price) VALUES ('Block Storage', '10.00');
INSERT INTO products(product_name, price) VALUES ('Managed Kubernetes', '60.00');
INSERT INTO products(product_name, price) VALUES ('Load Balancer', '10.00');
各コマンドを実行した後、次の出力が得られることを確認してください。
OutputQuery OK, 1 row affected (0.00 sec)
SELECTコマンドを使用してデータを確認します。
SELECT * FROM products;
次のような出力が表示されます。
Output+------------+-------------------------+-------+ | product_id | product_name | price | +------------+-------------------------+-------+ | 1 | Virtual Private Servers | 5 | | 2 | Managed Databases | 15 | | 3 | Block Storage | 10 | | 4 | Managed Kubernetes | 60 | | 5 | Load Balancer | 10 | +------------+-------------------------+-------+ 5 rows in set (0.00 sec)
test_userのMySQLセッションを終了します。
quit;
test_storeデータベース、productsテーブル、および test_user を設定したら、PHPスクリプトをコーディングして、MySQLデータベースからデータを取得してキャッシュします。 Redis。
ステップ3—MySQLデータをフェッチおよびキャッシュするためのPHPスクリプトを設計する
このステップでは、前のステップで作成したサンプルデータを取得するためのPHPスクリプトを作成します。
スクリプトを初めて実行すると、MySQLから(つまり、ディスクから)データが読み取られ、Redisにキャッシュされます。 その結果、製品のデータの後続の読み取りはRedisから(つまり、システムRAMから)行われます。 システムメモリは最速のソリッドステートドライブよりも数倍高速であるため、データはシステムディスクから読み取るよりもRedisキャッシュから高速に取得されます。
注:パフォーマンスは向上しない可能性がありますが、MySQLデータベースから取得するレコードはわずかであるため、いくつかのベンチマークでは、Redisからキャッシュされたデータを取得する方が、処理時にMySQLから読み取るよりも数倍高速であることが証明されています。数十万のレコードがあります。
Webサイトのルートディレクトリにproducts.phpファイルを作成します。
sudo nano /var/www/html/products.php
まず、次の情報を入力してRedisのインスタンスを接続して作成し、オブジェクトとして$redis変数に保存します。
アドレス127.0.0.1はlocalhostに接続します。 リモートサーバーからRedisを実行している場合は、この値を変更できます。 REDIS_PASSWORDを、/etc/redis/redis.conf構成ファイルで設定されたRedisの特定のパスワードに置き換えることを忘れないでください。
また、適切なポート番号を入力します。 デフォルトでは、Redisはポート6379で実行されます。
/var/www/html/products.php
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('REDIS_PASSWORD');
注:このガイドでは、$redis->auth('REDIS_PASSWORD')コマンドがパスワードをプレーンテキストでRedisに送信します。 実稼働環境では、 TLS(Transport Layer Security)などのより強力なアクセス制御レイヤーを使用して、RedisとPHPコードを実行しているクライアントサーバー間のエンドツーエンド通信を保護することを検討できます。 また、/etc/redis/redis.confファイルでRedisパスワードを設定するときは、ブルートフォース攻撃を防ぐために、長くて強い値を設定してください。
次のステップは、Redisでキーとして使用するPHP変数を初期化することです。
このガイドで前述したように、Redisはキー値データベースとして機能するため、保存および取得するデータに対して一意のキーが必要です。
したがって、/var/www/html/products.phpファイルに次の情報を追加して、PRODUCTSキーを定義します。 PRODUCTSキーの代わりに任意の名前を自由に使用できます。
データがMySQLデータベースから取得されると、PHPスクリプトはこのキーを使用して情報をRedisにキャッシュします。
/var/www/html/products.php
... $key = 'PRODUCTS';
次に、条件付きPHP if...elseステートメントを含めて、PRODUCTSキーがRedisに存在するかどうかを確認します。
/var/www/html/products.php
...
if (!$redis->get($key)) {
$source = 'MySQL Server';
$database_name = 'test_store';
$database_user = 'test_user';
$database_password = 'PASSWORD';
$mysql_host = 'localhost';
$pdo = new PDO('mysql:host=' . $mysql_host . '; dbname=' . $database_name, $database_user, $database_password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM products";
$stmt = $pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$products[] = $row;
}
$redis->set($key, serialize($products));
$redis->expire($key, 10);
} else {
$source = 'Redis Server';
$products = unserialize($redis->get($key));
}
echo $source . ': <br>';
print_r($products);
キーがRedisに存在しない場合、スクリプトは前に作成したデータベースに接続し、productsテーブルにクエリを実行し、$redis->set($key, serialize($products))コマンドを使用してデータをRedisに保存します。
$redis->expire($key, 10);コマンドは、有効期限を10秒に設定します。 キャッシュポリシーに応じて、この値を微調整できます。
$source変数は、echo $sourceおよびprint_r($products)コマンドを使用して、スクリプトの最後に配列としてエコーされたデータのソースを識別するのに役立ちます。
すべてをまとめると、/var/www/html/products.phpファイルは次のようになります。
/var/www/html/products.php
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('REDIS_PASSWORD');
$key = 'PRODUCTS';
if (!$redis->get($key)) {
$source = 'MySQL Server';
$database_name = 'test_store';
$database_user = 'test_user';
$database_password = 'PASSWORD';
$mysql_host = 'localhost';
$pdo = new PDO('mysql:host=' . $mysql_host . '; dbname=' . $database_name, $database_user, $database_password);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM products";
$stmt = $pdo->prepare($sql);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
$products[] = $row;
}
$redis->set($key, serialize($products));
$redis->expire($key, 10);
} else {
$source = 'Redis Server';
$products = unserialize($redis->get($key));
}
echo $source . ': <br>';
print_r($products);
ファイルを保存して閉じます。
これで、MySQLに接続してデータをRedisにキャッシュするPHPスクリプトを設定しました。 次のステップでスクリプトをテストします。
ステップ4—PHPスクリプトをテストする
RedisがMySQLデータベースからデータをキャッシュしているかどうかをテストするには、ブラウザウィンドウにPHPスクリプトのパスを入力します。 your_server_IPは、http://your_server_IP/products.phpのように、サーバーのパブリックIPアドレスに置き換えることを忘れないでください。
スクリプトを初めて実行すると、MySQLデータベースからのデータを表示する次の出力が表示されます。この時点では、PHPスクリプトはまだRedisにデータをキャッシュしていないためです。
MySQL Server Array ( [0] => Array ( [product_id] => 1 [product_name] => Virtual Private Servers [price] => 5 ) [1] => Array ( [product_id] => 2 [product_name] => Managed Databases [price] => 15 ) [2] => Array ( [product_id] => 3 [product_name] => Block Storage [price] => 10 ) [3] => Array ( [product_id] => 4 [product_name] => Managed Kubernetes [price] => 60 ) [4] => Array ( [product_id] => 5 [product_name] => Load Balancer [price] => 10 ) )
スクリプトを再度実行すると、MySQLのキャッシュとして機能しているRedisからデータを読み取っていることを確認する出力が表示されます。
Redis Server Array ( [0] => Array ( [product_id] => 1 [product_name] => Virtual Private Servers [price] => 5 ) [1] => Array ( [product_id] => 2 [product_name] => Managed Databases [price] => 15 ) [2] => Array ( [product_id] => 3 [product_name] => Block Storage [price] => 10 ) [3] => Array ( [product_id] => 4 [product_name] => Managed Kubernetes [price] => 60 ) [4] => Array ( [product_id] => 5 [product_name] => Load Balancer [price] => 10 ) )
キーは10秒後に期限切れになり、データはMySQLから再度取得されることに注意してください。
結論
このガイドでは、Redisを使用してUbuntu20.04でPHPを使用してMySQLデータをキャッシュしました。 このガイドのコーディングを使用して、MySQLデータのキャッシュメカニズムを設定できます。これは、トラフィックの多いWebアプリケーションで特に役立ちます。
その他の教育リソースについては、Redisトピックページをご覧ください。 または、 PHPトピックページのチュートリアルとコンテンツを使用して、PHPでのコーディングの詳細を確認してください。