Skip to content

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)
    {
        // 将连接放回池中
    }
}

最佳实践

  1. 合理使用数据类型
  2. 设置合适的过期时间
  3. 使用管道提升性能
  4. 实现可靠的错误处理
  5. 做好监控和日志

总结

Redis在PHP开发中是一个强大的工具,通过合理使用可以显著提升应用性能。

参考资料

  1. Redis官方文档
  2. PHP Redis扩展文档
  3. Redis设计与实现

幸运的人用童年治愈一生,不幸的人用一生治愈童年 —— 强爸