如何在Ubuntu20.04上使用PHP将Redis设置为MySQL的缓存

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Girls Who Code 来接受捐赠。

介绍

Redis(远程字典服务器) 是一个快速的开源内存数据库,您可以将其用作高度可扩展和面向性能的系统的键值存储。 Redis 的一些用例包括:缓存、高速事务、实时分析、实时通知、机器学习、搜索和队列/作业处理。 由于 Redis 是一个内存键值存储,它的性能使其适合在应用程序中缓存数据。

缓存 将数据临时存储在高速存储层(例如,在计算机 RAM 中),以便在客户端发出相同的未来请求时更快地提供数据。 这增强了对先前计算数据的重用,而不是每次都从磁盘中获取它。

当您使用 PHPMySQL 时,使用 Redis 作为缓存可以提高您的应用程序性能,因为 Redis 将数据存储在 RAM 中,这比硬盘 (HDD) 快几倍或固态驱动器 (SSD)。 缓存还降低了数据库成本——即到后端数据库的往返次数——并避免了后端过载。

当您设计读取高于写入的 Web 应用程序时,缓存数据是一项不可或缺的设计功能。 此类应用程序包括博客、在线商店和社交媒体网站。

在本教程中,您将在 Ubuntu 20.04 上使用 Redis 通过 PHP 缓存 MySQL 数据。

先决条件

要完成本教程,您需要以下内容:

第 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_usertest_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.

接下来,您将创建一个包含三列的 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 表以进行测试。

您无需手动将数据输入到 product_id 列,因为 AUTO_INCREMENT 列将完成此操作。 一一运行以下命令:

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 数据库中检索数据并将其缓存到雷迪斯。

第 3 步 — 设计用于获取和缓存 MySQL 数据的 PHP 脚本

在此步骤中,您将创建一个 PHP 脚本来检索您在上一步中创建的示例数据。

第一次运行该脚本时,它会从 MySQL(即磁盘)读取数据,然后缓存到 Redis。 因此,后续对产品数据的读取将来自 Redis(即来自系统 RAM)。 系统内存甚至比最快的固态驱动器快数倍,因此从 Redis 缓存中检索数据的速度比从系统磁盘中读取数据的速度要快。

注意: 虽然你可能不会得到任何性能提升,因为你只是从 MySQL 数据库中检索几条记录,但几个基准测试证明,从 Redis 检索缓存数据比从 MySQL 读取数据快几倍有几十万条记录。


在您网站的根目录下创建一个 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。 在生产环境中,您可以考虑使用更强大的访问控制层来保护 Redis 和运行 PHP 代码的客户端服务器之间的端到端通信,例如 TLS(传输层安全性)。 此外,在 /etc/redis/redis.conf 文件中配置 Redis 密码时,请确保设置长且强的值以防止暴力攻击。


下一步是初始化一个 PHP 变量,您将在 Redis 中将其用作键。

如本指南前面所述,Redis 充当键值数据库,因此您必须为要从中存储和检索的数据具有唯一键。

因此,通过将以下信息添加到 /var/www/html/products.php 文件来定义 PRODUCTS 键。 您可以随意使用任何名称来代替 PRODUCTS 键。

一旦从 MySQL 数据库中检索到数据,您的 PHP 脚本将使用此键将信息缓存到 Redis:

/var/www/html/products.php

...
$key = 'PRODUCTS';

接下来,包含一个条件 PHP if...else 语句来检查 Redis 中是否存在 PRODUCTS 键:

/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 $sourceprint_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);

保存并关闭文件。

您现在已经设置了一个 PHP 脚本,它将连接到 MySQL 并将数据缓存到 Redis。 您将在下一步中测试您的脚本。

第 4 步 — 测试 PHP 脚本

要测试 Redis 是否正在缓存来自 MySQL 数据库的数据,您将在浏览器窗口中输入 PHP 脚本的路径。 请记住将 your_server_IP 替换为您服务器的公共 IP 地址,例如:http://your_server_IP/products.php

当您第一次运行该脚本时,您将收到以下显示来自 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 ) )

再次运行脚本后,您将获得一个输出,确认它正在从 Redis 读取数据,Redis 充当 MySQL 的缓存。

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 在 Ubuntu 20.04 上通过 PHP 缓存 MySQL 数据。 您可以使用本指南中的编码为您的 MySQL 数据设置缓存机制,这对于高流量的 Web 应用程序特别有用。

您可以查看我们的 Redis 主题页面 以获取更多教育资源。 或者,通过 PHP 主题页面 上的更多教程和内容了解更多关于 PHP 编码的信息。