PHP 怎么数据驻留

wen PHP项目 1

本文目录导读:

PHP 怎么数据驻留

  1. 文件缓存(简单,适合小型项目)
  2. 内存缓存(推荐,高性能)
  3. 本地进程内驻留(仅限 CLI 模式)
  4. 数据库持久化(最安全,但最慢)
  5. 共享文件系统/网络文件系统(NFS)
  6. 会话(Session)驻留(特定场景)
  7. 总结对比表格
  8. 最佳实践建议
  9. 特别提醒:关于“全局变量”的误区

在 PHP 中实现数据驻留(即数据在多个请求之间持久保存),有多种方式,选择哪种取决于你的具体需求(如数据量、是否需要实时同步、性能要求等)。

这里按从简单到复杂从本地到分布式的顺序,介绍最常见的几种方案:


文件缓存(简单,适合小型项目)

将数据直接写入文件,下次请求时读取。

  • 优点:无需额外服务,实现简单。
  • 缺点:磁盘 I/O 慢,不适合高并发;数据无过期时间(需自己管理)。

示例代码(使用 serialize):

<?php
$cacheFile = '/tmp/my_data.cache';
// 读取
if (file_exists($cacheFile)) {
    $data = unserialize(file_get_contents($cacheFile));
} else {
    // 生成数据(模拟从数据库读取)
    $data = ['users' => [1, 2, 3], 'timestamp' => time()];
    // 写入
    file_put_contents($cacheFile, serialize($data));
}
var_dump($data);

内存缓存(推荐,高性能)

这是最常用的方案,PHP-FPM 模式(传统 web)下,PHP 进程在处理完请求后会销毁所有变量,无法直接跨请求驻留,必须依赖外部进程。

1 Redis(首选)

  • 优点:速度快、支持丰富的数据结构(List、Hash、Set)、支持过期时间、支持分布式。
  • 适用:会话管理、热数据缓存、排行榜、分布式锁。

示例(使用 phpredisPredis):

<?php
// 连接
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 写入(带过期时间 3600 秒)
$redis->set('user:1001', json_encode(['name' => 'Alice']), 3600);
// 读取
$user = json_decode($redis->get('user:1001'), true);
// 使用 Hash 存储对象
$redis->hMset('user:1001', ['name' => 'Alice', 'age' => 30]);
$name = $redis->hGet('user:1001', 'name');

2 Memcached

  • 优点:简单、极快,内存存储。
  • 缺点:只支持字符串类型,无持久化(重启丢失)。

本地进程内驻留(仅限 CLI 模式)

如果你运行的是长期运行的 CLI 脚本(如队列消费者、Workerman/Swoole 常驻进程),PHP 变量在内存中天然驻留。

  • 适用:WebSocket 服务器、异步任务队(Resque/Beanstalkd workers)、常驻内存的应用(如 Laravel Octane, Swoole)。
  • 注意:需要防止内存泄漏,必须用 unset() 清理大对象。

示例(Workerman 服务器,全局变量驻留):

<?php
use Workerman\Worker;
$worker = new Worker('tcp://0.0.0.0:2345');
// 该数组在进程生命周期内一直驻留内存
$globalData = [];
$worker->onMessage = function ($connection, $data) use (&$globalData) {
    $globalData[md5($data)] = $data; // 数据驻留
    $connection->send("Stored: " . count($globalData));
};
Worker::runAll();

数据库持久化(最安全,但最慢)

将数据写入 MySQL/PostgreSQL,下次请求再查。

  • 优点:持久化可靠性最高,支持复杂查询。
  • 缺点:磁盘 I/O,性能不如内存。
  • 适用:用户数据、订单数据等需要永久保存的业务数据

共享文件系统/网络文件系统(NFS)

多台机器共享一个文件目录存储缓存(如 APCu over NFS 不可行,需自己实现锁),一般不建议,因为并发锁不好处理,Redis 是更好的选择。


会话(Session)驻留(特定场景)

针对需要跨页面保持的用户级数据(如登录状态),PHP 支持原生 Session。

  • 存储位置:默认文件,可改为 Redis(修改 php.ini 或用 session_set_save_handler())。
  • 缺点:作用域仅为单个用户,不适合全局数据。

总结对比表格

方法 跨请求持久 分布式支持 性能 持久化 适用场景
文件缓存 单机小项目
Redis 极高 ✅ (RDB/AOF) 大多数生产环境首选
Memcached 极高 纯热缓存,不介意丢失
数据库表 低-中 核心业务数据
PHP常驻进程 极高 Swoole/Workerman/CLI
Session 特定用户状态

最佳实践建议

  1. 热数据(排行榜、验证码、API Token) -> Redis
  2. 静态配置(如系统配置参数) -> APCu(PHP内置,单机进程内驻留,共享内存)或 文件
  3. 业务数据(订单、用户资料) -> 数据库(使用主从复制增加读性能)。
  4. 如果项目使用框架(如 Laravel、Symfony)-> 直接用框架内置的 Cache Facade(底层就支持 Redis/File/Database)。

特别提醒:全局变量”的误区

在传统 Apache/Nginx + PHP-FPM 下,普通的 PHP 全局变量 $GLOBALS 在本次请求结束后会被销毁无法跨请求驻留,这是 PHP 生命周期决定的(PHP_FPM 进程虽然常驻,但每次请求都会重新初始化环境)。

注意static 关键字在函数内对变量驻留有效,但也仅限于当前请求的进程内,请求结束会被释放(FPM模式下)。

如果你想在 FPM 模式下“共享”数据,必须使用共享存储(Redis/文件/数据库),没有第三条路。

抱歉,评论功能暂时关闭!