本文目录导读:

PHP 中有多种共享内存的实现方式,从简单到复杂,我来详细介绍:
PHP 原生共享内存函数(最简单)
// 创建或打开共享内存段 $shm_id = shmop_open(0x1234, 'c', 0644, 1024); // 创建1KB的共享内存 // 写入数据 $data = "Hello, shared memory!"; shmop_write($shm_id, $data, 0); // 读取数据 $content = shmop_read($shm_id, 0, shmop_size($shm_id)); // 删除共享内存 shmop_delete($shm_id); // 关闭连接 shmop_close($shm_id);
System V 共享内存(推荐)
// 创建或访问共享内存
$shm_key = ftok(__FILE__, 't'); // 生成唯一key
$shm_id = shm_attach($shm_key, 1024, 0666); // 附加到共享内存
// 存储变量
if (shm_has_var($shm_id, 1)) {
echo "Key 1 exists: " . shm_get_var($shm_id, 1);
} else {
shm_put_var($shm_id, 1, array(
'time' => time(),
'data' => 'test'
));
}
// 移除变量
shm_remove_var($shm_id, 1);
// 分离共享内存
shm_detach($shm_id);
// 删除共享内存段
shm_remove($shm_id);
使用 APCu 扩展(缓存型)
// 写入缓存
apcu_store('user_data', $data, 3600); // 缓存1小时
// 读取缓存
$data = apcu_fetch('user_data');
// 删除缓存
apcu_delete('user_data');
// 判断是否存在
if (apcu_exists('user_data')) {
echo "Key exists";
}
使用 Redis 作为共享存储(分布式)
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 写入数据
$redis->set('shared_key', $data);
// 读取数据
$data = $redis->get('shared_key');
// 队列操作
$redis->lPush('queue', 'task1');
$task = $redis->rPop('queue');
完整示例:多进程计数器
<?php
class SharedCounter {
private $shm_id;
private $sem_id;
public function __construct() {
$key = ftok(__FILE__, 'c');
// 创建信号量用于互斥
$this->sem_id = sem_get($key, 1, 0666, 1);
// 创建共享内存(8字节用于存整数)
$this->shm_id = shm_attach($key, 1024, 0666);
if (!shm_has_var($this->shm_id, 1)) {
shm_put_var($this->shm_id, 1, 0);
}
}
public function increment() {
sem_acquire($this->sem_id);
$count = shm_get_var($this->shm_id, 1);
$count++;
shm_put_var($this->shm_id, 1, $count);
sem_release($this->sem_id);
return $count;
}
public function get() {
return shm_get_var($this->shm_id, 1);
}
public function reset() {
sem_acquire($this->sem_id);
shm_put_var($this->shm_id, 1, 0);
sem_release($this->sem_id);
}
public function __destruct() {
shm_detach($this->shm_id);
}
}
// 使用示例
$counter = new SharedCounter();
// fork多个进程测试
for ($i = 0; $i < 5; $i++) {
$pid = pcntl_fork();
if ($pid == 0) {
// 子进程
for ($j = 0; $j < 10; $j++) {
$counter->increment();
}
exit(0);
}
}
// 等待所有子进程完成
while (pcntl_waitpid(0, $status) != -1);
echo "Final counter: " . $counter->get() . "\n"; // 应该显示50
注意事项
安全访问模式
// 使用锁保护
function withSharedMemory(string $key, callable $callback) {
$shm_key = ftok(__FILE__, 's');
$shm_id = shm_attach($shm_key, 1048576); // 1MB
// 获取锁
sem_acquire($sem_id);
try {
if (!shm_has_var($shm_id, 1)) {
shm_put_var($shm_id, 1, []);
}
$data = shm_get_var($shm_id, 1);
$result = $callback($data);
shm_put_var($shm_id, 1, $data);
return $result;
} finally {
sem_release($sem_id);
shm_detach($shm_id);
}
}
// 使用
$value = withSharedMemory('cache', function(&$data) {
$data['access_time'] = time();
return $data;
});
扩展安装
# 安装 System V 共享内存支持 apt-get install php-sysvmsg php-sysvsem php-sysvshm # 安装 APCu pecl install apcu # 安装 Redis 扩展 pecl install redis
常见应用场景
- 进程间通信:多 worker 进程共享数据
- 缓存:热数据缓存,减少数据库查询
- 计数器:PV/UV 统计
- 配置共享:多进程共享配置信息
- 会话管理:分布式 Session 存储
性能对比
| 方法 | 速度 | 跨进程支持 | 分布式支持 | 复杂度 |
|---|---|---|---|---|
| shmop | 快 | 是 | 否 | 低 |
| System V | 快 | 是 | 否 | 中 |
| APCu | 非常快 | 单进程 | 否 | 低 |
| Redis | 快 | 是 | 是 | 中 |
选择合适的方法取决于你的需求:如果只是单机多进程,System V 共享内存最合适;如果需要分布式,选择 Redis;如果只是进程内缓存,APCu 最合适。
版权声明: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直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播