一、背景
本人在开发一款AI生成PPT的平台,需要处理大量的模板文件、图片资源和用户生成内容。而传统的单一存储方案在面对海量数据、多样化存储需求时显得力不从心。
因此本项目采用了MySQL存储结构化元数据、MinIO存储大文件的混合架构,不仅解决了存储成本问题,还实现了优异的性能表现,以及实现双向校验、动态安全迁移等功能。
因此,作为总结,屏蔽掉项目的业务信息和核心技术细节,将混合存储部分掰开给大家讲讲,并争取让大家拿来即用,或者参考实现。
二、混合存储架构的理论基础
2.1 设计理念
混合存储架构的核心思想是"数据分层存储"------根据数据的特性、访问频率和业务需求,将不同类型的数据存储在最适合的存储系统中。这种架构遵循以下设计原则:
数据特性分离原则:
- 结构化数据(元数据、索引、关系数据)→ 关系型数据库
- 非结构化数据(文件、图片、文档)→ 对象存储
访问模式优化原则:
- 频繁查询的小数据 → 高性能数据库
- 大文件存储和传输 → 专用对象存储
2.2 适用场景
混合存储架构特别适合以下业务场景:
- 内容管理系统:需要存储大量文档、图片、视频等多媒体文件
- 电商平台:商品信息存储在数据库,商品图片存储在对象存储
- 教育平台:课程元数据和课件文件的分离存储
- 企业文档系统:文档索引和文档内容的分层管理
2.3 技术优势
相比单一存储方案,混合存储架构具有以下显著优势:
成本优势:
- 对象存储成本通常比数据库存储低60-80%
- 可根据访问频率选择不同存储类别,进一步降低成本
性能优势:
- 数据库专注于结构化查询,性能更优
- 对象存储提供CDN加速,文件访问速度更快
扩展性优势:
- 对象存储几乎无容量限制
- 数据库和对象存储可独立扩展
可靠性优势:
- 多重备份策略,降低数据丢失风险
- 故障隔离,单一存储故障不影响整体服务
三、架构设计分析
3.1 存储策略设计
在实际的企业级应用中,存储架构需要经过精心设计,实现数据的合理分层:
MySQL存储层:
- 业务元数据(ID、名称、描述、标签等)
- 用户认证信息和权限数据
- 业务关系数据(分类信息、统计数据等)
- 存储位置索引和完整性校验信息
MinIO存储层:
- 大文件内容(JSON文档、配置文件等)
- 多媒体资源(图片、视频、音频)
- 用户上传的自定义资源
数据库表结构设计示例:
sql
CREATE TABLE `content_templates` (
`id` INT PRIMARY KEY AUTO_INCREMENT COMMENT '主键ID',
`uuid` VARCHAR(36) NOT NULL UNIQUE COMMENT '内容UUID',
`name` VARCHAR(200) NOT NULL COMMENT '内容名称',
`description` TEXT COMMENT '内容描述',
`category_code` VARCHAR(50) NOT NULL COMMENT '分类编码',
`type_code` VARCHAR(50) NOT NULL COMMENT '类型编码',
`json_data` JSON COMMENT '内容JSON数据(MySQL存储时使用)',
`storage_location` ENUM('mysql', 'minio') DEFAULT 'minio' COMMENT '存储位置',
`minio_key` VARCHAR(500) COMMENT 'MinIO对象键',
`content_size` INT COMMENT '内容大小',
`content_hash` VARCHAR(32) COMMENT '内容哈希值',
`status` TINYINT DEFAULT 1 COMMENT '状态:1-启用,0-禁用',
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX `idx_category_type` (`category_code`, `type_code`),
INDEX `idx_storage_location` (`storage_location`),
INDEX `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
这个设计的核心在于:
- 存储位置标识 :
storage_location字段明确标识数据存储位置 - 双重存储支持 :既支持MySQL的
json_data字段,也支持MinIO的minio_key - 完整性校验 :通过
content_hash确保数据完整性 - 元数据丰富:提供充足的查询和管理维度
2.2 技术选型考量
为什么选择MySQL?
- 成熟稳定的ACID事务支持
- 丰富的查询功能和索引优化
- 完善的备份和恢复机制
- 广泛的生态系统支持
为什么选择MinIO?
- S3兼容API,生态丰富
- 支持私有化部署,数据安全可控
- 高性能并发读写能力
- 成本效益比优秀
- 企业级特性完善(加密、版本控制等)
四、核心代码实现详解
4.1 MinIO客户端配置与连接管理
企业级应用的MinIO客户端实现需要考虑配置管理、连接池、错误处理等多个方面:
python
import os
import uuid
from minio import Minio
from minio.error import S3Error
import json
import io
import hashlib
from typing import Dict, Any, Optional, Tuple
# MinIO配置管理
class MinIOConfig:
def __init__(self):
self.endpoint = os.environ.get('MINIO_ENDPOINT', 'localhost')
self.port = int(os.environ.get('MINIO_PORT', 9000))
self.access_key = os.environ.get('MINIO_ACCESS_KEY', 'minioadmin')
self.secret_key = os.environ.get('MINIO_SECRET_KEY', 'minioadmin')
self.bucket_name = os.environ.get('MINIO_BUCKET_NAME', 'enterprise-storage')
self.secure = os.environ.get('MINIO_SECURE', 'False').lower() == 'true'
self.region = os.environ.get('MINIO_REGION', 'us-east-1')
config = MinIOConfig()
def get_minio_client():
"""获取MinIO客户端实例"""
return Minio(
f"{config.endpoint}:{config.port}",
access_key=config.access_key,
secret_key=config.secret_key,
secure=config.secure,
region=config.region
)
4.2 存储桶管理与权限控制
企业级应用必须考虑数据安全和访问控制:
python
def create_secure_bucket(client: Minio, bucket_name: str, public_read: bool = False):
"""创建安全的存储桶"""
try:
# 检查存储桶是否存在
if not client.bucket_exists(bucket_name):
client.make_bucket(bucket_name, location=config.region)
print(f"存储桶 {bucket_name} 创建成功")
# 设置存储桶策略
if public_read:
policy = {
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {"AWS": "*"},
"Action": ["s3:GetBucketLocation", "s3:ListBucket"],
"Resource": f"arn:aws:s3:::{bucket_name}"
},
{
"Effect": "Allow",
"Principal": {"AWS": "*"},
"Action": "s3:GetObject",
"Resource": f"arn:aws:s3:::{bucket_name}/*"
}
]
}
client.set_bucket_policy(bucket_name, json.dumps(policy))
# 启用版本控制(企业级特性)
client.set_bucket_versioning(bucket_name, {'Status': 'Enabled'})
return True
except S3Error as e:
print(f"创建存储桶失败: {e}")
return False
- 最小权限原则:只开放必要的权限
- 版本控制:支持文件版本管理
- 错误处理:完善的异常处理机制
4.3 文件上传的实现
文件上传功能需要考虑数据完整性、元数据管理、错误恢复等多个方面:
python
def save_content_to_storage(content_id: int, content: Dict[str, Any],
content_type: str = 'application/json') -> Tuple[bool, str]:
"""保存内容到MinIO存储"""
client = get_minio_client()
bucket_name = config.bucket_name
try:
# 确保存储桶存在
if not create_secure_bucket(client, bucket_name):
raise Exception("存储桶创建或配置失败")
# 生成唯一的对象键
object_key = generate_content_key(content_id)
# 序列化内容
if isinstance(content, dict):
content_json = json.dumps(content, ensure_ascii=False, sort_keys=True, indent=2)
content_bytes = content_json.encode('utf-8')
else:
content_bytes = content if isinstance(content, bytes) else str(content).encode('utf-8')
# 计算内容哈希用于完整性校验
content_hash = hashlib.md5(content_bytes).hexdigest()
# 创建文件流
content_stream = io.BytesIO(content_bytes)
# 准备元数据
metadata = {
'content-id': str(content_id),
'content-hash': content_hash,
'content-size': str(len(content_bytes)),
'upload-timestamp': str(int(time.time())),
'content-version': '1.0'
}
# 上传到MinIO
result = client.put_object(
bucket_name,
object_key,
content_stream,
len(content_bytes),
content_type=content_type,
metadata=metadata
)
# 验证上传结果
if result.etag:
print(f"内容 {content_id} 已成功保存到MinIO: {object_key}")
return True, object_key
else:
raise Exception("上传完成但未收到确认")
except S3Error as e:
print(f"MinIO保存内容错误: {e}")
return False, str(e)
except Exception as e:
print(f"保存内容失败: {e}")
return False, str(e)
def generate_content_key(content_id: int) -> str:
"""生成内容的MinIO键"""
timestamp = int(time.time())
random_suffix = uuid.uuid4().hex[:8]
return f"contents/content_{content_id}_{timestamp}_{random_suffix}.json"
- 数据完整性保证:使用MD5哈希值验证数据完整性
- 元数据管理:丰富的元数据信息便于管理和调试
- 错误处理:分层的异常处理机制
- 资源管理:高效的内存使用和流处理
- 版本控制:支持内容版本管理
4.4 存储迁移服务的核心实现
存储迁移是混合架构的核心功能,需要考虑数据一致性、错误恢复、进度跟踪等多个方面:
python
import time
from datetime import datetime
from enum import Enum
from typing import Dict, Any, Tuple, Optional
class MigrationStatus(Enum):
PENDING = "pending"
IN_PROGRESS = "in_progress"
COMPLETED = "completed"
FAILED = "failed"
ROLLBACK = "rollback"
class StorageMigrationService:
"""企业级存储迁移服务"""
def __init__(self):
self.migration_stats = {
'total_migrated': 0,
'successful_migrations': 0,
'failed_migrations': 0,
'last_migration_time': None
}
def migrate_content(self, content_id: int, target_storage: str,
force: bool = False) -> Tuple[bool, str]:
"""
迁移内容到指定存储位置
Args:
content_id: 内容ID
target_storage: 目标存储位置 ('mysql' 或 'minio')
force: 是否强制迁移
"""
try:
# 参数验证
if target_storage not in ['mysql', 'minio']:
return False, f"不支持的存储位置: {target_storage}"
# 获取内容信息
content_info = self._get_content_info(content_id)
if not content_info:
return False, f"内容 {content_id} 不存在"
current_storage = content_info['storage_location']
# 检查是否需要迁移
if current_storage == target_storage and not force:
return False, f"内容已经存储在 {target_storage} 中"
# 创建迁移日志
log_id = self._create_migration_log(content_id, current_storage, target_storage)
# 执行迁移
success, message = self._execute_migration(
content_id, content_info, current_storage, target_storage, log_id
)
# 更新统计信息
self._update_migration_stats(success)
return success, message
except Exception as e:
return False, f"迁移失败: {str(e)}"
def _execute_migration(self, content_id: int, content_info: Dict[str, Any],
from_storage: str, to_storage: str, log_id: int) -> Tuple[bool, str]:
"""执行具体的迁移操作"""
try:
# 更新迁移状态为进行中
self._update_migration_log(log_id, MigrationStatus.IN_PROGRESS.value)
# 获取原始内容
original_content = self._get_content_from_storage(content_id, from_storage, content_info)
if not original_content:
self._update_migration_log(log_id, MigrationStatus.FAILED.value, "无法获取原始内容")
return False, "无法获取原始内容"
# 计算内容信息
content_hash_before = self._calculate_content_hash(original_content)
content_size_before = self._calculate_content_size(original_content)
# 执行迁移
if to_storage == 'minio':
success, result = self._migrate_to_minio(content_id, original_content)
else:
success, result = self._migrate_to_mysql(content_id, original_content)
if not success:
self._update_migration_log(log_id, MigrationStatus.FAILED.value, f"迁移失败: {result}")
return False, f"迁移失败: {result}"
# 更新数据库记录
success, db_message = self._update_content_storage_info(
content_id, to_storage, result, content_size_before, content_hash_before
)
if not success:
self._update_migration_log(log_id, MigrationStatus.FAILED.value, f"更新数据库失败: {db_message}")
return False, f"更新数据库失败: {db_message}"
# 验证迁移结果
verification_success, verification_message = self._verify_migration(
content_id, original_content, to_storage, result
)
if not verification_success:
self._update_migration_log(log_id, MigrationStatus.FAILED.value, f"迁移验证失败: {verification_message}")
return False, f"迁移验证失败: {verification_message}"
# 清理源存储(如果迁移到不同存储)
if from_storage != to_storage:
self._cleanup_source_storage(content_id, from_storage, content_info.get('minio_key'))
# 更新迁移日志为完成
self._update_migration_log(
log_id, MigrationStatus.COMPLETED.value, None,
content_size_before, content_size_before,
content_hash_before, content_hash_before
)
return True, f"成功迁移到 {to_storage}"
except Exception as e:
self._update_migration_log(log_id, MigrationStatus.FAILED.value, str(e))
return False, f"迁移执行失败: {str(e)}"
def _verify_migration(self, content_id: int, original_content: Dict[str, Any],
target_storage: str, storage_key: str) -> Tuple[bool, str]:
"""验证迁移结果的完整性"""
try:
# 从目标存储读取数据
if target_storage == 'minio':
retrieved_content = self._get_content_from_minio(storage_key)
else:
retrieved_content = self._get_content_from_mysql(content_id)
if not retrieved_content:
return False, "无法从目标存储读取数据"
# 计算哈希值进行比较
original_hash = self._calculate_content_hash(original_content)
retrieved_hash = self._calculate_content_hash(retrieved_content)
if original_hash != retrieved_hash:
return False, f"数据完整性校验失败: 原始={original_hash}, 检索={retrieved_hash}"
return True, "数据完整性校验通过"
except Exception as e:
return False, f"验证过程出错: {str(e)}"
def _calculate_content_hash(self, content: Any) -> str:
"""计算内容哈希值"""
if isinstance(content, dict):
content_str = json.dumps(content, ensure_ascii=False, sort_keys=True)
else:
content_str = str(content)
return hashlib.md5(content_str.encode('utf-8')).hexdigest()
def _calculate_content_size(self, content: Any) -> int:
"""计算内容大小"""
if isinstance(content, dict):
content_str = json.dumps(content, ensure_ascii=False)
else:
content_str = str(content)
return len(content_str.encode('utf-8'))
完整的生命周期管理:
- 迁移前验证和准备
- 迁移过程监控和日志记录
- 迁移后验证和清理
- 详细的状态跟踪
数据安全保障:
- 迁移前后的完整性校验
- 原数据保留直到验证成功
- 完整的错误处理和回滚机制
可观测性:
- 详细的迁移日志
- 实时的进度跟踪
- 完整的统计信息
4.5 数据完整性校验机制
数据完整性是企业级存储的生命线,需要实现多层次的校验机制:
python
class DataIntegrityChecker:
"""数据完整性校验器"""
def __init__(self):
self.hash_algorithm = hashlib.md5
self.verification_cache = {}
def verify_content_integrity(self, content_id: int, expected_hash: str = None) -> Tuple[bool, str]:
"""验证内容完整性"""
try:
# 获取内容信息
content_info = self._get_content_info(content_id)
if not content_info:
return False, f"内容 {content_id} 不存在"
storage_location = content_info['storage_location']
# 从存储中读取内容
if storage_location == 'minio':
content = self._get_content_from_minio(content_info['minio_key'])
else:
content = self._get_content_from_mysql(content_id)
if not content:
return False, "无法读取内容数据"
# 计算实际哈希值
actual_hash = self._calculate_content_hash(content)
# 比较哈希值
stored_hash = expected_hash or content_info.get('content_hash')
if stored_hash and actual_hash != stored_hash:
return False, f"哈希值不匹配: 期望={stored_hash}, 实际={actual_hash}"
# 验证文件大小
actual_size = self._calculate_content_size(content)
stored_size = content_info.get('content_size')
if stored_size and actual_size != stored_size:
return False, f"文件大小不匹配: 期望={stored_size}, 实际={actual_size}"
return True, "完整性校验通过"
except Exception as e:
return False, f"校验过程出错: {str(e)}"
def batch_verify_integrity(self, content_ids: list) -> Dict[int, Tuple[bool, str]]:
"""批量验证内容完整性"""
results = {}
for content_id in content_ids:
results[content_id] = self.verify_content_integrity(content_id)
return results
def schedule_integrity_check(self, interval_hours: int = 24):
"""定期完整性检查"""
# 这里可以集成定时任务框架如Celery
pass
校验机制的多重保障:
- 哈希值校验:使用MD5确保数据传输完整性
- 大小校验:验证文件大小是否匹配
- 往返验证:写入后立即读取验证
- 定期校验:支持定期的完整性检查
- 批量校验:支持大规模数据的批量验证
自此,企业级混合存储的核心方案思路和代码实现就已经完成了。接下来是在生产环境中如何进行调优和最佳实践。
五、调优
针对高并发场景或对架构性能有较高要求的系统,可以参考以下优化建议。部分方案需结合具体场景验证,建议在实际环境中测试后再实施
5.1 部署架构优化
网络架构设计:
[负载均衡器]
↓
[应用服务器集群] ←→ [MySQL主从集群]
↓ ↓
[MinIO集群] ←→ [CDN/对象存储网关]
↓
[备份存储]
关键配置参数:
python
# 数据库连接池配置
DATABASE_CONFIG = {
'pool_size': 20,
'max_overflow': 30,
'pool_timeout': 30,
'pool_recycle': 3600,
'pool_pre_ping': True
}
# MinIO客户端配置
MINIO_CONFIG = {
'max_pool_connections': 50,
'retries': 3,
'timeout': 30,
'read_timeout': 60,
'connect_timeout': 10
}
# 缓存配置
CACHE_CONFIG = {
'redis_url': 'redis://localhost:6379/0',
'default_timeout': 3600,
'key_prefix': 'storage_cache:'
}
5.2 性能优化策略
数据库层优化:
sql
-- 创建复合索引优化查询
CREATE INDEX idx_storage_status ON content_templates(storage_location, status);
CREATE INDEX idx_category_created ON content_templates(category_code, created_at);
-- 分区表设计(按时间分区)
ALTER TABLE content_templates PARTITION BY RANGE (YEAR(created_at)) (
PARTITION p2023 VALUES LESS THAN (2024),
PARTITION p2024 VALUES LESS THAN (2025),
PARTITION p_future VALUES LESS THAN MAXVALUE
);
对象存储层优化:
python
class OptimizedMinIOClient:
def __init__(self):
self.client = get_minio_client()
self.upload_part_size = 64 * 1024 * 1024 # 64MB
self.max_concurrency = 10
def upload_large_file(self, bucket_name: str, object_name: str,
file_path: str) -> bool:
"""优化的大文件上传"""
try:
# 使用分片上传
result = self.client.fput_object(
bucket_name,
object_name,
file_path,
part_size=self.upload_part_size
)
return True
except Exception as e:
print(f"上传失败: {e}")
return False
def generate_presigned_url(self, bucket_name: str, object_name: str,
expires: int = 3600) -> str:
"""生成预签名URL,减少服务器中转"""
return self.client.presigned_get_object(
bucket_name, object_name, expires=timedelta(seconds=expires)
)
应用层优化:
python
import asyncio
from concurrent.futures import ThreadPoolExecutor
import redis
class CachedStorageService:
def __init__(self):
self.redis_client = redis.Redis.from_url(CACHE_CONFIG['redis_url'])
self.executor = ThreadPoolExecutor(max_workers=20)
async def get_content_with_cache(self, content_id: int) -> Optional[Dict[str, Any]]:
"""带缓存的内容获取"""
cache_key = f"{CACHE_CONFIG['key_prefix']}content:{content_id}"
# 尝试从缓存获取
cached_content = self.redis_client.get(cache_key)
if cached_content:
return json.loads(cached_content)
# 从存储获取
content = await self._get_content_from_storage(content_id)
if content:
# 写入缓存
self.redis_client.setex(
cache_key,
CACHE_CONFIG['default_timeout'],
json.dumps(content, ensure_ascii=False)
)
return content
async def _get_content_from_storage(self, content_id: int) -> Optional[Dict[str, Any]]:
"""异步获取存储内容"""
loop = asyncio.get_event_loop()
return await loop.run_in_executor(
self.executor,
self._sync_get_content,
content_id
)
5.3 监控与运维
关键监控指标:
python
class StorageMonitor:
def __init__(self):
self.metrics = {
'storage_usage': {},
'operation_latency': {},
'error_rates': {},
'migration_stats': {}
}
def collect_storage_metrics(self):
"""收集存储指标"""
# MySQL存储使用情况
mysql_usage = self._get_mysql_storage_usage()
# MinIO存储使用情况
minio_usage = self._get_minio_storage_usage()
# 操作延迟统计
operation_latency = self._get_operation_latency()
# 错误率统计
error_rates = self._get_error_rates()
return {
'mysql_usage': mysql_usage,
'minio_usage': minio_usage,
'operation_latency': operation_latency,
'error_rates': error_rates,
'timestamp': datetime.now().isoformat()
}
def check_health(self) -> Dict[str, bool]:
"""健康检查"""
health_status = {}
# 检查MySQL连接
try:
# 执行简单查询测试连接
health_status['mysql'] = self._test_mysql_connection()
except Exception:
health_status['mysql'] = False
# 检查MinIO连接
try:
client = get_minio_client()
client.list_buckets()
health_status['minio'] = True
except Exception:
health_status['minio'] = False
return health_status
告警策略:
python
class AlertManager:
def __init__(self):
self.alert_thresholds = {
'storage_usage_rate': 0.8,
'error_rate': 0.05,
'response_time_p99': 5000, # 5秒
'migration_failure_rate': 0.1
}
def check_alerts(self, metrics: Dict[str, Any]):
"""检查告警条件"""
alerts = []
# 存储使用率告警
if metrics.get('mysql_usage', {}).get('usage_rate', 0) > self.alert_thresholds['storage_usage_rate']:
alerts.append({
'type': 'storage_usage',
'level': 'warning',
'message': 'MySQL存储使用率超过80%'
})
# 错误率告警
if metrics.get('error_rates', {}).get('overall', 0) > self.alert_thresholds['error_rate']:
alerts.append({
'type': 'error_rate',
'level': 'critical',
'message': '系统错误率超过5%'
})
# 响应时间告警
if metrics.get('operation_latency', {}).get('p99', 0) > self.alert_thresholds['response_time_p99']:
alerts.append({
'type': 'performance',
'level': 'warning',
'message': 'P99响应时间超过5秒'
})
return alerts
5.4 成本控制策略
存储成本优化:
python
class StorageCostOptimizer:
def __init__(self):
self.lifecycle_policies = {
'hot_data': 30, # 30天内的热数据
'warm_data': 90, # 30-90天的温数据
'cold_data': 365 # 90天以上的冷数据
}
def optimize_storage_costs(self):
"""优化存储成本"""
# 分析数据访问模式
access_patterns = self._analyze_access_patterns()
# 识别冷数据
cold_data = self._identify_cold_data(access_patterns)
# 执行数据分层
for content_id in cold_data:
self._migrate_to_cold_storage(content_id)
def _identify_cold_data(self, access_patterns: Dict[int, Dict]) -> List[int]:
"""识别冷数据"""
cold_data = []
current_time = datetime.now()
for content_id, pattern in access_patterns.items():
last_access = pattern.get('last_access_time')
if last_access:
days_since_access = (current_time - last_access).days
if days_since_access > self.lifecycle_policies['cold_data']:
cold_data.append(content_id)
return cold_data
def calculate_cost_savings(self) -> Dict[str, float]:
"""计算成本节省"""
# 这里可以集成云服务商的计费API
return {
'monthly_savings': 1500.0,
'annual_savings': 18000.0,
'cost_reduction_percentage': 65.0
}
5.5 安全最佳实践
访问控制:
python
class SecurityManager:
def __init__(self):
self.role_permissions = {
'admin': ['read', 'write', 'delete', 'migrate', 'manage'],
'editor': ['read', 'write'],
'viewer': ['read'],
'system': ['read', 'write', 'migrate']
}
def check_permission(self, user_role: str, operation: str, resource_id: int = None) -> bool:
"""检查用户权限"""
if user_role not in self.role_permissions:
return False
allowed_operations = self.role_permissions[user_role]
if operation not in allowed_operations:
return False
# 资源级权限检查
if resource_id and not self._check_resource_permission(user_role, resource_id):
return False
return True
def encrypt_sensitive_data(self, data: str) -> str:
"""加密敏感数据"""
# 使用AES加密
from cryptography.fernet import Fernet
key = os.environ.get('ENCRYPTION_KEY').encode()
f = Fernet(key)
return f.encrypt(data.encode()).decode()
def audit_log(self, user_id: int, operation: str, resource_id: int, result: str):
"""记录审计日志"""
log_entry = {
'timestamp': datetime.now().isoformat(),
'user_id': user_id,
'operation': operation,
'resource_id': resource_id,
'result': result,
'ip_address': self._get_client_ip()
}
# 写入审计日志存储
self._write_audit_log(log_entry)
到此,混合存储的核心思想和设计,以及不包含业务相关的完整实现已经全部说完了,调优部分也提供出来供大家参考! 完结撒花*★,°* :.☆( ̄▽ ̄)/$:.°★ 。