首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP Redis 快取操作類別完整實作與進階功能

     編輯:PHP 綜合知識

前置需求

  • 安裝 Redis 服務
  • PHP 安裝 redis 擴充套件:pecl install redis
  • 啟用擴充:extension=redis.so

Redis 快取類別實作

class RedisCache implements CacheInterface {
    private $redis;
    private $config;
    private $connected = false;
    
    public function __construct(array $config = []) {
        if (!class_exists('Redis')) {
            throw new Exception('Redis 擴充套件未安裝');
        }
        
        $this->redis = new Redis();
        $this->config = array_merge([
            'host' => '127.0.0.1',
            'port' => 6379,
            'database' => 0,
            'password' => null,
            'timeout' => 2.5,
            'persistent' => true,
            'prefix' => 'app:cache:',
            'serializer' => Redis::SERIALIZER_PHP, // 或 SERIALIZER_IGBINARY
        ], $config);
        
        $this->connect();
    }
    
    private function connect() {
        if ($this->connected) return;
        
        $method = $this->config['persistent'] ? 'pconnect' : 'connect';
        $result = $this->redis->$method(
            $this->config['host'],
            $this->config['port'],
            $this->config['timeout']
        );
        
        if (!$result) {
            throw new Exception("Redis 連線失敗:{$this->config['host']}:{$this->config['port']}");
        }
        
        if ($this->config['password']) {
            $this->redis->auth($this->config['password']);
        }
        
        $this->redis->select($this->config['database']);
        $this->redis->setOption(Redis::OPT_SERIALIZER, $this->config['serializer']);
        $this->redis->setOption(Redis::OPT_PREFIX, $this->config['prefix']);
        
        $this->connected = true;
    }
    
    public function set($key, $value, $expire = 0) {
        $this->connect();
        if ($expire > 0) {
            return $this->redis->setex($key, $expire, $value);
        }
        return $this->redis->set($key, $value);
    }
    
    public function get($key) {
        $this->connect();
        return $this->redis->get($key);
    }
    
    public function delete($key) {
        $this->connect();
        return $this->redis->del($key);
    }
    
    public function flush() {
        $this->connect();
        // 僅清除當前資料庫且帶前綴的鍵
        $keys = $this->redis->keys($this->config['prefix'] . '*');
        if ($keys) {
            return $this->redis->del($keys);
        }
        return true;
    }
    
    // === Redis 進階功能 ===
    
    /** 列表操作 */
    public function lPush($key, $value) { $this->connect(); return $this->redis->lPush($key, $value); }
    public function rPop($key) { $this->connect(); return $this->redis->rPop($key); }
    public function lRange($key, $start, $end) { $this->connect(); return $this->redis->lRange($key, $start, $end); }
    
    /** 集合操作 */
    public function sAdd($key, $member) { $this->connect(); return $this->redis->sAdd($key, $member); }
    public function sMembers($key) { $this->connect(); return $this->redis->sMembers($key); }
    public function sIsMember($key, $member) { $this->connect(); return $this->redis->sIsMember($key, $member); }
    
    /** 有序集合 */
    public function zAdd($key, $score, $member) { $this->connect(); return $this->redis->zAdd($key, $score, $member); }
    public function zRange($key, $start, $end, $withScores = false) { $this->connect(); return $this->redis->zRange($key, $start, $end, $withScores); }
    
    /** 原子計數器 */
    public function incr($key) { $this->connect(); return $this->redis->incr($key); }
    public function decr($key) { $this->connect(); return $this->redis->decr($key); }
    public function incrBy($key, $value) { $this->connect(); return $this->redis->incrBy($key, $value); }
    
    /** 分散式鎖 */
    public function lock($key, $expire = 10) {
        $this->connect();
        $lockKey = 'lock:' . $key;
        return $this->redis->set($lockKey, 1, ['nx', 'ex' => $expire]);
    }
    
    public function unlock($key) {
        $this->connect();
        $lockKey = 'lock:' . $key;
        // Lua 腳本保證原子性:僅刪除自己設定的鎖
        $script = "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end";
        return $this->redis->eval($script, 1, $lockKey, 1);
    }
    
    /** 管線操作(批量指令) */
    public function pipeline(callable $callback) {
        $this->connect();
        $this->redis->multi(Redis::PIPELINE);
        $callback($this->redis);
        return $this->redis->exec();
    }
}

使用範例

$redis = new RedisCache([
    'host' => '127.0.0.1',
    'prefix' => 'myapp:',
    'serializer' => Redis::SERIALIZER_IGBINARY, // 需安裝 igbinary
]);

// 基本快取
$redis->set('config:site_name', '我的網站', 86400);
$name = $redis->get('config:site_name');

// 熱門文章排行(有序集合)
$redis->zAdd('rank:articles', 100, 'article:1');
$redis->zAdd('rank:articles', 85, 'article:2');
$topArticles = $redis->zRange('rank:articles', 0, 9, true); // 前 10 名

// 分散式鎖防止快取擊穿
$lockKey = 'rebuild:homepage_cache';
if ($redis->lock($lockKey, 30)) {
    try {
        // 重建快取邏輯
        $html = renderHomepage();
        $redis->set('page:home', $html, 3600);
    } finally {
        $redis->unlock($lockKey);
    }
}

// 管線批量寫入
$redis->pipeline(function($r) {
    for ($i = 1; $i <= 1000; $i++) {
        $r->set("batch:$i", "value_$i");
    }
});

Redis vs Memcached 選擇指南

特性RedisMemcached
資料結構字串、列表、集合、有序集合、雜湊、位圖、HyperLogLog簡單 Key-Value
持久化RDB/AOF 可選不支援
複寫/叢集主從複寫、Redis Cluster、SentinelClient 端一致性雜湊
記憶體管理自有分配器、支援過期驅逐策略Slab Allocator、LRU
適用場景複雜資料結構、排行榜、分散式鎖、快取、Session、佇列純快取、簡單 Key-Value、大量小物件
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved