PHP 实现键值存储

wen PHP项目 2

本文目录导读:

PHP 实现键值存储

  1. 内存数组实现(最简单)
  2. 文件存储实现
  3. JSON 文件持久化(带缓存优化)
  4. SQLite 实现(数据量大时推荐)
  5. Redis 实现(高性能场景)
  6. 通用接口设计
  7. 选择建议

我将为您提供几种PHP键值存储的实现方案,从简单到复杂。

内存数组实现(最简单)

<?php
class MemoryKVStore {
    private $data = [];
    public function set($key, $value) {
        $this->data[$key] = $value;
    }
    public function get($key) {
        return isset($this->data[$key]) ? $this->data[$key] : null;
    }
    public function delete($key) {
        unset($this->data[$key]);
    }
    public function has($key) {
        return isset($this->data[$key]);
    }
    public function getAll() {
        return $this->data;
    }
    public function clear() {
        $this->data = [];
    }
    public function count() {
        return count($this->data);
    }
}
// 使用示例
$store = new MemoryKVStore();
$store->set('username', 'Alice');
$store->set('age', 25);
echo $store->get('username'); // 输出: Alice
?>

文件存储实现

<?php
class FileKVStore {
    private $filePath;
    private $data = [];
    public function __construct($filePath = 'kvstore.json') {
        $this->filePath = $filePath;
        $this->load();
    }
    public function set($key, $value) {
        $this->data[$key] = $value;
        $this->save();
    }
    public function get($key) {
        return isset($this->data[$key]) ? $this->data[$key] : null;
    }
    public function delete($key) {
        if (isset($this->data[$key])) {
            unset($this->data[$key]);
            $this->save();
            return true;
        }
        return false;
    }
    public function has($key) {
        return isset($this->data[$key]);
    }
    public function getAll() {
        return $this->data;
    }
    public function clear() {
        $this->data = [];
        $this->save();
    }
    private function load() {
        if (file_exists($this->filePath)) {
            $content = file_get_contents($this->filePath);
            $this->data = json_decode($content, true) ?: [];
        }
    }
    private function save() {
        $content = json_encode($this->data, JSON_PRETTY_PRINT);
        file_put_contents($this->filePath, $content);
    }
    public function __destruct() {
        $this->save();
    }
}
// 使用示例
$store = new FileKVStore('storage.json');
$store->set('user1', ['name' => 'Bob', 'age' => 30]);
$store->set('config', ['debug' => true]);
$user = $store->get('user1');
?>

JSON 文件持久化(带缓存优化)

<?php
class JsonKVStore {
    private $filePath;
    private $data = [];
    private $loaded = false;
    public function __construct($filePath = 'kvstore.json') {
        $this->filePath = $filePath;
    }
    private function ensureLoaded() {
        if (!$this->loaded) {
            $this->loadFromFile();
            $this->loaded = true;
        }
    }
    private function loadFromFile() {
        if (file_exists($this->filePath)) {
            $content = file_get_contents($this->filePath);
            $this->data = json_decode($content, true);
            if (!is_array($this->data)) {
                $this->data = [];
            }
        } else {
            $this->data = [];
        }
    }
    public function set($key, $value) {
        $this->ensureLoaded();
        $this->data[$key] = $value;
        $this->persist();
    }
    public function get($key, $default = null) {
        $this->ensureLoaded();
        return isset($this->data[$key]) ? $this->data[$key] : $default;
    }
    public function delete($key) {
        $this->ensureLoaded();
        if (isset($this->data[$key])) {
            unset($this->data[$key]);
            $this->persist();
            return true;
        }
        return false;
    }
    public function getOrSet($key, $callback) {
        $this->ensureLoaded();
        if (!isset($this->data[$key])) {
            $this->data[$key] = is_callable($callback) ? $callback() : $callback;
            $this->persist();
        }
        return $this->data[$key];
    }
    private function persist() {
        $tempFile = $this->filePath . '.tmp';
        $content = json_encode($this->data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
        file_put_contents($tempFile, $content, LOCK_EX);
        rename($tempFile, $this->filePath); // 原子操作
    }
}
// 使用示例
$store = new JsonKVStore('data.json');
// 使用 getOrSet 避免重复设置
$value = $store->getOrSet('timestamp', function() {
    return time();
});
?>

SQLite 实现(数据量大时推荐)

<?php
class SqliteKVStore {
    private $pdo;
    public function __construct($dbPath = 'kvstore.db') {
        $this->pdo = new PDO("sqlite:{$dbPath}");
        $this->pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        $this->pdo->exec("CREATE TABLE IF NOT EXISTS kv_store (
            key_text TEXT PRIMARY KEY,
            value_text TEXT,
            created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
            updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
        )");
    }
    public function set($key, $value) {
        $encoded = json_encode($value);
        $stmt = $this->pdo->prepare(
            "UPDATE kv_store SET value_text = :value, updated_at = CURRENT_TIMESTAMP WHERE key_text = :key"
        );
        $stmt->execute([':key' => $key, ':value' => $encoded]);
        if ($stmt->rowCount() === 0) {
            $stmt = $this->pdo->prepare(
                "INSERT INTO kv_store (key_text, value_text) VALUES (:key, :value)"
            );
            $stmt->execute([':key' => $key, ':value' => $encoded]);
        }
    }
    public function get($key) {
        $stmt = $this->pdo->prepare("SELECT value_text FROM kv_store WHERE key_text = :key");
        $stmt->execute([':key' => $key]);
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($result) {
            return json_decode($result['value_text'], true);
        }
        return null;
    }
    public function delete($key) {
        $stmt = $this->pdo->prepare("DELETE FROM kv_store WHERE key_text = :key");
        $stmt->execute([':key' => $key]);
        return $stmt->rowCount() > 0;
    }
    public function has($key) {
        $stmt = $this->pdo->prepare("SELECT COUNT(*) FROM kv_store WHERE key_text = :key");
        $stmt->execute([':key' => $key]);
        return $stmt->fetchColumn() > 0;
    }
    public function getAll() {
        $stmt = $this->pdo->query("SELECT key_text, value_text FROM kv_store");
        $result = [];
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $result[$row['key_text']] = json_decode($row['value_text'], true);
        }
        return $result;
    }
    public function clear() {
        $this->pdo->exec("DELETE FROM kv_store");
    }
    public function count() {
        return $this->pdo->query("SELECT COUNT(*) FROM kv_store")->fetchColumn();
    }
    public function getMultiple(array $keys) {
        $placeholder = implode(',', array_fill(0, count($keys), '?'));
        $stmt = $this->pdo->prepare("SELECT key_text, value_text FROM kv_store WHERE key_text IN ($placeholder)");
        $stmt->execute($keys);
        $result = [];
        while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) {
            $result[$row['key_text']] = json_decode($row['value_text'], true);
        }
        return $result;
    }
    public function setMultiple(array $data) {
        $this->pdo->beginTransaction();
        try {
            foreach ($data as $key => $value) {
                $this->set($key, $value);
            }
            $this->pdo->commit();
        } catch (Exception $e) {
            $this->pdo->rollBack();
            throw $e;
        }
    }
}
// 使用示例
$store = new SqliteKVStore('data.db');
$store->set('app_config', ['debug' => true, 'env' => 'production']);
$store->setMultiple([
    'user_1' => ['name' => 'Alice', 'age' => 25],
    'user_2' => ['name' => 'Bob', 'age' => 30]
]);
?>

Redis 实现(高性能场景)

<?php
class RedisKVStore {
    private $redis;
    public function __construct($host = '127.0.0.1', $port = 6379) {
        $this->redis = new Redis();
        $this->redis->connect($host, $port);
    }
    public function set($key, $value, $ttl = null) {
        $encoded = json_encode($value);
        if ($ttl) {
            return $this->redis->setex($key, $ttl, $encoded);
        }
        return $this->redis->set($key, $encoded);
    }
    public function get($key) {
        $result = $this->redis->get($key);
        return $result !== false ? json_decode($result, true) : null;
    }
    public function delete($key) {
        return $this->redis->del($key) > 0;
    }
    public function has($key) {
        return $this->redis->exists($key);
    }
    public function getAll() {
        $keys = $this->redis->keys('*');
        $result = [];
        foreach ($keys as $key) {
            $result[$key] = $this->get($key);
        }
        return $result;
    }
    public function clear() {
        return $this->redis->flushDB();
    }
    public function setExpire($key, $ttl) {
        return $this->redis->expire($key, $ttl);
    }
}
// 如果安装了 Predis(纯PHP实现)
// require 'vendor/autoload.php';
// class PredisKVStore {
//     private $client;
//     public function __construct($config = []) {
//         $this->client = new Predis\Client($config);
//     }
//     // 类似的方法
// }
?>

通用接口设计

<?php
interface KVStoreInterface {
    public function set($key, $value);
    public function get($key);
    public function delete($key);
    public function has($key);
    public function getAll();
    public function clear();
}
// 工厂模式
class KVStoreFactory {
    public static function create($type = 'memory', $options = []) {
        switch ($type) {
            case 'memory':
                return new MemoryKVStore();
            case 'file':
                return new FileKVStore($options['path'] ?? 'kvstore.json');
            case 'sqlite':
                return new SqliteKVStore($options['path'] ?? 'kvstore.db');
            case 'redis':
                return new RedisKVStore(
                    $options['host'] ?? '127.0.0.1',
                    $options['port'] ?? 6379
                );
            default:
                throw new InvalidArgumentException("Unsupported store type: {$type}");
        }
    }
}
// 使用示例
$store = KVStoreFactory::create('redis');
$store->set('key', 'value');
echo $store->get('key'); // 输出: value
?>

选择建议

场景 推荐方案 特点
临时数据、简单场景 内存数组 最快,但数据不持久化
小规模持久化 文件存储 简单,适合小型应用
中等规模 SQLite 稳定,支持并发
高并发、分布式 Redis 性能最好,支持TTL

根据您的具体需求选择合适的实现方案即可。

抱歉,评论功能暂时关闭!