本文目录导读:

- 共享内存(shmop / sysvshm) 🚀
- 文件锁(flock) 📁
- Redis / Memcached 🔥
- 消息队列(Message Queue) 💬
- ZeroMQ / 其他IPC 🛠️
- 数据库(MySQL/PostgreSQL) 📊
- Apache/nginx + 缓存文件 📝
- 进程守护 + Swoole/Workerman 🚀
- 选择建议 📋
- 完整示例:计数器实现 🔄
在 PHP 中实现跨进程共享,主要有以下几种方案,根据你的需求和环境选择:
共享内存(shmop / sysvshm) 🚀
最常见的跨进程通信方式,性能最好。
使用 shmop 扩展(简单版)
<?php // 创建 100KB 共享内存块 $shm_id = shmop_open(0xFF3, "c", 0644, 100 * 1024); // 写入数据 $data = json_encode(['user' => 'admin', 'time' => time()]); shmop_write($shm_id, $data, 0); // 读取数据(在另一个进程中) $size = shmop_size($shm_id); $data = shmop_read($shm_id, 0, $size); // 关闭 shmop_close($shm_id); ?>
使用 sysvshm 扩展(带信号量)
<?php
// key 必须是整数
$key = ftok('/tmp/test', 'R'); // 或直接指定数字
// 创建信号量(用于同步)
$sem = sem_get($key, 1, 0644, 1);
// 获取共享内存
$shm = shm_attach($key, 1024 * 1024, 0644);
// 锁定
sem_acquire($sem);
// 写入数组
$data = ['key' => 'value', 'count' => 100];
shm_put_var($shm, 1, $data);
// 读取
$result = shm_get_var($shm, 1);
// 解锁和清理
sem_release($sem);
shm_detach($shm);
?>
文件锁(flock) 📁
适用于简单的数据共享,通过文件加锁保证互斥。
<?php
// 写进程
$file = fopen('/tmp/shared_data.txt', 'c+');
flock($file, LOCK_EX);
fseek($file, 0);
ftruncate($file, 0);
fwrite($file, json_encode(['time' => time(), 'data' => 'hello']));
fflush($file);
flock($file, LOCK_UN);
fclose($file);
// 读进程
$file = fopen('/tmp/shared_data.txt', 'r');
flock($file, LOCK_SH);
$data = fread($file, filesize('/tmp/shared_data.txt'));
flock($file, LOCK_UN);
fclose($file);
?>
Redis / Memcached 🔥
网络化的共享方案,适合分布式系统。
<?php
// Redis 示例
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 进程 A
$redis->setex('shared_key', 3600, json_encode(['data' => 'value']));
// 进程 B
$data = $redis->get('shared_key');
echo $data; // {"data":"value"}
?>
消息队列(Message Queue) 💬
适合异步处理和任务分发。
<?php
// 使用 Redis 列表做队列
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 生产者
$redis->lpush('task_queue', json_encode(['task' => 'process', 'id' => 1]));
// 消费者
$task = $redis->rpop('task_queue');
echo $task; // {"task":"process","id":1}
?>
ZeroMQ / 其他IPC 🛠️
适合复杂场景的进程间通信。
<?php
// 需要安装 zmq 扩展
$context = new ZMQContext();
$socket = $context->getSocket(ZMQ::SOCKET_REP, 'my_persistent_id');
$socket->bind("tcp://*:5555");
// 接收消息
$message = $socket->recv();
$socket->send("Response");
// 另一进程连接
$reqSocket = $context->getSocket(ZMQ::SOCKET_REQ);
$reqSocket->connect("tcp://localhost:5555");
$reqSocket->send("Hello");
$reply = $reqSocket->recv();
?>
数据库(MySQL/PostgreSQL) 📊
最通用的方案,但性能最差。
<?php
// 使用数据库做状态共享
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$pdo->exec("CREATE TABLE IF NOT EXISTS shared_state (
key VARCHAR(50) PRIMARY KEY,
value TEXT,
updated_at TIMESTAMP
)");
// 写入
$pdo->prepare("INSERT INTO shared_state (key, value, updated_at) VALUES (?, ?, NOW())
ON DUPLICATE KEY UPDATE value = ?, updated_at = NOW()")
->execute(['counter', 100, 100]);
// 读取
$stmt = $pdo->prepare("SELECT value FROM shared_state WHERE key = ?");
$stmt->execute(['counter']);
$value = $stmt->fetchColumn();
?>
Apache/nginx + 缓存文件 📝
简单且常用,通过临时文件系统。
<?php
// 使用 /tmp 目录 + 唯一文件名
$lock_key = md5('my_shared_data');
$cache_file = sys_get_temp_dir() . '/' . $lock_key . '.cache';
// 原子写入
$data_to_write = json_encode(['time' => time()]);
$tmp_file = $cache_file . '.' . uniqid();
file_put_contents($tmp_file, $data_to_write);
rename($tmp_file, $cache_file); // 原子操作
// 读取
if (file_exists($cache_file)) {
$data = json_decode(file_get_contents($cache_file), true);
}
?>
进程守护 + Swoole/Workerman 🚀
使用常驻内存方案,天然共享。
<?php
// Swoole 示例
$server = new Swoole\Http\Server('0.0.0.0', 9501);
$server->on('start', function() {
// 全局变量在所有 worker 中共享
Swoole\Table::getInstance()->create('connections', 1024);
});
$server->on('request', function($request, $response) {
// 写入共享表
$table = Swoole\Table::getInstance('connections');
$table->set($request->fd, ['data' => 'value']);
// 读取
$data = $table->get($request->fd);
$response->end(json_encode($data));
});
?>
选择建议 📋
| 方案 | 性能 | 适用场景 | 复杂度 |
|---|---|---|---|
| 共享内存 | 高性能本地IPC | 中等 | |
| 文件锁 | 简单数据共享 | 低 | |
| Redis | 分布式系统 | 中等 | |
| 消息队列 | 异步任务 | 中等 | |
| 数据库 | 持久化状态 | 低 |
完整示例:计数器实现 🔄
<?php
// 使用 Redis 实现一个安全的计数器
class Counter {
private $redis;
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
// 原子递增
public function increment($key) {
return $this->redis->incr($key);
}
// 带过期时间的锁
public function withLock($key, $callback) {
$lock_key = "lock:$key";
while (!$this->redis->set($lock_key, 1, ['NX', 'EX' => 10])) {
usleep(100000); // 等待 100ms
}
try {
return $callback();
} finally {
$this->redis->del($lock_key);
}
}
}
// 使用示例
$counter = new Counter();
$counter->increment('page_views');
echo "总访问数: " . $counter->withLock('data', function() {
return $counter->increment('total');
});
?>
选择方案时考虑:
- 数据大小:大容量数据用共享内存
- 数据持久性:需要持久化用数据库/Redis
- 分布式部署:用 Redis/MQ
- 性能要求:高并发用共享内存/Redis
- 简单性:文件系统最简单但功能有限
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播