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
で実行されます。
<?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にキャッシュします。
...
$key = 'PRODUCTS';
次に、条件付きPHP if...else
ステートメントを含めて、PRODUCTS
キーがRedisに存在するかどうかを確認します。
...
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
ファイルは次のようになります。
<?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でのコーディングの詳細を確認してください。