本文目录导读:

我来详细介绍在PHP项目中操作Redis的方法:
安装Redis扩展
使用PECL安装
pecl install redis
编译安装
# 下载扩展 wget https://github.com/phpredis/phpredis/archive/develop.zip unzip develop.zip cd phpredis-develop # 编译安装 phpize ./configure make && make install # 在php.ini中添加 extension=redis.so
Composer安装(推荐)
{
"require": {
"predis/predis": "^2.0"
}
}
连接Redis
基本连接
<?php
// 使用phpredis扩展(面向对象方式)
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->auth('password'); // 如果有密码
// 使用Predis库
require 'vendor/autoload.php';
$client = new Predis\Client([
'scheme' => 'tcp',
'host' => '127.0.0.1',
'port' => 6379,
'password' => 'password' // 可选
]);
连接池配置
// 使用长连接
$redis->pconnect('127.0.0.1', 6379);
// 设置连接池参数
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
$redis->setOption(Redis::OPT_PREFIX, 'myapp:');
基本操作
字符串操作
// 设置值
$redis->set('key', 'value');
$redis->setex('key_expire', 3600, 'value'); // 设置过期时间(秒)
$redis->setnx('key', 'value'); // 仅当key不存在时设置
// 获取值
$value = $redis->get('key');
// 批量操作
$redis->mset(['key1' => 'val1', 'key2' => 'val2']);
$values = $redis->mget(['key1', 'key2']);
// 递增递减
$redis->incr('counter');
$redis->incrBy('counter', 10);
$redis->decr('counter');
哈希操作
// 设置哈希字段
$redis->hSet('user:1', 'name', '张三');
$redis->hMSet('user:1', [
'name' => '张三',
'age' => 25,
'city' => '北京'
]);
// 获取哈希字段
$name = $redis->hGet('user:1', 'name');
$user = $redis->hGetAll('user:1');
$fields = $redis->hMGet('user:1', ['name', 'age']);
// 检查字段是否存在
$exists = $redis->hExists('user:1', 'name');
// 删除字段
$redis->hDel('user:1', 'age');
// 获取所有字段
$keys = $redis->hKeys('user:1');
$values = $redis->hVals('user:1');
列表操作
// 左/右插入
$redis->lPush('tasks', 'task1');
$redis->rPush('tasks', 'task2');
// 左/右弹出
$task = $redis->lPop('tasks');
$task = $redis->rPop('tasks');
// 获取列表长度
$length = $redis->lLen('tasks');
// 获取范围内元素
$tasks = $redis->lRange('tasks', 0, -1);
// 阻塞弹出(带超时)
$task = $redis->blPop(['tasks'], 5); // 等待5秒
集合操作
// 添加元素
$redis->sAdd('users:online', 'user1', 'user2');
// 检查成员
$isMember = $redis->sIsMember('users:online', 'user1');
// 获取所有成员
$members = $redis->sMembers('users:online');
// 集合运算
$redis->sAdd('set1', 'a', 'b', 'c');
$redis->sAdd('set2', 'b', 'c', 'd');
$union = $redis->sUnion('set1', 'set2'); // 并集
$intersect = $redis->sInter('set1', 'set2'); // 交集
$diff = $redis->sDiff('set1', 'set2'); // 差集
有序集合操作
// 添加分数成员
$redis->zAdd('scores', 100, 'Alice');
$redis->zAdd('scores', 90, 'Bob');
// 获取排名
$rank = $redis->zRank('scores', 'Alice'); // 升序
$rank = $redis->zRevRank('scores', 'Alice'); // 降序
// 获取范围内的成员
$top3 = $redis->zRevRange('scores', 0, 2, true);
// 增加分数
$redis->zIncrBy('scores', 10, 'Bob');
// 获取分数
$score = $redis->zScore('scores', 'Bob');
高级功能
事务处理
// 方式一:multi/exec
$redis->multi();
$redis->set('key1', 'value1');
$redis->set('key2', 'value2');
$redis->incr('counter');
$result = $redis->exec(); // 执行事务
// 方式二:discard(取消事务)
$redis->multi();
$redis->set('key1', 'value1');
$redis->discard(); // 取消事务
// 乐观锁(watch)
$redis->watch('stock');
$stock = $redis->get('stock');
if ($stock > 0) {
$redis->multi();
$redis->decr('stock');
$redis->exec();
}
管道操作
// 批量发送命令,提高性能
$redis->pipeline();
$redis->set('key1', 'value1');
$redis->set('key2', 'value2');
$redis->set('key3', 'value3');
$results = $redis->exec();
发布/订阅
// 发布者
$redis->publish('channel', 'message');
// 订阅者(需要单独脚本)
$redis->subscribe(['channel'], function($redis, $channel, $message) {
echo "收到消息: $message\n";
});
Lua脚本
// 原子性脚本执行
$lua = <<<'SCRIPT'
local current = redis.call('GET', KEYS[1])
if not current then
return redis.error_reply('Key not found')
end
if tonumber(current) > tonumber(ARGV[1]) then
return redis.error_reply('Value is too large')
end
return redis.call('INCR', KEYS[1])
SCRIPT;
$result = $redis->eval($lua, ['counter', '10'], 1);
实际应用示例
缓存实现
class CacheService {
private $redis;
private $ttl = 3600; // 默认1小时
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function get($key, $callback = null) {
$value = $this->redis->get($key);
if ($value === false && $callback) {
$value = $callback();
$this->set($key, $value);
}
return $value;
}
public function set($key, $value, $ttl = null) {
$ttl = $ttl ?? $this->ttl;
return $this->redis->setex($key, $ttl, $value);
}
public function delete($key) {
return $this->redis->del($key);
}
public function clear($pattern = '*') {
$keys = $this->redis->keys($pattern);
if (!empty($keys)) {
return $this->redis->del($keys);
}
return 0;
}
}
分布式锁
class RedisLock {
private $redis;
private $lockTime = 10; // 锁超时时间(秒)
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function acquire($key, $requestId) {
$result = $this->redis->set(
"lock:$key",
$requestId,
['NX', 'EX' => $this->lockTime]
);
return $result !== false;
}
public function release($key, $requestId) {
$script = <<<'LUA'
if redis.call("get",KEYS[1]) == ARGV[1] then
return redis.call("del",KEYS[1])
else
return 0
end
LUA;
return $this->redis->eval($script, ["lock:$key", $requestId], 1);
}
}
用户会话管理
class SessionManager {
private $redis;
private $sessionPrefix = 'session:';
private $sessionTimeout = 1800; // 30分钟
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function createSession($userId, $data = []) {
$sessionId = bin2hex(random_bytes(32));
$key = $this->sessionPrefix . $sessionId;
$data['user_id'] = $userId;
$data['created_at'] = time();
$this->redis->hMSet($key, $data);
$this->redis->expire($key, $this->sessionTimeout);
return $sessionId;
}
public function getSession($sessionId) {
$key = $this->sessionPrefix . $sessionId;
$data = $this->redis->hGetAll($key);
if (!empty($data)) {
$this->redis->expire($key, $this->sessionTimeout); // 续期
}
return $data;
}
public function destroySession($sessionId) {
return $this->redis->del($this->sessionPrefix . $sessionId);
}
}
性能优化建议
// 1. 使用长连接
$redis = new Redis();
$redis->pconnect('127.0.0.1', 6379, 2.5); // 2.5秒超时
// 2. 批量操作代替循环
// 不推荐
foreach ($items as $key => $value) {
$redis->set($key, $value);
}
// 推荐
$pipe = $redis->pipeline();
foreach ($items as $key => $value) {
$pipe->set($key, $value);
}
$pipe->exec();
// 3. 使用scan代替keys(大数据量时)
$iterator = null;
while ($keys = $redis->scan($iterator, 'pattern:*')) {
foreach ($keys as $key) {
// 处理key
}
}
// 4. 合理设置序列化
$redis->setOption(Redis::OPT_SERIALIZER, Redis::SERIALIZER_PHP);
错误处理
try {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$redis->set('test', 'value');
} catch (RedisException $e) {
// 连接失败或操作异常
error_log("Redis error: " . $e->getMessage());
// 重试逻辑
if ($e->getCode() == 0) { // 连接错误
sleep(1);
$redis->connect('127.0.0.1', 6379);
}
} finally {
if (isset($redis)) {
$redis->close();
}
}
这些是PHP操作Redis的核心内容,根据项目需求选择合适的扩展库和实现方式,注意性能优化和错误处理。