作为 Write for DOnations 计划的一部分,作者选择了 Girls Who Code 来接受捐赠。
介绍
Redis(远程字典服务器) 是一个快速的开源内存数据库,您可以将其用作高度可扩展和面向性能的系统的键值存储。 Redis 的一些用例包括:缓存、高速事务、实时分析、实时通知、机器学习、搜索和队列/作业处理。 由于 Redis 是一个内存键值存储,它的性能使其适合在应用程序中缓存数据。
缓存 将数据临时存储在高速存储层(例如,在计算机 RAM 中),以便在客户端发出相同的未来请求时更快地提供数据。 这增强了对先前计算数据的重用,而不是每次都从磁盘中获取它。
当您使用 PHP 和 MySQL 时,使用 Redis 作为缓存可以提高您的应用程序性能,因为 Redis 将数据存储在 RAM 中,这比硬盘 (HDD) 快几倍或固态驱动器 (SSD)。 缓存还降低了数据库成本——即到后端数据库的往返次数——并避免了后端过载。
当您设计读取高于写入的 Web 应用程序时,缓存数据是一项不可或缺的设计功能。 此类应用程序包括博客、在线商店和社交媒体网站。
在本教程中,您将在 Ubuntu 20.04 上使用 Redis 通过 PHP 缓存 MySQL 数据。
先决条件
要完成本教程,您需要以下内容:
- 具有 sudo 权限的非 root 用户的 Ubuntu 20.04 服务器。 按照 Initial Server Setup with Ubuntu 20.04 指南进行设置。
- 一个 LAMP 堆栈。 按照 如何在 Ubuntu 20.04 上安装 Linux、Apache、MySQL、PHP (LAMP) 堆栈教程。 对于本指南,您可以跳过 步骤 4 — 为您的网站创建虚拟主机 。
- 按照 如何在 Ubuntu 20.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.
接下来,您将创建一个包含三列的 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 $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);
保存并关闭文件。
您现在已经设置了一个 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 编码的信息。