PHP 怎么共享内存

wen PHP项目 2

本文目录导读:

PHP 怎么共享内存

  1. PHP 原生共享内存函数(最简单)
  2. System V 共享内存(推荐)
  3. 使用 APCu 扩展(缓存型)
  4. 使用 Redis 作为共享存储(分布式)
  5. 完整示例:多进程计数器
  6. 注意事项
  7. 扩展安装
  8. 常见应用场景
  9. 性能对比

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 最合适。

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