FastApi面试系列5(监控、日志、微服务、高并发)
·
1. FastAPI如何实现日志记录?
from fastapi import FastAPI, Request
import logging
import json
from datetime import datetime
app = FastAPI()
# 日志配置
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)
# 结构化日志
import structlog
structlog.configure(
processors=[
structlog.processors.TimeStamper(fmt="iso"),
structlog.processors.JSONRenderer()
]
)
structured_logger = structlog.get_logger()
# 请求日志中间件
@app.middleware("http")
async def log_requests(request: Request, call_next):
start_time = time.time()
# 请求日志
logger.info(f"Request: {request.method} {request.url}")
response = await call_next(request)
# 响应日志
process_time = time.time() - start_time
logger.info(f"Response: {response.status_code} - {process_time:.3f}s")
return response
# 结构化日志中间件
@app.middleware("http")
async def structured_logging(request: Request, call_next):
start_time = time.time()
structured_logger.info(
"request_started",
method=request.method,
path=request.url.path,
client=request.client.host
)
response = await call_next(request)
structured_logger.info(
"request_completed",
status_code=response.status_code,
duration=time.time() - start_time
)
return response
# 异常日志
@app.exception_handler(Exception)
async def log_exception(request: Request, exc: Exception):
logger.exception(f"Unhandled exception: {exc}")
return JSONResponse(
status_code=500,
content={"error": "Internal server error"}
)
# 审计日志
def audit_log(action: str, user_id: int, details: dict):
log_entry = {
"timestamp": datetime.now().isoformat(),
"action": action,
"user_id": user_id,
"details": details
}
logger.info(f"AUDIT: {json.dumps(log_entry)}")
@app.post("/users")
async def create_user(user: UserCreate):
result = save_user(user)
audit_log("create_user", user.id, {"email": user.email})
return result
2. FastAPI如何实现性能监控?
from fastapi import FastAPI, Request
from prometheus_client import Counter, Histogram, generate_latest
from fastapi.responses import PlainTextResponse
import time
app = FastAPI()
# Prometheus指标
REQUEST_COUNT = Counter(
'http_requests_total',
'Total HTTP requests',
['method', 'endpoint', 'status']
)
REQUEST_LATENCY = Histogram(
'http_request_duration_seconds',
'HTTP request latency',
['method', 'endpoint']
)
ACTIVE_REQUESTS = Counter(
'http_requests_active',
'Active HTTP requests',
['method', 'endpoint']
)
# 监控中间件
@app.middleware("http")
async def prometheus_middleware(request: Request, call_next):
method = request.method
endpoint = request.url.path
ACTIVE_REQUESTS.labels(method=method, endpoint=endpoint).inc()
start_time = time.time()
response = await call_next(request)
duration = time.time() - start_time
REQUEST_COUNT.labels(
method=method,
endpoint=endpoint,
status=response.status_code
).inc()
REQUEST_LATENCY.labels(
method=method,
endpoint=endpoint
).observe(duration)
ACTIVE_REQUESTS.labels(method=method, endpoint=endpoint).dec()
return response
# Prometheus端点
@app.get("/metrics")
async def metrics():
return PlainTextResponse(generate_latest())
# 自定义指标
DB_QUERY_COUNT = Counter(
'db_queries_total',
'Total database queries',
['operation']
)
CACHE_HIT_COUNT = Counter(
'cache_hits_total',
'Total cache hits'
)
CACHE_MISS_COUNT = Counter(
'cache_misses_total',
'Total cache misses'
)
# 性能追踪
import functools
import time
def timing_decorator(func):
@functools.wraps(func)
async def wrapper(*args, **kwargs):
start_time = time.time()
result = await func(*args, **kwargs)
duration = time.time() - start_time
logger.info(f"{func.__name__} took {duration:.3f}s")
return result
return wrapper
@app.get("/slow-endpoint")
@timing_decorator
async def slow_endpoint():
await asyncio.sleep(1)
return {"message": "Done"}
# 健康检查
@app.get("/health")
async def health_check():
return {
"status": "healthy",
"timestamp": time.time(),
"version": "1.0.0"
}
3. FastAPI如何实现分布式追踪?
from fastapi import FastAPI, Request
from opentelemetry import trace
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor
from opentelemetry.exporter.jaeger import JaegerExporter
from opentelemetry.sdk.resources import Resource
app = FastAPI()
# 配置追踪
resource = Resource.create({"service.name": "fastapi-app"})
trace.set_tracer_provider(TracerProvider(resource=resource))
jaeger_exporter = JaegerExporter(
agent_host_name="localhost",
agent_port=6831,
)
trace.get_tracer_provider().add_span_processor(
BatchSpanProcessor(jaeger_exporter)
)
tracer = trace.get_tracer(__name__)
# 追踪中间件
@app.middleware("http")
async def tracing_middleware(request: Request, call_next):
with tracer.start_as_current_span(
f"{request.method} {request.url.path}"
) as span:
span.set_attribute("http.method", request.method)
span.set_attribute("http.url", str(request.url))
span.set_attribute("http.host", request.headers.get("host", ""))
response = await call_next(request)
span.set_attribute("http.status_code", response.status_code)
return response
# 追踪函数
@app.get("/traced-operation")
async def traced_operation():
with tracer.start_as_current_span("database_query"):
result = await query_database()
with tracer.start_as_current_span("external_api_call"):
data = await call_external_api()
return {"result": result, "data": data}
# 请求ID追踪
from contextvars import ContextVar
import uuid
request_id_var: ContextVar[str] = ContextVar('request_id', default='')
@app.middleware("http")
async def request_id_middleware(request: Request, call_next):
request_id = request.headers.get("X-Request-ID", str(uuid.uuid4()))
request_id_var.set(request_id)
response = await call_next(request)
response.headers["X-Request-ID"] = request_id
return response
def get_request_id() -> str:
return request_id_var.get()
# 日志关联
class RequestIDFilter(logging.Filter):
def filter(self, record):
record.request_id = get_request_id()
return True
logging.basicConfig(
format='%(asctime)s - [%(request_id)s] - %(levelname)s - %(message)s'
)
logging.getLogger().addFilter(RequestIDFilter())
4. FastAPI如何实现告警系统?
from fastapi import FastAPI
import asyncio
from typing import List
from enum import Enum
app = FastAPI()
class AlertLevel(str, Enum):
INFO = "info"
WARNING = "warning"
ERROR = "error"
CRITICAL = "critical"
class Alert:
def __init__(
self,
level: AlertLevel,
message: str,
details: dict = None
):
self.level = level
self.message = message
self.details = details or {}
self.timestamp = datetime.now()
# 告警处理器
class AlertHandler:
def __init__(self):
self.handlers = []
def add_handler(self, handler):
self.handlers.append(handler)
async def send(self, alert: Alert):
for handler in self.handlers:
try:
await handler(alert)
except Exception as e:
logger.error(f"Alert handler failed: {e}")
alert_handler = AlertHandler()
# 邮件告警
async def email_alert(alert: Alert):
if alert.level in [AlertLevel.ERROR, AlertLevel.CRITICAL]:
send_email(
to="admin@example.com",
subject=f"[{alert.level.value.upper()}] {alert.message}",
body=json.dumps(alert.details, indent=2)
)
# Slack告警
async def slack_alert(alert: Alert):
import httpx
webhook_url = "https://hooks.slack.com/services/xxx"
async with httpx.AsyncClient() as client:
await client.post(webhook_url, json={
"text": f"[{alert.level.value.upper()}] {alert.message}",
"attachments": [{
"text": json.dumps(alert.details, indent=2)
}]
})
alert_handler.add_handler(email_alert)
alert_handler.add_handler(slack_alert)
# 错误监控
@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
alert = Alert(
level=AlertLevel.ERROR,
message=str(exc),
details={
"path": request.url.path,
"method": request.method,
"exception_type": type(exc).__name__
}
)
await alert_handler.send(alert)
return JSONResponse(
status_code=500,
content={"error": "Internal server error"}
)
# 性能告警
@app.middleware("http")
async def performance_alert(request: Request, call_next):
start_time = time.time()
response = await call_next(request)
duration = time.time() - start_time
if duration > 5: # 超过5秒
alert = Alert(
level=AlertLevel.WARNING,
message=f"Slow request: {request.url.path}",
details={
"duration": duration,
"method": request.method
}
)
await alert_handler.send(alert)
return response
# 健康检查告警
async def health_check_monitor():
while True:
try:
async with httpx.AsyncClient() as client:
response = await client.get("http://localhost:8000/health")
if response.status_code != 200:
alert = Alert(
level=AlertLevel.CRITICAL,
message="Health check failed",
details={"status_code": response.status_code}
)
await alert_handler.send(alert)
except Exception as e:
alert = Alert(
level=AlertLevel.CRITICAL,
message="Health check exception",
details={"error": str(e)}
)
await alert_handler.send(alert)
await asyncio.sleep(60)
@app.on_event("startup")
async def start_health_monitor():
asyncio.create_task(health_check_monitor())
5. FastAPI如何实现微服务架构?
from fastapi import FastAPI
import httpx
import asyncio
# 服务网关
app = FastAPI()
# 服务注册
SERVICES = {
"user-service": "http://localhost:8001",
"order-service": "http://localhost:8002",
"product-service": "http://localhost:8003"
}
# 服务路由
@app.api_route("/{service_name}/{path:path}", methods=["GET", "POST", "PUT", "DELETE"])
async def proxy_request(service_name: str, path: str, request: Request):
if service_name not in SERVICES:
raise HTTPException(status_code=404, detail="Service not found")
service_url = SERVICES[service_name]
async with httpx.AsyncClient() as client:
response = await client.request(
method=request.method,
url=f"{service_url}/{path}",
headers=dict(request.headers),
content=await request.body()
)
return Response(
content=response.content,
status_code=response.status_code,
headers=dict(response.headers)
)
# 服务聚合
@app.get("/user-orders/{user_id}")
async def get_user_orders(user_id: int):
async with httpx.AsyncClient() as client:
# 并发调用多个服务
user_task = client.get(f"{SERVICES['user-service']}/users/{user_id}")
orders_task = client.get(f"{SERVICES['order-service']}/orders?user_id={user_id}")
user_response, orders_response = await asyncio.gather(user_task, orders_task)
return {
"user": user_response.json(),
"orders": orders_response.json()
}
# 服务熔断
from circuitbreaker import circuit
@circuit(failure_threshold=5, recovery_timeout=30)
async def call_user_service(user_id: int):
async with httpx.AsyncClient() as client:
response = await client.get(f"{SERVICES['user-service']}/users/{user_id}")
return response.json()
@app.get("/users/{user_id}")
async def get_user(user_id: int):
try:
user = await call_user_service(user_id)
return user
except Exception:
return {"error": "Service unavailable"}
6. FastAPI如何实现服务间通信?
from fastapi import FastAPI
import httpx
import asyncio
from typing import Optional
app = FastAPI()
# HTTP客户端
class ServiceClient:
def __init__(self, base_url: str, timeout: int = 30):
self.base_url = base_url
self.client = httpx.AsyncClient(timeout=timeout)
async def get(self, path: str, params: dict = None):
response = await self.client.get(f"{self.base_url}{path}", params=params)
return response.json()
async def post(self, path: str, data: dict):
response = await self.client.post(f"{self.base_url}{path}", json=data)
return response.json()
async def close(self):
await self.client.aclose()
user_client = ServiceClient("http://localhost:8001")
order_client = ServiceClient("http://localhost:8002")
# 同步调用
@app.get("/sync-call")
async def sync_call(user_id: int):
user = await user_client.get(f"/users/{user_id}")
orders = await order_client.get(f"/orders", {"user_id": user_id})
return {"user": user, "orders": orders}
# 并发调用
@app.get("/concurrent-call")
async def concurrent_call(user_id: int):
user_task = user_client.get(f"/users/{user_id}")
orders_task = order_client.get(f"/orders", {"user_id": user_id})
user, orders = await asyncio.gather(user_task, orders_task)
return {"user": user, "orders": orders}
# 消息队列通信
import aio_pika
async def send_message(queue: str, message: dict):
connection = await aio_pika.connect_robust("amqp://localhost")
async with connection:
channel = await connection.channel()
await channel.declare_queue(queue, durable=True)
await channel.default_exchange.publish(
aio_pika.Message(body=json.dumps(message).encode()),
routing_key=queue
)
@app.post("/async-message")
async def send_async_message(data: dict):
await send_message("task_queue", data)
return {"message": "Message sent"}
# gRPC通信
import grpc
from generated import user_pb2, user_pb2_grpc
async def get_user_grpc(user_id: int):
async with grpc.aio.insecure_channel('localhost:50051') as channel:
stub = user_pb2_grpc.UserServiceStub(channel)
response = await stub.GetUser(user_pb2.GetUserRequest(id=user_id))
return {"id": response.id, "name": response.name}
7. FastAPI如何实现服务熔断?
from fastapi import FastAPI
from circuitbreaker import circuit
import httpx
from enum import Enum
app = FastAPI()
# 使用circuitbreaker库
@circuit(failure_threshold=5, recovery_timeout=30)
async def call_external_service(url: str):
async with httpx.AsyncClient() as client:
response = await client.get(url)
response.raise_for_status()
return response.json()
# 自定义熔断器
class CircuitState(Enum):
CLOSED = "closed"
OPEN = "open"
HALF_OPEN = "half_open"
class CircuitBreaker:
def __init__(
self,
failure_threshold: int = 5,
recovery_timeout: int = 30,
success_threshold: int = 2
):
self.failure_threshold = failure_threshold
self.recovery_timeout = recovery_timeout
self.success_threshold = success_threshold
self.failure_count = 0
self.success_count = 0
self.state = CircuitState.CLOSED
self.last_failure_time = None
async def call(self, func, *args, **kwargs):
if self.state == CircuitState.OPEN:
if self._should_attempt_reset():
self.state = CircuitState.HALF_OPEN
else:
raise Exception("Circuit breaker is open")
try:
result = await func(*args, **kwargs)
self._on_success()
return result
except Exception as e:
self._on_failure()
raise e
def _should_attempt_reset(self) -> bool:
return (
self.last_failure_time and
time.time() - self.last_failure_time >= self.recovery_timeout
)
def _on_success(self):
self.failure_count = 0
if self.state == CircuitState.HALF_OPEN:
self.success_count += 1
if self.success_count >= self.success_threshold:
self.state = CircuitState.CLOSED
self.success_count = 0
def _on_failure(self):
self.failure_count += 1
self.last_failure_time = time.time()
if self.state == CircuitState.HALF_OPEN:
self.state = CircuitState.OPEN
self.success_count = 0
elif self.failure_count >= self.failure_threshold:
self.state = CircuitState.OPEN
# 使用自定义熔断器
breaker = CircuitBreaker()
@app.get("/protected-call")
async def protected_call():
try:
result = await breaker.call(call_external_api)
return result
except Exception as e:
return {"error": str(e)}
# 熔断器状态监控
@app.get("/circuit-status")
async def circuit_status():
return {
"state": breaker.state.value,
"failure_count": breaker.failure_count,
"success_count": breaker.success_count
}
8. FastAPI如何实现服务降级?
from fastapi import FastAPI
import httpx
from functools import wraps
app = FastAPI()
# 降级装饰器
def fallback(fallback_func):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
try:
return await func(*args, **kwargs)
except Exception as e:
return await fallback_func(*args, **kwargs)
return wrapper
return decorator
# 默认降级响应
async def default_fallback():
return {"message": "Service temporarily unavailable", "cached": True}
# 使用降级
@app.get("/users/{user_id}")
@fallback(default_fallback)
async def get_user(user_id: int):
async with httpx.AsyncClient() as client:
response = await client.get(f"http://user-service/users/{user_id}")
response.raise_for_status()
return response.json()
# 缓存降级
import redis.asyncio as redis
redis_client = redis.from_url("redis://localhost")
async def cached_fallback(key: str):
cached = await redis_client.get(key)
if cached:
return {"data": json.loads(cached), "cached": True}
return {"error": "No cached data available"}
@app.get("/products/{product_id}")
async def get_product(product_id: int):
try:
async with httpx.AsyncClient() as client:
response = await client.get(f"http://product-service/products/{product_id}")
data = response.json()
# 更新缓存
await redis_client.setex(
f"product:{product_id}",
300,
json.dumps(data)
)
return data
except Exception:
return await cached_fallback(f"product:{product_id}")
# 功能降级
class FeatureFlags:
def __init__(self):
self.flags = {
"recommendations": True,
"reviews": True,
"related_products": True
}
def is_enabled(self, feature: str) -> bool:
return self.flags.get(feature, False)
def disable(self, feature: str):
self.flags[feature] = False
def enable(self, feature: str):
self.flags[feature] = True
feature_flags = FeatureFlags()
@app.get("/product-details/{product_id}")
async def get_product_details(product_id: int):
result = {"product": await get_product(product_id)}
if feature_flags.is_enabled("recommendations"):
try:
result["recommendations"] = await get_recommendations(product_id)
except Exception:
feature_flags.disable("recommendations")
if feature_flags.is_enabled("reviews"):
try:
result["reviews"] = await get_reviews(product_id)
except Exception:
feature_flags.disable("reviews")
return result
9. FastAPI如何处理高并发请求?
from fastapi import FastAPI
import asyncio
from concurrent.futures import ThreadPoolExecutor
import uvicorn
app = FastAPI()
# 使用uvicorn多worker
# uvicorn main:app --workers 4
# 线程池处理CPU密集型任务
executor = ThreadPoolExecutor(max_workers=10)
@app.get("/cpu-intensive")
async def cpu_intensive_task():
loop = asyncio.get_event_loop()
result = await loop.run_in_executor(executor, heavy_computation)
return {"result": result}
# 并发控制
from asyncio import Semaphore
MAX_CONCURRENT = 100
semaphore = Semaphore(MAX_CONCURRENT)
@app.get("/limited-concurrent")
async def limited_concurrent():
async with semaphore:
result = await process_request()
return result
# 连接池复用
import httpx
http_client = httpx.AsyncClient(
limits=httpx.Limits(
max_keepalive_connections=100,
max_connections=200
)
)
@app.get("/external-api")
async def call_external():
response = await http_client.get("https://api.example.com/data")
return response.json()
# 异步数据库连接池
from sqlalchemy.ext.asyncio import create_async_engine
engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost/db",
pool_size=20,
max_overflow=10
)
# 响应流式处理
from fastapi.responses import StreamingResponse
@app.get("/stream")
async def stream_response():
async def generate():
for i in range(1000):
yield f"data: {i}\n"
await asyncio.sleep(0.01)
return StreamingResponse(generate(), media_type="text/event-stream")
# 批量处理
@app.post("/batch")
async def batch_process(items: list):
tasks = [process_item(item) for item in items]
results = await asyncio.gather(*tasks, return_exceptions=True)
return {"results": results}
10. FastAPI如何实现请求限流?
from fastapi import FastAPI, Request, HTTPException
from fastapi.responses import JSONResponse
import time
from collections import defaultdict
import asyncio
app = FastAPI()
# 令牌桶限流
class TokenBucket:
def __init__(self, rate: int, capacity: int):
self.rate = rate
self.capacity = capacity
self.buckets = {}
def get_bucket(self, key: str):
if key not in self.buckets:
self.buckets[key] = {
"tokens": self.capacity,
"last_update": time.time()
}
return self.buckets[key]
def is_allowed(self, key: str) -> bool:
bucket = self.get_bucket(key)
now = time.time()
# 添加令牌
elapsed = now - bucket["last_update"]
bucket["tokens"] = min(
self.capacity,
bucket["tokens"] + elapsed * self.rate
)
bucket["last_update"] = now
if bucket["tokens"] >= 1:
bucket["tokens"] -= 1
return True
return False
limiter = TokenBucket(rate=10, capacity=100)
@app.middleware("http")
async def rate_limit_middleware(request: Request, call_next):
client_id = request.client.host
if not limiter.is_allowed(client_id):
return JSONResponse(
status_code=429,
content={"error": "Too many requests"}
)
return await call_next(request)
# 滑动窗口限流
class SlidingWindow:
def __init__(self, max_requests: int, window_seconds: int):
self.max_requests = max_requests
self.window_seconds = window_seconds
self.requests = defaultdict(list)
def is_allowed(self, key: str) -> bool:
now = time.time()
requests = self.requests[key]
# 移除过期请求
while requests and now - requests[0] > self.window_seconds:
requests.pop(0)
if len(requests) >= self.max_requests:
return False
requests.append(now)
return True
# 分布式限流(Redis)
import redis.asyncio as redis
redis_client = redis.from_url("redis://localhost")
async def distributed_rate_limit(key: str, limit: int, window: int) -> bool:
now = time.time()
window_start = now - window
pipe = redis_client.pipeline()
await pipe.zremrangebyscore(key, 0, window_start)
await pipe.zadd(key, {str(now): now})
await pipe.zcard(key)
await pipe.expire(key, window)
results = await pipe.execute()
return results[2] <= limit
@app.get("/limited")
async def limited_endpoint(request: Request):
client_id = request.client.host
if not await distributed_rate_limit(f"rate:{client_id}", 100, 60):
raise HTTPException(status_code=429, detail="Too many requests")
return {"message": "OK"}
11. FastAPI如何实现数据库连接池管理?
from fastapi import FastAPI, Depends
from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker, Session
from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
app = FastAPI()
# 同步连接池
sync_engine = create_engine(
"postgresql://user:pass@localhost/db",
pool_size=20, # 连接池大小
max_overflow=10, # 最大溢出连接
pool_timeout=30, # 获取连接超时
pool_recycle=3600, # 连接回收时间
pool_pre_ping=True, # 连接前检查
echo_pool=True # 连接池日志
)
SyncSessionLocal = sessionmaker(bind=sync_engine)
# 异步连接池
async_engine = create_async_engine(
"postgresql+asyncpg://user:pass@localhost/db",
pool_size=20,
max_overflow=10,
pool_timeout=30,
pool_recycle=3600
)
AsyncSessionLocal = sessionmaker(
async_engine,
class_=AsyncSession,
expire_on_commit=False
)
# 依赖注入
def get_sync_db():
db = SyncSessionLocal()
try:
yield db
finally:
db.close()
async def get_async_db():
async with AsyncSessionLocal() as session:
try:
yield session
finally:
await session.close()
# 使用连接池
@app.get("/users")
async def get_users(db: Session = Depends(get_sync_db)):
return db.query(User).all()
@app.get("/async-users")
async def get_async_users(db: AsyncSession = Depends(get_async_db)):
result = await db.execute(select(User))
return result.scalars().all()
# 连接池监控
@app.get("/pool-stats")
async def pool_stats():
return {
"pool_size": sync_engine.pool.size(),
"checked_in": sync_engine.pool.checkedin(),
"checked_out": sync_engine.pool.checkedout(),
"overflow": sync_engine.pool.overflow()
}
# 连接池预热
@app.on_event("startup")
async def warmup_pool():
# 预先创建连接
for _ in range(10):
db = SyncSessionLocal()
db.execute("SELECT 1")
db.close()
12. FastAPI如何实现缓存策略?
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
import redis.asyncio as redis
from functools import wraps
import hashlib
import json
app = FastAPI()
redis_client = redis.from_url("redis://localhost")
# 缓存装饰器
def cache(ttl: int = 300):
def decorator(func):
@wraps(func)
async def wrapper(*args, **kwargs):
# 生成缓存键
cache_key = f"{func.__name__}:{hashlib.md5(str(args).encode()).hexdigest()}"
# 尝试从缓存获取
cached = await redis_client.get(cache_key)
if cached:
return json.loads(cached)
# 执行函数
result = await func(*args, **kwargs)
# 存储到缓存
await redis_client.setex(cache_key, ttl, json.dumps(result))
return result
return wrapper
return decorator
# HTTP缓存头
@app.get("/items")
async def get_items(response: Response):
items = fetch_items()
# 设置缓存头
response.headers["Cache-Control"] = "public, max-age=300"
response.headers["ETag"] = compute_etag(items)
return items
# 条件请求
@app.get("/conditional")
async def conditional_request(request: Request):
data = get_data()
etag = compute_etag(data)
if request.headers.get("If-None-Match") == etag:
return Response(status_code=304)
return JSONResponse(content=data, headers={"ETag": etag})
# 多级缓存
class MultiLevelCache:
def __init__(self):
self.local_cache = {}
self.redis = redis_client
async def get(self, key: str):
# L1: 本地缓存
if key in self.local_cache:
return self.local_cache[key]
# L2: Redis缓存
data = await self.redis.get(key)
if data:
self.local_cache[key] = json.loads(data)
return self.local_cache[key]
return None
async def set(self, key: str, value, ttl: int = 300):
self.local_cache[key] = value
await self.redis.setex(key, ttl, json.dumps(value))
async def delete(self, key: str):
self.local_cache.pop(key, None)
await self.redis.delete(key)
# 缓存失效
@app.post("/items")
async def create_item(item: ItemCreate):
result = save_item(item)
# 清除相关缓存
await redis_client.delete("items_list")
return result
更多推荐


所有评论(0)