如何使用 Redis 缓存热点数据减少 PHP 直接查询数据库次数

文章导读
在 PHP 项目中集成 Redis 扩展,针对高频读取的 SQL 查询结果采用 Cache-Aside 模式,先请求 Redis 再回源数据库。该方案适合读多写少的业务场景,主要风险在于缓存更新延迟导致的数据一致性问题。
📋 目录
  1. 命令速用版
  2. 为什么会这样
  3. 分步处理
  4. 怎么验证是否生效
  5. 常见坑
  6. 常见问题
  7. 参考来源
A A

在 PHP 项目中集成 Redis 扩展,针对高频读取的 SQL 查询结果采用 Cache-Aside 模式,先请求 Redis 再回源数据库。该方案适合读多写少的业务场景,主要风险在于缓存更新延迟导致的数据一致性问题。

先说结论:通过 Redis 缓存热点数据能有效降低数据库连接消耗和 I/O 等待,但必须设计合理的过期和失效策略。

  • 先定位:通过慢查询日志找出执行频繁且耗时较长的 SQL 语句
  • 先做:在 PHP 代码层封装缓存读取逻辑,设置合理的过期时间 TTL
  • 再验证:监控 Redis 命中率指标和数据库 QPS 变化确认效果

命令速用版

安装 PHP Redis 扩展并验证环境可用性,随后在代码中实现基础读写逻辑。

# 安装 phpredis 扩展(根据系统环境选择)
pecl install redis
# 重启 PHP-FPM
systemctl restart php-fpm
# 验证扩展是否加载
php -m | grep redis

PHP 代码基础示例:

$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$key = 'user_info_1001';
$data = $redis->get($key);
if (!$data) {
    $data = $db->query('SELECT * FROM users WHERE id=1001');
    $redis->setEx($key, 3600, serialize($data));
}

为什么会这样

数据库查询涉及磁盘 I/O 和锁竞争,而 Redis 基于内存操作且单线程处理命令,响应速度更快。

MySQL 在处理高并发读取时,连接数上限和磁盘读写能力是主要瓶颈。Redis 将热点数据驻留内存,PHP 请求直接命中内存数据,避免了重复的网络往返和数据库解析开销。公开资料中没有看到可靠的量化数据表明具体提升倍数,因为性能取决于数据大小、网络延迟和并发模型,但架构原理上减少了数据库的直接负载。

分步处理

步骤 1:识别热点数据

开启 MySQL 慢查询日志,筛选执行次数多且耗时稳定的查询。不要缓存频繁变更的数据,如库存扣减计数。

步骤 2:安装与配置

确保 PHP 环境已安装 redis 扩展,并在 php.ini 中启用。配置 Redis 服务器允许 PHP 服务器 IP 访问,设置密码保护。

步骤 3:实现 Cache-Aside 模式

代码逻辑遵循“先读缓存,命中则返回;未命中则查库,写入缓存后返回”。写入缓存时必须设置过期时间(TTL),防止脏数据永久驻留。

如何使用 Redis 缓存热点数据减少 PHP 直接查询数据库次数

步骤 4:设计失效策略

当数据库数据更新时,直接删除对应的 Redis 缓存 Key,而不是更新缓存。下次读取时会重新加载最新数据。这比双写一致性更容易维护。

怎么验证是否生效

使用 Redis 命令行工具查看命中统计,同时观察数据库负载变化。

# 查看 Redis 命中率统计
redis-cli info stats | grep keyspace_hits
# 查看 MySQL 慢查询数量
mysqldumpslow -s t /var/log/mysql/slow.log

如果 keyspace_hits 随请求量增长,且 MySQL 慢查询日志新增记录减少,说明缓存生效。也可以分别在应用日志中记录“缓存命中”和“数据库查询”的次数比例。

常见坑

缓存穿透:查询不存在的数据,请求直接打到数据库。解决方法是对空结果也缓存短暂时间。

缓存雪崩:大量 Key 同一时间过期,导致数据库瞬间压力激增。解决方法是给过期时间加上随机值。

数据一致性:缓存删除失败会导致旧数据残留。关键业务需记录删除日志或使用消息队列重试删除操作。

常见问题

缓存和数据库数据不一致怎么办?

优先采用“更新数据库后删除缓存”的策略,容忍秒级的不一致窗口。强一致性场景不建议使用缓存,或需使用分布式锁。

Redis 挂了会影响业务吗?

会,代码中需要增加异常捕获,当 Redis 连接失败时自动降级为直接查询数据库,避免服务不可用。

过期时间设置多少合适?

根据数据更新频率决定,静态配置可设较长,用户信息建议较短。公开资料中没有统一标准,需结合业务容忍度测试。

参考来源

  • phpredis 文档,GitHub Repository,https://github.com/phpredis/phpredis
  • Redis Documentation,Redis.io,https://redis.io/docs/