PHP Redis实战指南:从入门到精通
引言
Redis作为高性能的内存数据库,在PHP开发中有着广泛的应用。本文将详细介绍Redis在PHP中的使用方法和最佳实践。
基础配置
安装配置
bash
# 安装PHP Redis扩展
pecl install redis
# 配置php.ini
extension=redis.so
连接管理
php
class RedisManager
{
private static $instance = null;
private $redis;
private function __construct()
{
$this->redis = new Redis();
$this->redis->connect('127.0.0.1', 6379);
// 设置密码
$this->redis->auth('your_password');
// 选择数据库
$this->redis->select(0);
}
public static function getInstance()
{
if (self::$instance === null) {
self::$instance = new self();
}
return self::$instance;
}
public function getRedis()
{
return $this->redis;
}
}
数据类型操作
字符串操作
php
class StringOperation
{
private $redis;
public function __construct()
{
$this->redis = RedisManager::getInstance()->getRedis();
}
public function setCache($key, $value, $expiration = 3600)
{
return $this->redis->setex($key, $expiration, $value);
}
public function getCache($key)
{
return $this->redis->get($key);
}
public function increment($key, $step = 1)
{
return $this->redis->incrBy($key, $step);
}
public function decrement($key, $step = 1)
{
return $this->redis->decrBy($key, $step);
}
}
哈希表操作
php
class HashOperation
{
private $redis;
public function __construct()
{
$this->redis = RedisManager::getInstance()->getRedis();
}
public function setHashField($key, $field, $value)
{
return $this->redis->hSet($key, $field, $value);
}
public function getHashField($key, $field)
{
return $this->redis->hGet($key, $field);
}
public function setMultipleFields($key, array $data)
{
return $this->redis->hMset($key, $data);
}
public function getAllFields($key)
{
return $this->redis->hGetAll($key);
}
}
列表操作
php
class ListOperation
{
private $redis;
public function __construct()
{
$this->redis = RedisManager::getInstance()->getRedis();
}
public function pushToList($key, $value)
{
return $this->redis->lPush($key, $value);
}
public function popFromList($key)
{
return $this->redis->rPop($key);
}
public function getListRange($key, $start = 0, $end = -1)
{
return $this->redis->lRange($key, $start, $end);
}
public function trimList($key, $start, $end)
{
return $this->redis->lTrim($key, $start, $end);
}
}
缓存策略
缓存管理
php
class CacheManager
{
private $redis;
private $prefix;
public function __construct($prefix = 'cache:')
{
$this->redis = RedisManager::getInstance()->getRedis();
$this->prefix = $prefix;
}
public function remember($key, $ttl, callable $callback)
{
$value = $this->redis->get($this->prefix . $key);
if ($value !== false) {
return unserialize($value);
}
$value = $callback();
$this->redis->setex(
$this->prefix . $key,
$ttl,
serialize($value)
);
return $value;
}
public function forget($key)
{
return $this->redis->del($this->prefix . $key);
}
public function tags(array $tags)
{
return new TaggedCache($this->redis, $this->prefix, $tags);
}
}
标签系统
php
class TaggedCache
{
private $redis;
private $prefix;
private $tags;
public function __construct($redis, $prefix, array $tags)
{
$this->redis = $redis;
$this->prefix = $prefix;
$this->tags = $tags;
}
public function set($key, $value, $ttl = null)
{
$this->addToTagSet($key);
if ($ttl === null) {
return $this->redis->set($this->prefix . $key, serialize($value));
}
return $this->redis->setex(
$this->prefix . $key,
$ttl,
serialize($value)
);
}
public function get($key)
{
$value = $this->redis->get($this->prefix . $key);
return $value ? unserialize($value) : null;
}
public function flush()
{
foreach ($this->tags as $tag) {
$keys = $this->redis->sMembers("tag:{$tag}");
if (!empty($keys)) {
$this->redis->del($keys);
$this->redis->del("tag:{$tag}");
}
}
}
private function addToTagSet($key)
{
foreach ($this->tags as $tag) {
$this->redis->sAdd("tag:{$tag}", $this->prefix . $key);
}
}
}
分布式锁
锁实现
php
class RedisLock
{
private $redis;
private $lockKey;
private $token;
private $ttl;
public function __construct($key, $ttl = 30)
{
$this->redis = RedisManager::getInstance()->getRedis();
$this->lockKey = "lock:{$key}";
$this->token = uniqid();
$this->ttl = $ttl;
}
public function acquire()
{
return $this->redis->set(
$this->lockKey,
$this->token,
['NX', 'EX' => $this->ttl]
);
}
public function release()
{
$script = <<<LUA
if redis.call('get', KEYS[1]) == ARGV[1] then
return redis.call('del', KEYS[1])
end
return 0
LUA;
return $this->redis->eval(
$script,
[$this->lockKey, $this->token],
1
);
}
}
使用示例
php
function processOrder($orderId)
{
$lock = new RedisLock("order:{$orderId}");
try {
if (!$lock->acquire()) {
throw new Exception('获取锁失败');
}
// 处理订单逻辑
processOrderLogic($orderId);
} finally {
$lock->release();
}
}
队列系统
队列实现
php
class RedisQueue
{
private $redis;
private $key;
public function __construct($queueName)
{
$this->redis = RedisManager::getInstance()->getRedis();
$this->key = "queue:{$queueName}";
}
public function push($data)
{
return $this->redis->rPush(
$this->key,
serialize($data)
);
}
public function pop($timeout = 0)
{
$result = $this->redis->blPop($this->key, $timeout);
if ($result) {
return unserialize($result[1]);
}
return null;
}
public function size()
{
return $this->redis->lLen($this->key);
}
public function clear()
{
return $this->redis->del($this->key);
}
}
延迟队列
php
class DelayedQueue
{
private $redis;
private $key;
public function __construct($queueName)
{
$this->redis = RedisManager::getInstance()->getRedis();
$this->key = "delayed:{$queueName}";
}
public function schedule($data, $delay)
{
$time = time() + $delay;
return $this->redis->zAdd(
$this->key,
$time,
serialize(['time' => $time, 'data' => $data])
);
}
public function getReady()
{
$now = time();
$items = $this->redis->zRangeByScore(
$this->key,
'-inf',
$now
);
if (!empty($items)) {
$this->redis->zRemRangeByScore(
$this->key,
'-inf',
$now
);
}
return array_map(function ($item) {
return unserialize($item)['data'];
}, $items);
}
}
会话管理
Session处理器
php
class RedisSessionHandler implements SessionHandlerInterface
{
private $redis;
private $prefix;
private $ttl;
public function __construct($prefix = 'session:', $ttl = 3600)
{
$this->redis = RedisManager::getInstance()->getRedis();
$this->prefix = $prefix;
$this->ttl = $ttl;
}
public function open($path, $name)
{
return true;
}
public function close()
{
return true;
}
public function read($id)
{
$data = $this->redis->get($this->prefix . $id);
return $data === false ? '' : $data;
}
public function write($id, $data)
{
return $this->redis->setex(
$this->prefix . $id,
$this->ttl,
$data
);
}
public function destroy($id)
{
return $this->redis->del($this->prefix . $id);
}
public function gc($maxlifetime)
{
return true;
}
}
性能优化
管道技术
php
class RedisPipeline
{
private $redis;
public function __construct()
{
$this->redis = RedisManager::getInstance()->getRedis();
}
public function batchSet(array $data)
{
$pipe = $this->redis->multi(Redis::PIPELINE);
foreach ($data as $key => $value) {
$pipe->set($key, $value);
}
return $pipe->exec();
}
public function batchGet(array $keys)
{
$pipe = $this->redis->multi(Redis::PIPELINE);
foreach ($keys as $key) {
$pipe->get($key);
}
return $pipe->exec();
}
}
连接池
php
class RedisPool
{
private static $connections = [];
private static $max = 10;
public static function getConnection()
{
if (count(self::$connections) < self::$max) {
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
self::$connections[] = $redis;
return $redis;
}
return self::$connections[array_rand(self::$connections)];
}
public static function release($connection)
{
// 将连接放回池中
}
}
最佳实践
- 合理使用数据类型
- 设置合适的过期时间
- 使用管道提升性能
- 实现可靠的错误处理
- 做好监控和日志
总结
Redis在PHP开发中是一个强大的工具,通过合理使用可以显著提升应用性能。
参考资料
- Redis官方文档
- PHP Redis扩展文档
- Redis设计与实现