引入Redis
This commit is contained in:
210
src/common/database/optimization/cache_backend.py
Normal file
210
src/common/database/optimization/cache_backend.py
Normal file
@@ -0,0 +1,210 @@
|
||||
"""缓存后端抽象基类
|
||||
|
||||
定义统一的缓存接口,支持多种缓存后端实现:
|
||||
- MemoryCache: 内存多级缓存(L1 + L2)
|
||||
- RedisCache: Redis 分布式缓存
|
||||
"""
|
||||
|
||||
from abc import ABC, abstractmethod
|
||||
from dataclasses import dataclass
|
||||
from typing import Any
|
||||
|
||||
|
||||
@dataclass
|
||||
class CacheStats:
|
||||
"""缓存统计信息
|
||||
|
||||
Attributes:
|
||||
hits: 命中次数
|
||||
misses: 未命中次数
|
||||
evictions: 淘汰次数
|
||||
total_size: 总大小(字节)
|
||||
item_count: 条目数量
|
||||
"""
|
||||
|
||||
hits: int = 0
|
||||
misses: int = 0
|
||||
evictions: int = 0
|
||||
total_size: int = 0
|
||||
item_count: int = 0
|
||||
|
||||
@property
|
||||
def hit_rate(self) -> float:
|
||||
"""命中率"""
|
||||
total = self.hits + self.misses
|
||||
return self.hits / total if total > 0 else 0.0
|
||||
|
||||
@property
|
||||
def eviction_rate(self) -> float:
|
||||
"""淘汰率"""
|
||||
return self.evictions / self.item_count if self.item_count > 0 else 0.0
|
||||
|
||||
|
||||
class CacheBackend(ABC):
|
||||
"""缓存后端抽象基类
|
||||
|
||||
定义统一的缓存操作接口,所有缓存实现必须继承此类
|
||||
"""
|
||||
|
||||
@abstractmethod
|
||||
async def get(self, key: str) -> Any | None:
|
||||
"""从缓存获取数据
|
||||
|
||||
Args:
|
||||
key: 缓存键
|
||||
|
||||
Returns:
|
||||
缓存值,如果不存在返回 None
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def set(
|
||||
self,
|
||||
key: str,
|
||||
value: Any,
|
||||
ttl: float | None = None,
|
||||
) -> None:
|
||||
"""设置缓存值
|
||||
|
||||
Args:
|
||||
key: 缓存键
|
||||
value: 缓存值
|
||||
ttl: 过期时间(秒),None 表示使用默认 TTL
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def delete(self, key: str) -> bool:
|
||||
"""删除缓存条目
|
||||
|
||||
Args:
|
||||
key: 缓存键
|
||||
|
||||
Returns:
|
||||
是否成功删除
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def exists(self, key: str) -> bool:
|
||||
"""检查键是否存在
|
||||
|
||||
Args:
|
||||
key: 缓存键
|
||||
|
||||
Returns:
|
||||
键是否存在
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def clear(self) -> None:
|
||||
"""清空所有缓存"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def get_stats(self) -> dict[str, Any]:
|
||||
"""获取缓存统计信息
|
||||
|
||||
Returns:
|
||||
包含命中率、条目数等统计数据的字典
|
||||
"""
|
||||
pass
|
||||
|
||||
@abstractmethod
|
||||
async def close(self) -> None:
|
||||
"""关闭缓存连接/清理资源"""
|
||||
pass
|
||||
|
||||
async def get_or_load(
|
||||
self,
|
||||
key: str,
|
||||
loader: Any,
|
||||
ttl: float | None = None,
|
||||
) -> Any | None:
|
||||
"""获取缓存或通过 loader 加载
|
||||
|
||||
Args:
|
||||
key: 缓存键
|
||||
loader: 数据加载函数(同步或异步)
|
||||
ttl: 过期时间(秒)
|
||||
|
||||
Returns:
|
||||
缓存值或加载的值
|
||||
"""
|
||||
import asyncio
|
||||
|
||||
# 尝试从缓存获取
|
||||
value = await self.get(key)
|
||||
if value is not None:
|
||||
return value
|
||||
|
||||
# 缓存未命中,使用 loader 加载
|
||||
if loader is not None:
|
||||
if asyncio.iscoroutinefunction(loader):
|
||||
value = await loader()
|
||||
else:
|
||||
value = loader()
|
||||
|
||||
if value is not None:
|
||||
await self.set(key, value, ttl=ttl)
|
||||
|
||||
return value
|
||||
|
||||
return None
|
||||
|
||||
async def delete_pattern(self, pattern: str) -> int:
|
||||
"""删除匹配模式的所有键(可选实现)
|
||||
|
||||
Args:
|
||||
pattern: 键模式(支持 * 通配符)
|
||||
|
||||
Returns:
|
||||
删除的键数量
|
||||
"""
|
||||
# 默认实现:不支持模式删除
|
||||
raise NotImplementedError("此缓存后端不支持模式删除")
|
||||
|
||||
async def mget(self, keys: list[str]) -> dict[str, Any]:
|
||||
"""批量获取多个键的值(可选实现)
|
||||
|
||||
Args:
|
||||
keys: 键列表
|
||||
|
||||
Returns:
|
||||
键值对字典,不存在的键不包含在结果中
|
||||
"""
|
||||
# 默认实现:逐个获取
|
||||
result = {}
|
||||
for key in keys:
|
||||
value = await self.get(key)
|
||||
if value is not None:
|
||||
result[key] = value
|
||||
return result
|
||||
|
||||
async def mset(
|
||||
self,
|
||||
mapping: dict[str, Any],
|
||||
ttl: float | None = None,
|
||||
) -> None:
|
||||
"""批量设置多个键值对(可选实现)
|
||||
|
||||
Args:
|
||||
mapping: 键值对字典
|
||||
ttl: 过期时间(秒)
|
||||
"""
|
||||
# 默认实现:逐个设置
|
||||
for key, value in mapping.items():
|
||||
await self.set(key, value, ttl=ttl)
|
||||
|
||||
@property
|
||||
@abstractmethod
|
||||
def backend_type(self) -> str:
|
||||
"""返回缓存后端类型标识"""
|
||||
pass
|
||||
|
||||
@property
|
||||
def is_distributed(self) -> bool:
|
||||
"""是否为分布式缓存(默认 False)"""
|
||||
return False
|
||||
Reference in New Issue
Block a user