本文目录导读:

我来详细介绍在PHP中使用Redis的方法:
安装和配置
安装Redis扩展
# Ubuntu/Debian sudo apt-get install php-redis # CentOS/RHEL sudo yum install php-redis # 或者使用PECL pecl install redis
检查扩展是否安装
<?php
phpinfo(); // 查看是否有Redis扩展
// 或者
echo extension_loaded('redis') ? 'Redis已加载' : 'Redis未加载';
基础连接
简单连接
<?php
// 创建Redis对象
$redis = new Redis();
// 连接服务器
$redis->connect('127.0.0.1', 6379);
// 认证(如果有密码)
$redis->auth('your_password');
// 选择数据库
$redis->select(0);
// 测试连接
echo $redis->ping(); // 输出: +PONG
?>
连接池/Persistent连接
<?php
$redis = new Redis();
// 持久连接(减少握手开销)
$redis->pconnect('127.0.0.1', 6379, 2.5); // 2.5秒超时
// 设置选项
$redis->setOption(Redis::OPT_READ_TIMEOUT, -1);
$redis->setOption(Redis::OPT_CONNECT_TIMEOUT, 5);
?>
字符串操作
<?php
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
// 设置值
$redis->set('name', 'John');
$redis->set('age', 25);
$redis->set('expire_key', 'value', 3600); // 设置过期时间
// 批量设置
$redis->mset(['key1' => 'value1', 'key2' => 'value2']);
// 获取值
echo $redis->get('name'); // 输出: John
// 批量获取
$values = $redis->mget(['name', 'age']);
// 自增/自减
$redis->incr('counter');
$redis->incrBy('counter', 10);
$redis->decr('counter');
$redis->decrBy('counter', 5);
// 追加
$redis->append('message', 'Hello ');
$redis->append('message', 'World!');
// 获取字符串长度
$len = $redis->strlen('message');
// 设置值并返回旧值
$oldValue = $redis->getSet('name', 'Jane');
?>
Hash操作
<?php
// 存储用户对象
$redis->hSet('user:1', 'name', 'John');
$redis->hSet('user:1', 'age', 25);
$redis->hSet('user:1', 'email', 'john@example.com');
// 批量设置
$redis->hMset('user:2', [
'name' => 'Jane',
'age' => 30,
'email' => 'jane@example.com'
]);
// 获取所有字段
$user = $redis->hGetAll('user:1');
// 获取单个字段
$name = $redis->hGet('user:1', 'name');
// 获取多个字段
$fields = $redis->hMget('user:1', ['name', 'email']);
// 判断字段是否存在
$exists = $redis->hExists('user:1', 'name');
// 删除字段
$redis->hDel('user:1', 'email');
// 获取所有字段名
$keys = $redis->hKeys('user:1');
// 获取所有值
$values = $redis->hVals('user:1');
// 获取长度
$count = $redis->hLen('user:1');
?>
List操作
<?php
// 添加元素(右侧)
$redis->rPush('tasks', 'task1');
$redis->rPush('tasks', 'task2', 'task3');
// 添加元素(左侧)
$redis->lPush('tasks_front', 'task1');
$redis->lPush('tasks_front', 'task2');
// 获取列表长度
$length = $redis->lLen('tasks');
// 获取指定范围的元素
$tasks = $redis->lRange('tasks', 0, -1);
// 获取指定索引的元素
$task = $redis->lIndex('tasks', 0);
// 弹出元素
$lastTask = $redis->rPop('tasks'); // 右侧弹出
$firstTask = $redis->lPop('tasks'); // 左侧弹出
// 阻塞弹出(等待)
$result = $redis->blPop('tasks', 5); // 等待5秒
// 修剪列表
$redis->lTrim('tasks', 0, 9); // 只保留前10个元素
// 移除元素
$redis->lRem('tasks', 'task2', 0); // 删除所有'task2'
?>
Set操作
<?php
// 添加成员
$redis->sAdd('tags', 'php');
$redis->sAdd('tags', 'redis', 'mysql');
// 获取所有成员
$tags = $redis->sMembers('tags');
// 判断成员是否存在
$exists = $redis->sIsMember('tags', 'php');
// 获取数量
$count = $redis->sCard('tags');
// 随机获取成员
$randomTag = $redis->sRandMember('tags');
// 移除成员
$redis->sRem('tags', 'php');
// 集合运算
$redis->sAdd('set1', 'a', 'b', 'c', 'd');
$redis->sAdd('set2', 'c', 'd', 'e');
// 交集
$intersection = $redis->sInter('set1', 'set2');
// 并集
$union = $redis->sUnion('set1', 'set2');
// 差集
$diff = $redis->sDiff('set1', 'set2');
?>
Sorted Set操作
<?php
// 添加带分数的成员
$redis->zAdd('ranking', 100, 'player1');
$redis->zAdd('ranking', 200, 'player2');
$redis->zAdd('ranking', 150, 'player3');
// 批量添加
$redis->zAdd('ranking', [
'player4' => 300,
'player5' => 250
]);
// 获取排行榜(从高到低)
$top10 = $redis->zRevRange('ranking', 0, 9, true);
// 获取指定范围(从低到高)
$bottom = $redis->zRange('ranking', 0, -1, true);
// 获取某个成员的分数
$score = $redis->zScore('ranking', 'player1');
// 获取排名(从0开始)
$rank = $redis->zRevRank('ranking', 'player1');
// 增加分数
$redis->zIncrBy('ranking', 50, 'player1');
// 获取成员数量
$count = $redis->zCard('ranking');
// 按分数范围获取
$players = $redis->zRangeByScore('ranking', 100, 200);
?>
过期和缓存操作
<?php
// 设置过期时间
$redis->set('temp', 'data');
$redis->expire('temp', 3600); // 1小时后过期
// 或者使用SETEX
$redis->setex('session', 3600, 'user_data');
// 检查TTL
$ttl = $redis->ttl('temp'); // 返回剩余时间
$persists = $redis->persist('temp'); // 取消过期
// 删除键
$redis->del('temp');
// 检查键是否存在
$exists = $redis->exists('temp');
?>
实际应用示例
缓存数据库查询
<?php
class UserCache {
private $redis;
private $cacheTime = 3600;
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function getUser($userId) {
$key = "user:{$userId}";
// 尝试从缓存获取
$cached = $this->redis->get($key);
if ($cached !== false) {
return json_decode($cached, true);
}
// 模拟数据库查询
$userData = $this->getUserFromDB($userId);
// 存入缓存
$this->redis->setex($key, $this->cacheTime, json_encode($userData));
return $userData;
}
private function getUserFromDB($userId) {
// 实际数据库查询代码
return ['id' => $userId, 'name' => 'John', 'email' => 'john@example.com'];
}
public function clearUserCache($userId) {
$this->redis->del("user:{$userId}");
}
}
?>
实现简单的限制器
<?php
class RateLimiter {
private $redis;
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function isAllowed($userId, $maxRequests = 10, $period = 60) {
$key = "rate_limit:{$userId}";
// 使用Lua脚本保证原子性
$lua = '
local current = redis.call("incr", KEYS[1])
if current == 1 then
redis.call("expire", KEYS[1], ARGV[1])
end
if current > tonumber(ARGV[2]) then
return 0
end
return 1
';
return $this->redis->eval($lua, [$key, $maxRequests, $period], 1);
}
}
// 使用示例
$limiter = new RateLimiter();
if ($limiter->isAllowed('user123')) {
// 允许请求
} else {
// 拒绝请求
}
?>
购物车实现
<?php
class Cart {
private $redis;
public function __construct() {
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
}
public function addItem($cartId, $item) {
$key = "cart:{$cartId}";
// 使用hash存储购物车
$this->redis->hSet($key, $item['id'], json_encode($item));
return true;
}
public function removeItem($cartId, $itemId) {
$key = "cart:{$cartId}";
$this->redis->hDel($key, $itemId);
}
public function getCart($cartId) {
$key = "cart:{$cartId}";
$items = $this->redis->hGetAll($key);
return array_map('json_decode', array_values($items));
}
public function clearCart($cartId) {
$key = "cart:{$cartId}";
$this->redis->del($key);
}
}
?>
最佳实践
- 连接管理:使用连接池或持久连接
- 错误处理:始终处理Redis异常
- 数据序列化:复杂数据结构使用JSON序列化
- 键命名:使用有意义的前缀,如
user:1:profile - 设置超时:总是设置适当的过期时间
- 使用管道:批量操作时使用
multi()和exec()
<?php
// 管道批量操作
$redis->multi();
$redis->set('key1', 'value1');
$redis->set('key2', 'value2');
$redis->incr('counter');
$results = $redis->exec();
// 错误处理
try {
$redis->connect('127.0.0.1', 6379);
$redis->set('test', 'value');
} catch (RedisException $e) {
echo "Redis错误: " . $e->getMessage();
}
?>