本文目录导读:

我来帮你分析Python排查缓存读写异常的方法和脚本示例。
基础缓存读写监控脚本
#!/usr/bin/env python3
"""
缓存读写异常排查工具
支持: Redis、Memcached、本地缓存
"""
import time
import logging
import traceback
from typing import Any, Optional
from datetime import datetime
from functools import wraps
# 配置日志
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.FileHandler('cache_monitor.log'),
logging.StreamHandler()
]
)
logger = logging.getLogger(__name__)
class CacheMonitor:
"""缓存监控器"""
def __init__(self, name: str = "default"):
self.name = name
self.stats = {
'read_attempts': 0,
'write_attempts': 0,
'read_success': 0,
'write_success': 0,
'read_failures': 0,
'write_failures': 0,
'total_read_time': 0,
'total_write_time': 0,
'last_error': None,
'error_count': 0
}
self.slow_threshold = 1.0 # 慢操作阈值(秒)
def monitor_read(self, func):
"""装饰器:监控读操作"""
@wraps(func)
def wrapper(*args, **kwargs):
self.stats['read_attempts'] += 1
start_time = time.time()
try:
result = func(*args, **kwargs)
elapsed = time.time() - start_time
self.stats['read_success'] += 1
self.stats['total_read_time'] += elapsed
# 记录慢操作
if elapsed > self.slow_threshold:
logger.warning(
f"慢读操作: {func.__name__} 耗时 {elapsed:.3f}s"
)
return result
except Exception as e:
elapsed = time.time() - start_time
self.stats['read_failures'] += 1
self.stats['last_error'] = str(e)
self.stats['error_count'] += 1
logger.error(
f"缓存读取异常: {func.__name__}\n"
f"错误信息: {str(e)}\n"
f"堆栈: {traceback.format_exc()}"
)
raise
return wrapper
def monitor_write(self, func):
"""装饰器:监控写操作"""
@wraps(func)
def wrapper(*args, **kwargs):
self.stats['write_attempts'] += 1
start_time = time.time()
try:
result = func(*args, **kwargs)
elapsed = time.time() - start_time
self.stats['write_success'] += 1
self.stats['total_write_time'] += elapsed
if elapsed > self.slow_threshold:
logger.warning(
f"慢写操作: {func.__name__} 耗时 {elapsed:.3f}s"
)
return result
except Exception as e:
elapsed = time.time() - start_time
self.stats['write_failures'] += 1
self.stats['last_error'] = str(e)
self.stats['error_count'] += 1
logger.error(
f"缓存写入异常: {func.__name__}\n"
f"错误信息: {str(e)}\n"
f"堆栈: {traceback.format_exc()}"
)
raise
return wrapper
def get_report(self) -> dict:
"""获取监控报告"""
total_ops = self.stats['read_attempts'] + self.stats['write_attempts']
read_fail_rate = (
self.stats['read_failures'] / self.stats['read_attempts'] * 100
if self.stats['read_attempts'] > 0 else 0
)
write_fail_rate = (
self.stats['write_failures'] / self.stats['write_attempts'] * 100
if self.stats['write_attempts'] > 0 else 0
)
avg_read_time = (
self.stats['total_read_time'] / self.stats['read_success']
if self.stats['read_success'] > 0 else 0
)
avg_write_time = (
self.stats['total_write_time'] / self.stats['write_success']
if self.stats['write_success'] > 0 else 0
)
return {
'monitor_name': self.name,
'total_operations': total_ops,
'read_stats': {
'attempts': self.stats['read_attempts'],
'success': self.stats['read_success'],
'failures': self.stats['read_failures'],
'failure_rate': f"{read_fail_rate:.2f}%",
'avg_time': f"{avg_read_time:.3f}s"
},
'write_stats': {
'attempts': self.stats['write_attempts'],
'success': self.stats['write_success'],
'failures': self.stats['write_failures'],
'failure_rate': f"{write_fail_rate:.2f}%",
'avg_time': f"{avg_write_time:.3f}s"
},
'errors': {
'total_errors': self.stats['error_count'],
'last_error': self.stats['last_error']
},
'timestamp': datetime.now().isoformat()
}
具体缓存实现监控
import redis
import json
from typing import Optional
class RedisCacheMonitor:
"""Redis缓存监控"""
def __init__(self, host='localhost', port=6379, db=0):
self.redis_client = redis.Redis(
host=host,
port=port,
db=db,
socket_connect_timeout=5,
socket_timeout=5,
retry_on_timeout=True,
health_check_interval=30
)
self.monitor = CacheMonitor("redis")
self.connection_errors = 0
self.timeout_errors = 0
def check_connection(self) -> bool:
"""检查Redis连接"""
try:
self.redis_client.ping()
return True
except redis.ConnectionError as e:
logger.error(f"Redis连接失败: {e}")
self.connection_errors += 1
return False
except redis.TimeoutError as e:
logger.error(f"Redis连接超时: {e}")
self.timeout_errors += 1
return False
@CacheMonitor.monitor_read
def get(self, key: str) -> Optional[Any]:
"""读取缓存"""
if not self.check_connection():
return None
try:
data = self.redis_client.get(key)
if data:
return json.loads(data)
return None
except redis.RedisError as e:
logger.error(f"Redis读取异常 [{key}]: {e}")
raise
@CacheMonitor.monitor_write
def set(self, key: str, value: Any, expire: int = 3600):
"""写入缓存"""
if not self.check_connection():
return False
try:
serialized = json.dumps(value, default=str)
return self.redis_client.setex(key, expire, serialized)
except redis.RedisError as e:
logger.error(f"Redis写入异常 [{key}]: {e}")
raise
def health_check(self) -> dict:
"""健康检查"""
return {
'connection_ok': self.check_connection(),
'connection_errors': self.connection_errors,
'timeout_errors': self.timeout_errors,
'memory_info': self._get_memory_info()
}
def _get_memory_info(self) -> dict:
"""获取内存信息"""
try:
info = self.redis_client.info('memory')
return {
'used_memory': info.get('used_memory_human', 'N/A'),
'peak_memory': info.get('used_memory_peak_human', 'N/A'),
'fragmentation': info.get('mem_fragmentation_ratio', 'N/A')
}
except:
return {'error': '无法获取内存信息'}
异常分析工具类
import statistics
from collections import deque
from typing import List, Dict
class CacheExceptionAnalyzer:
"""缓存异常分析器"""
def __init__(self, window_size: int = 100):
self.window_size = window_size
self.exception_history = deque(maxlen=window_size)
self.time_buckets = {} # 按时间段统计异常
def record_exception(self, exception_type: str, key: str,
error_msg: str, duration: float):
"""记录异常"""
record = {
'timestamp': time.time(),
'type': exception_type,
'key': key,
'message': error_msg,
'duration': duration
}
self.exception_history.append(record)
# 按小时统计
hour_key = datetime.now().strftime('%Y-%m-%d %H:00')
if hour_key not in self.time_buckets:
self.time_buckets[hour_key] = []
self.time_buckets[hour_key].append(record)
def analyze_exceptions(self) -> Dict:
"""分析异常模式"""
if not self.exception_history:
return {'message': '没有异常记录'}
# 异常类型统计
type_stats = {}
for record in self.exception_history:
exc_type = record['type']
type_stats[exc_type] = type_stats.get(exc_type, 0) + 1
# 频率分析
recent_count = len(self.exception_history)
time_span = (time.time() - self.exception_history[0]['timestamp']) / 60 # 分钟
# 识别异常模式
patterns = []
# 检查是否频繁超时
timeout_records = [
r for r in self.exception_history
if 'timeout' in r['type'].lower()
]
if len(timeout_records) > self.window_size * 0.3:
patterns.append("频繁超时 - 建议检查网络和连接池")
# 检查连接错误
conn_errors = [
r for r in self.exception_history
if 'connection' in r['type'].lower()
]
if conn_errors:
patterns.append("存在连接错误 - 建议检查Redis/Memcached服务器状态")
# 检查键冲突
key_conflicts = [
r for r in self.exception_history
if 'key' in r['type'].lower()
]
if key_conflicts:
patterns.append("键相关错误 - 建议检查键命名规范")
return {
'total_exceptions': recent_count,
'frequency_per_minute': f"{recent_count/time_span:.2f}" if time_span > 0 else "0",
'type_distribution': type_stats,
'detected_patterns': patterns,
'top_error_keys': self._get_top_error_keys(5),
'time_based_distribution': self.time_buckets
}
def _get_top_error_keys(self, n: int) -> List:
"""获取最常见的异常键"""
key_count = {}
for record in self.exception_history:
key = record['key']
key_count[key] = key_count.get(key, 0) + 1
return sorted(
key_count.items(),
key=lambda x: x[1],
reverse=True
)[:n]
使用示例
def main():
"""主函数示例"""
# 初始化缓存监控
redis_monitor = RedisCacheMonitor(
host='localhost',
port=6379
)
analyzer = CacheExceptionAnalyzer(window_size=1000)
# 模拟业务操作
try:
# 写入缓存
redis_monitor.set('user:1001', {
'name': '张三',
'age': 30,
'last_login': datetime.now().isoformat()
}, expire=3600)
# 读取缓存
user_data = redis_monitor.get('user:1001')
print(f"读取到数据: {user_data}")
except redis.ConnectionError:
analyzer.record_exception(
'ConnectionError',
'user:1001',
'Redis连接失败',
time.time()
)
except redis.TimeoutError:
analyzer.record_exception(
'TimeoutError',
'user:1001',
'读取超时',
time.time()
)
finally:
# 获取监控报告
report = redis_monitor.monitor.get_report()
print("缓存监控报告:", json.dumps(report, indent=2, ensure_ascii=False))
# 异常分析
analysis = analyzer.analyze_exceptions()
if analysis:
print("异常分析结果:", json.dumps(analysis, indent=2, ensure_ascii=False))
# 健康检查
health = redis_monitor.health_check()
print("健康检查:", json.dumps(health, indent=2, ensure_ascii=False))
if __name__ == "__main__":
main()
关键排查点
| 异常类型 | 可能原因 | 排查方法 |
|---|---|---|
| 连接超时 | 网络问题、连接池耗尽 | 检查网络、增加连接池大小 |
| 读取失败 | key不存在、数据损坏 | 检查序列化/反序列化 |
| 写入失败 | 内存不足、数据过大 | 监控内存使用、分片存储 |
| 响应慢 | 大key、复杂查询 | 使用slowlog分析 |
这个脚本可以帮助你:
- 实时监控所有缓存操作
- 自动分析异常模式
- 生成报告便于定位问题
- 健康检查及时发现潜在风险
建议定期运行此脚本,并结合日志监控系统进行持续观察。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播