From fbca92ba77d25f15c5cf1306caf13a9c6ba49845 Mon Sep 17 00:00:00 2001 From: YoVinchen Date: Mon, 11 Aug 2025 14:09:57 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E6=96=87=E6=A1=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 40 - docs/README.md | 51 - docs/api-design.md | 759 -------------- docs/architecture.md | 387 -------- docs/database-design.md | 603 ------------ docs/deployment.md | 1427 --------------------------- docs/frontend-architecture.md | 1742 --------------------------------- docs/user-manual.md | 708 -------------- 8 files changed, 5717 deletions(-) delete mode 100644 docs/README.md delete mode 100644 docs/api-design.md delete mode 100644 docs/architecture.md delete mode 100644 docs/database-design.md delete mode 100644 docs/deployment.md delete mode 100644 docs/frontend-architecture.md delete mode 100644 docs/user-manual.md diff --git a/README.md b/README.md index 01c45b7..23003ad 100644 --- a/README.md +++ b/README.md @@ -365,7 +365,6 @@ BigDataTool采用模块化分层架构设计: - 确认分表参数配置正确 - 验证目标分表是否存在 -详细故障排查指南请参考 [运维手册](docs/operations.md) ## 📝 API文档 @@ -379,41 +378,6 @@ BigDataTool采用模块化分层架构设计: - `GET /api/query-history` - 获取查询历史 - `GET /api/query-logs` - 获取查询日志 -详细API文档请参考 [API.md](docs/API.md) - -## 📚 文档目录 - -### 🏠 核心文档 -- [开发指南](CLAUDE.md) - Claude Code开发指导文档 -- [许可证](LICENSE) - MIT开源许可证 - -### 📖 用户文档 -- [使用指南](docs/USER_GUIDE.md) - 快速上手和功能使用 -- [用户手册](docs/user-manual.md) - 详细的功能使用说明 -- [API文档](docs/API.md) - REST API接口简介 - -### 🏗️ 技术文档 -- [系统架构](docs/ARCHITECTURE.md) - 架构设计概览 -- [详细架构](docs/architecture.md) - 完整的系统架构设计 -- [API设计](docs/api-design.md) - 详细的REST API规范 -- [数据库设计](docs/database-design.md) - 数据模型和表结构 -- [前端架构](docs/frontend-architecture.md) - 前端模块化设计 - -### 🚀 运维文档 -- [部署指南](docs/DEPLOYMENT.md) - 快速部署说明 -- [详细部署](docs/deployment.md) - 生产环境部署配置 -- [运维手册](docs/operations.md) - 日常运维和故障排查 - -### 👨‍💻 开发文档 -- [开发者指南](docs/developer-guide.md) - 开发环境和二次开发 -- [代码规范](docs/coding-standards.md) - 代码风格和最佳实践 -- [安全规范](docs/security-guidelines.md) - 安全设计和数据保护 - -### 📋 项目管理 -- [需求分析](docs/requirements.md) - 业务需求和功能规格 -- [测试计划](docs/testing-plan.md) - 测试策略和用例设计 -- [文档索引](docs/README.md) - 完整的文档结构说明 - ## 🤝 贡献指南 我们欢迎所有形式的贡献!请遵循以下步骤: @@ -526,10 +490,6 @@ BigDataTool致力于数据安全: ## 📊 项目状态 -![项目状态](https://img.shields.io/badge/status-active-brightgreen.svg) -![维护状态](https://img.shields.io/badge/maintenance-active-brightgreen.svg) -![最后提交](https://img.shields.io/github/last-commit/your-org/BigDataTool.svg) - **最后更新**: 2024年8月6日 **当前版本**: v2.0 **开发状态**: 持续维护中 diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index f19bd29..0000000 --- a/docs/README.md +++ /dev/null @@ -1,51 +0,0 @@ -# DataTools Pro 设计文档 - -本目录包含DataTools Pro项目的完整设计文档,为开发者、运维人员和用户提供详细的技术参考。 - -## 文档结构 - -### 📋 核心设计文档 -- **[系统架构设计](architecture.md)** - 整体系统架构、技术选型和设计原则 -- **[API接口设计](api-design.md)** - REST API接口规范和数据结构定义 -- **[数据库设计](database-design.md)** - 数据模型、表结构和关系设计 -- **[前端模块化设计](frontend-architecture.md)** - 前端架构、模块化和组件设计 - -### 🚀 部署和运维 -- **[部署指南](deployment.md)** - 生产环境部署、配置和监控 -- **[运维手册](operations.md)** - 日常运维、故障排查和性能优化 - -### 📖 用户文档 -- **[用户使用手册](user-manual.md)** - 功能使用指南和最佳实践 -- **[开发者指南](developer-guide.md)** - 开发环境搭建和二次开发指南 - -### 🔧 技术规范 -- **[代码规范](coding-standards.md)** - 代码风格、命名规范和最佳实践 -- **[安全规范](security-guidelines.md)** - 安全设计、数据保护和风险管控 - -### 📊 业务文档 -- **[需求分析](requirements.md)** - 业务需求、功能规格和用例分析 -- **[测试计划](testing-plan.md)** - 测试策略、用例设计和质量保证 - -## 文档版本 - -| 文档版本 | 系统版本 | 更新日期 | 主要变更 | -|---------|---------|----------|----------| -| v2.0.0 | DataTools Pro 2.0 | 2024-08-05 | 完整的系统设计文档创建 | - -## 文档贡献 - -如需更新文档,请遵循以下原则: -1. 保持文档结构清晰,使用标准Markdown格式 -2. 及时更新版本信息和变更日志 -3. 确保代码示例和配置信息的准确性 -4. 添加必要的图片和流程图说明 - -## 联系方式 - -- **项目维护者**: DataTools Pro Team -- **技术支持**: 请提交Issue到项目仓库 -- **文档反馈**: 欢迎提出改进建议 - ---- - -**DataTools Pro** - 企业级数据处理与比对解决方案 \ No newline at end of file diff --git a/docs/api-design.md b/docs/api-design.md deleted file mode 100644 index cc8403f..0000000 --- a/docs/api-design.md +++ /dev/null @@ -1,759 +0,0 @@ -# DataTools Pro API接口设计文档 - -## 1. API概述 - -### 1.1 设计原则 -- **RESTful设计**: 遵循REST架构风格 -- **统一格式**: 标准化的请求和响应格式 -- **版本控制**: 支持API版本管理 -- **错误处理**: 完整的错误码和错误信息 -- **安全性**: 输入验证和权限控制 - -### 1.2 基础信息 -- **Base URL**: `http://localhost:5000` -- **Content-Type**: `application/json` -- **字符编码**: `UTF-8` -- **API版本**: `v1.0` - -### 1.3 响应格式规范 -```json -{ - "success": true, - "data": {}, - "message": "操作成功", - "timestamp": "2024-08-05T10:30:00Z", - "request_id": "uuid-string" -} -``` - -## 2. 核心API端点 - -### 2.1 Cassandra数据比对API - -#### 2.1.1 执行单表查询比对 -**端点**: `POST /api/query` - -**功能**: 执行Cassandra单表数据查询和比对分析 - -**请求参数**: -```json -{ - "pro_config": { - "cluster_name": "production-cluster", - "datacenter": "datacenter1", - "hosts": ["10.0.1.100", "10.0.1.101"], - "port": 9042, - "username": "cassandra", - "password": "password", - "keyspace": "production_ks", - "table": "user_data" - }, - "test_config": { - "cluster_name": "test-cluster", - "datacenter": "datacenter1", - "hosts": ["10.0.2.100"], - "port": 9042, - "username": "cassandra", - "password": "password", - "keyspace": "test_ks", - "table": "user_data" - }, - "keys": ["user_id"], - "values": ["1001", "1002", "1003"], - "fields_to_compare": ["name", "email", "status"], - "exclude_fields": ["created_at", "updated_at"] -} -``` - -**响应数据**: -```json -{ - "success": true, - "data": { - "total_keys": 3, - "pro_count": 3, - "test_count": 2, - "differences": [ - { - "key": {"user_id": "1001"}, - "field": "email", - "pro_value": "user1@prod.com", - "test_value": "user1@test.com", - "message": "字段值不匹配" - } - ], - "identical_results": [ - { - "key": {"user_id": "1002"}, - "pro_fields": {"name": "User2", "email": "user2@example.com"}, - "test_fields": {"name": "User2", "email": "user2@example.com"} - } - ], - "field_diff_count": { - "email": 1 - }, - "raw_pro_data": [...], - "raw_test_data": [...], - "summary": { - "overview": "查询了3个Key,发现1处差异", - "percentages": { - "match_rate": 66.67, - "diff_rate": 33.33 - }, - "field_analysis": { - "email": {"diff_count": 1, "diff_rate": 33.33} - }, - "recommendations": ["建议检查邮箱字段的数据同步"] - } - }, - "message": "查询比对完成", - "execution_time": 1.25, - "timestamp": "2024-08-05T10:30:00Z" -} -``` - -#### 2.1.2 执行分表查询比对 -**端点**: `POST /api/sharding-query` - -**功能**: 执行Cassandra分表数据查询和比对分析 - -**请求参数**: -```json -{ - "pro_config": { /* 同单表查询配置 */ }, - "test_config": { /* 同单表查询配置 */ }, - "keys": ["doc_id"], - "values": ["wmid_1609459200", "wmid_1609545600"], - "fields_to_compare": ["content", "status"], - "exclude_fields": [], - "sharding_config": { - "use_sharding_for_pro": true, - "use_sharding_for_test": false, - "interval_seconds": 604800, - "table_count": 14 - } -} -``` - -**响应数据**: -```json -{ - "success": true, - "data": { - /* 基础比对结果同单表查询 */ - "sharding_info": { - "pro_shard_mapping": { - "wmid_1609459200": "user_data_0", - "wmid_1609545600": "user_data_1" - }, - "test_shard_mapping": { - "wmid_1609459200": "user_data", - "wmid_1609545600": "user_data" - }, - "failed_keys": [], - "shard_stats": { - "pro_tables_used": ["user_data_0", "user_data_1"], - "test_tables_used": ["user_data"], - "timestamp_extraction_success_rate": 100.0 - } - } - }, - "message": "分表查询比对完成", - "execution_time": 2.15 -} -``` - -### 2.2 Redis集群比对API - -#### 2.2.1 执行Redis集群比对 -**端点**: `POST /api/redis/compare` - -**功能**: 执行Redis集群数据比对分析 - -**请求参数**: -```json -{ - "cluster1_config": { - "name": "生产集群", - "nodes": [ - {"host": "10.0.1.100", "port": 6379}, - {"host": "10.0.1.101", "port": 6380} - ], - "password": "redis_password", - "socket_timeout": 3, - "socket_connect_timeout": 3, - "max_connections_per_node": 16 - }, - "cluster2_config": { - "name": "测试集群", - "nodes": [{"host": "10.0.2.100", "port": 6379}], - "password": null - }, - "query_mode": "specified", - "keys": ["user:1001", "user:1002", "session:abc123"], - "sample_config": { - "count": 100, - "pattern": "*", - "source_cluster": "cluster2" - } -} -``` - -**响应数据**: -```json -{ - "success": true, - "data": { - "total_keys": 3, - "cluster1_found": 2, - "cluster2_found": 3, - "differences": [ - { - "key": "user:1001", - "cluster1_value": "{\"name\":\"John\",\"age\":25}", - "cluster2_value": "{\"name\":\"John\",\"age\":26}", - "value_type": "string", - "difference_type": "value_mismatch" - } - ], - "identical": [ - { - "key": "user:1002", - "value": "{\"name\":\"Jane\",\"age\":30}", - "value_type": "string" - } - ], - "missing_in_cluster1": ["session:abc123"], - "missing_in_cluster2": [], - "cluster_stats": { - "cluster1": { - "connection_status": "connected", - "response_time_avg": 0.15, - "nodes_status": [ - {"host": "10.0.1.100", "port": 6379, "status": "connected"}, - {"host": "10.0.1.101", "port": 6380, "status": "connected"} - ] - }, - "cluster2": { - "connection_status": "connected", - "response_time_avg": 0.12, - "nodes_status": [ - {"host": "10.0.2.100", "port": 6379, "status": "connected"} - ] - } - }, - "performance_summary": { - "total_execution_time": 0.85, - "keys_per_second": 3.53, - "data_transferred_kb": 2.1 - } - }, - "message": "Redis集群比对完成" -} -``` - -### 2.3 配置管理API - -#### 2.3.1 获取默认配置 -**端点**: `GET /api/default-config` - -**功能**: 获取系统默认数据库配置 - -**响应数据**: -```json -{ - "success": true, - "data": { - "pro_config": { - "cluster_name": "production-cluster", - "datacenter": "datacenter1", - "hosts": ["127.0.0.1"], - "port": 9042, - "username": "", - "password": "", - "keyspace": "production_ks", - "table": "table_name" - }, - "test_config": { - "cluster_name": "test-cluster", - "datacenter": "datacenter1", - "hosts": ["127.0.0.1"], - "port": 9042, - "username": "", - "password": "", - "keyspace": "test_ks", - "table": "table_name" - } - } -} -``` - -#### 2.3.2 创建配置组 -**端点**: `POST /api/config-groups` - -**请求参数**: -```json -{ - "name": "生产环境配置", - "description": "生产环境Cassandra配置组", - "pro_config": { /* Cassandra配置 */ }, - "test_config": { /* Cassandra配置 */ }, - "query_config": { - "keys": ["user_id"], - "fields_to_compare": [], - "exclude_fields": [] - }, - "sharding_config": { - "use_sharding_for_pro": false, - "use_sharding_for_test": false, - "interval_seconds": 604800, - "table_count": 14 - } -} -``` - -**响应数据**: -```json -{ - "success": true, - "data": { - "id": 1, - "name": "生产环境配置", - "created_at": "2024-08-05T10:30:00Z" - }, - "message": "配置组创建成功" -} -``` - -#### 2.3.3 获取配置组列表 -**端点**: `GET /api/config-groups` - -**响应数据**: -```json -{ - "success": true, - "data": [ - { - "id": 1, - "name": "生产环境配置", - "description": "生产环境Cassandra配置组", - "created_at": "2024-08-05T10:30:00Z", - "updated_at": "2024-08-05T10:30:00Z" - } - ] -} -``` - -#### 2.3.4 获取特定配置组 -**端点**: `GET /api/config-groups/{id}` - -**响应数据**: -```json -{ - "success": true, - "data": { - "id": 1, - "name": "生产环境配置", - "description": "生产环境Cassandra配置组", - "pro_config": { /* 完整配置 */ }, - "test_config": { /* 完整配置 */ }, - "query_config": { /* 查询配置 */ }, - "sharding_config": { /* 分表配置 */ }, - "created_at": "2024-08-05T10:30:00Z", - "updated_at": "2024-08-05T10:30:00Z" - } -} -``` - -#### 2.3.5 删除配置组 -**端点**: `DELETE /api/config-groups/{id}` - -**响应数据**: -```json -{ - "success": true, - "data": null, - "message": "配置组删除成功" -} -``` - -### 2.4 查询历史管理API - -#### 2.4.1 获取查询历史列表 -**端点**: `GET /api/query-history` - -**查询参数**: -- `limit`: 返回记录数量限制 (默认50) -- `offset`: 偏移量 (默认0) -- `query_type`: 查询类型 (`single`/`sharding`) - -**响应数据**: -```json -{ - "success": true, - "data": { - "items": [ - { - "id": 1, - "name": "用户数据比对-20240805", - "description": "生产环境用户数据比对", - "query_type": "single", - "total_keys": 100, - "differences_count": 5, - "identical_count": 95, - "execution_time": 2.5, - "created_at": "2024-08-05T10:30:00Z" - } - ], - "total": 1, - "has_more": false - } -} -``` - -#### 2.4.2 保存查询历史 -**端点**: `POST /api/query-history` - -**请求参数**: -```json -{ - "name": "用户数据比对-20240805", - "description": "生产环境用户数据比对", - "pro_config": { /* 生产配置 */ }, - "test_config": { /* 测试配置 */ }, - "query_config": { /* 查询配置 */ }, - "query_keys": ["1001", "1002", "1003"], - "results_summary": { - "total_keys": 3, - "differences_count": 1, - "identical_count": 2 - }, - "execution_time": 1.25, - "query_type": "single", - "sharding_config": null, - "raw_results": { /* 完整查询结果 */ } -} -``` - -#### 2.4.3 获取历史记录详情 -**端点**: `GET /api/query-history/{id}` - -**响应数据**: -```json -{ - "success": true, - "data": { - "id": 1, - "name": "用户数据比对-20240805", - "description": "生产环境用户数据比对", - "pro_config": { /* 完整配置 */ }, - "test_config": { /* 完整配置 */ }, - "query_config": { /* 查询配置 */ }, - "query_keys": ["1001", "1002", "1003"], - "results_summary": { /* 结果摘要 */ }, - "execution_time": 1.25, - "query_type": "single", - "created_at": "2024-08-05T10:30:00Z" - } -} -``` - -#### 2.4.4 获取历史记录完整结果 -**端点**: `GET /api/query-history/{id}/results` - -**响应数据**: -```json -{ - "success": true, - "data": { - "differences": [ /* 完整差异数据 */ ], - "identical_results": [ /* 完整相同数据 */ ], - "raw_pro_data": [ /* 生产原始数据 */ ], - "raw_test_data": [ /* 测试原始数据 */ ], - "field_diff_count": { /* 字段差异统计 */ }, - "summary": { /* 详细分析报告 */ } - } -} -``` - -### 2.5 日志管理API - -#### 2.5.1 获取查询日志 -**端点**: `GET /api/query-logs` - -**查询参数**: -- `limit`: 返回记录数量 (默认100) -- `level`: 日志级别 (`INFO`/`WARNING`/`ERROR`) -- `history_id`: 关联的历史记录ID - -**响应数据**: -```json -{ - "success": true, - "data": { - "logs": [ - { - "id": 1, - "batch_id": "batch-uuid-123", - "history_id": 1, - "timestamp": "2024-08-05T10:30:01.123Z", - "level": "INFO", - "message": "开始执行Cassandra查询", - "query_type": "cassandra_single", - "created_at": "2024-08-05T10:30:01Z" - }, - { - "id": 2, - "batch_id": "batch-uuid-123", - "history_id": 1, - "timestamp": "2024-08-05T10:30:02.456Z", - "level": "INFO", - "message": "生产环境查询完成,返回3条记录", - "query_type": "cassandra_single", - "created_at": "2024-08-05T10:30:02Z" - } - ], - "total": 2 - } -} -``` - -#### 2.5.2 获取特定历史记录的日志 -**端点**: `GET /api/query-logs/history/{id}` - -**响应数据**: -```json -{ - "success": true, - "data": { - "history_id": 1, - "logs": [ /* 该历史记录相关的所有日志 */ ], - "log_summary": { - "total_logs": 10, - "info_count": 8, - "warning_count": 1, - "error_count": 1, - "start_time": "2024-08-05T10:30:00Z", - "end_time": "2024-08-05T10:30:05Z" - } - } -} -``` - -#### 2.5.3 清空查询日志 -**端点**: `DELETE /api/query-logs` - -**响应数据**: -```json -{ - "success": true, - "data": { - "deleted_count": 150 - }, - "message": "查询日志清空成功" -} -``` - -### 2.6 系统管理API - -#### 2.6.1 初始化数据库 -**端点**: `POST /api/init-db` - -**功能**: 初始化SQLite数据库表结构 - -**响应数据**: -```json -{ - "success": true, - "data": { - "tables_created": [ - "config_groups", - "query_history", - "query_logs" - ] - }, - "message": "数据库初始化成功" -} -``` - -#### 2.6.2 系统健康检查 -**端点**: `GET /api/health` - -**响应数据**: -```json -{ - "success": true, - "data": { - "status": "healthy", - "version": "2.0.0", - "uptime": "2 days, 3 hours, 45 minutes", - "database": { - "sqlite": { - "status": "connected", - "file_size_mb": 15.2 - } - }, - "memory_usage": { - "used_mb": 128.5, - "available_mb": 3967.5 - }, - "last_check": "2024-08-05T10:30:00Z" - } -} -``` - -## 3. 错误处理 - -### 3.1 错误响应格式 -```json -{ - "success": false, - "error": { - "code": "VALIDATION_ERROR", - "message": "请求参数验证失败", - "details": { - "field": "pro_config.hosts", - "issue": "hosts字段不能为空" - } - }, - "timestamp": "2024-08-05T10:30:00Z", - "request_id": "uuid-string" -} -``` - -### 3.2 错误码定义 - -| 错误码 | HTTP状态码 | 说明 | -|--------|-----------|------| -| `VALIDATION_ERROR` | 400 | 请求参数验证失败 | -| `CONNECTION_ERROR` | 500 | 数据库连接失败 | -| `QUERY_ERROR` | 500 | 查询执行失败 | -| `TIMEOUT_ERROR` | 408 | 请求超时 | -| `NOT_FOUND` | 404 | 资源不存在 | -| `CONFLICT` | 409 | 资源冲突 | -| `SYSTEM_ERROR` | 500 | 系统内部错误 | -| `AUTH_ERROR` | 401 | 认证失败 | -| `PERMISSION_DENIED` | 403 | 权限不足 | - -### 3.3 详细错误场景 - -#### 3.3.1 连接错误 -```json -{ - "success": false, - "error": { - "code": "CONNECTION_ERROR", - "message": "无法连接到Cassandra集群", - "details": { - "cluster": "production-cluster", - "hosts": ["10.0.1.100", "10.0.1.101"], - "error_detail": "Connection refused", - "suggestions": [ - "检查网络连通性", - "验证主机地址和端口", - "确认Cassandra服务状态" - ] - } - } -} -``` - -#### 3.3.2 查询错误 -```json -{ - "success": false, - "error": { - "code": "QUERY_ERROR", - "message": "CQL查询执行失败", - "details": { - "query": "SELECT * FROM user_data WHERE user_id IN (?)", - "error_detail": "Invalid keyspace name 'invalid_ks'", - "suggestions": [ - "检查keyspace名称是否正确", - "确认表名拼写无误", - "验证字段名是否存在" - ] - } - } -} -``` - -## 4. 认证和授权 - -### 4.1 认证机制 -当前版本暂未实现认证机制,所有API端点均为开放访问。在生产环境中建议实现以下认证方式: - -- **API Key认证**: 基于API密钥的简单认证 -- **JWT Token**: JSON Web Token认证 -- **OAuth 2.0**: 标准OAuth认证流程 -- **LDAP集成**: 企业级LDAP认证 - -### 4.2 权限控制 -建议实施基于角色的访问控制(RBAC): - -```json -{ - "roles": [ - { - "name": "admin", - "permissions": ["read", "write", "delete", "config"] - }, - { - "name": "operator", - "permissions": ["read", "write"] - }, - { - "name": "viewer", - "permissions": ["read"] - } - ] -} -``` - -## 5. API版本管理 - -### 5.1 版本策略 -- **URL版本控制**: `/api/v1/query`, `/api/v2/query` -- **Header版本控制**: `Accept: application/vnd.datatools.v1+json` -- **向后兼容**: 保持旧版本API的兼容性 -- **弃用策略**: 提前通知API弃用计划 - -### 5.2 版本变更记录 - -| API版本 | 发布日期 | 主要变更 | 兼容性 | -|---------|----------|----------|--------| -| v1.0 | 2024-08-05 | 初始版本发布 | N/A | - -## 6. 性能和限制 - -### 6.1 API限制 -- **请求频率**: 每分钟最多100次请求 -- **并发连接**: 最多10个并发连接 -- **响应大小**: 单次响应最大50MB -- **查询超时**: 默认120秒超时 - -### 6.2 性能优化 -- **连接池**: 复用数据库连接 -- **缓存策略**: 配置数据缓存 -- **异步处理**: 长时间查询异步执行 -- **分页处理**: 大数据集分页返回 - -## 7. 监控和日志 - -### 7.1 API监控指标 -- **响应时间**: 平均响应时间和95分位数 -- **成功率**: API调用成功率统计 -- **错误率**: 各类错误的发生率 -- **吞吐量**: 每秒处理的请求数 - -### 7.2 日志记录 -- **访问日志**: 记录所有API访问 -- **错误日志**: 详细的错误信息和堆栈 -- **性能日志**: 慢查询和性能瓶颈 -- **审计日志**: 重要操作的审计记录 - ---- - -**版本**: v1.0 -**更新日期**: 2024-08-05 -**维护者**: DataTools Pro Team \ No newline at end of file diff --git a/docs/architecture.md b/docs/architecture.md deleted file mode 100644 index 86b02b8..0000000 --- a/docs/architecture.md +++ /dev/null @@ -1,387 +0,0 @@ -# DataTools Pro 系统架构设计 - -## 1. 系统概述 - -### 1.1 项目简介 -DataTools Pro 是一个企业级数据处理与比对工具平台,专注于提供高效、精准、可视化的数据分析解决方案。系统支持Cassandra数据库和Redis集群的数据比对分析,具备分表查询、多主键查询、配置管理等企业级功能。 - -### 1.2 设计目标 -- **高性能**: 支持大规模数据查询和比对处理 -- **高可用**: 企业级稳定性和容错能力 -- **易扩展**: 模块化设计,便于功能扩展 -- **用户友好**: 直观的Web界面和操作体验 -- **安全性**: 数据安全和访问控制 - -### 1.3 技术栈 -``` -前端技术栈: -├── 原生JavaScript (ES6+) -├── Bootstrap 5.1.3 -├── Font Awesome 6.0.0 -└── 模块化架构 (ES6 Modules) - -后端技术栈: -├── Python 3.7+ -├── Flask 2.3.3 -├── Cassandra Driver 3.29.1 -├── Redis Client -└── SQLite (配置存储) - -数据存储: -├── Apache Cassandra (主要数据源) -├── Redis Cluster (缓存和数据源) -└── SQLite (配置和历史数据) -``` - -## 2. 整体架构 - -### 2.1 架构概览 -``` -┌─────────────────────────────────────────────────────────────┐ -│ DataTools Pro 架构图 │ -├─────────────────────────────────────────────────────────────┤ -│ 前端层 (Frontend Layer) │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ -│ │ 首页模块 │ │ Cassandra工具 │ │ Redis工具 ││ -│ │ index.html │ │ db_compare.html │ │redis_compare.html││ -│ └─────────────────┘ └─────────────────┘ └─────────────────┘│ -│ │ │ │ │ -│ ┌───────────────────────────────────────────────────────────┐│ -│ │ 模块化JavaScript架构 ││ -│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐ ┌─────────┐││ -│ │ │ config │ │ utils │ │ api │ │ ui │ │ nav │││ -│ │ └─────────┘ └─────────┘ └─────────┘ └─────────┘ └─────────┘││ -│ └───────────────────────────────────────────────────────────┘│ -├─────────────────────────────────────────────────────────────┤ -│ 网关层 (Gateway Layer) │ -│ ┌───────────────────────────────────────────────────────────┐│ -│ │ Flask Web Server ││ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐││ -│ │ │ 静态资源 │ │ API路由 │ │ 模板渲染 │││ -│ │ │ 服务 │ │ 处理 │ │ 引擎 │││ -│ │ └─────────────┘ └─────────────┘ └─────────────────────────┘││ -│ └───────────────────────────────────────────────────────────┘│ -├─────────────────────────────────────────────────────────────┤ -│ 业务逻辑层 (Business Logic Layer) │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ -│ │ 查询引擎 │ │ 数据比对 │ │ 配置管理 ││ -│ │ QueryEngine │ │ DataComparison │ │ ConfigManager ││ -│ └─────────────────┘ └─────────────────┘ └─────────────────┘│ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ -│ │ 分表处理 │ │ 日志收集 │ │ Redis处理 ││ -│ │ ShardingCalc │ │ QueryLogger │ │ RedisClient ││ -│ └─────────────────┘ └─────────────────┘ └─────────────────┘│ -├─────────────────────────────────────────────────────────────┤ -│ 数据访问层 (Data Access Layer) │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ -│ │ Cassandra │ │ Redis Cluster │ │ SQLite DB ││ -│ │ 客户端 │ │ 客户端 │ │ 本地存储 ││ -│ └─────────────────┘ └─────────────────┘ └─────────────────┘│ -├─────────────────────────────────────────────────────────────┤ -│ 数据存储层 (Data Storage Layer) │ -│ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐│ -│ │ 生产环境 │ │ 测试环境 │ │ 配置数据 ││ -│ │ Cassandra │ │ Cassandra │ │ SQLite ││ -│ └─────────────────┘ └─────────────────┘ └─────────────────┘│ -│ ┌─────────────────┐ ┌─────────────────┐ │ -│ │ 生产Redis │ │ 测试Redis │ │ -│ │ 集群 │ │ 集群 │ │ -│ └─────────────────┘ └─────────────────┘ │ -└─────────────────────────────────────────────────────────────┘ -``` - -### 2.2 核心组件 - -#### 2.2.1 前端架构 -```javascript -// 模块化架构设计 -static/js/ -├── app-main.js // 主应用入口,统一管理 -└── modules/ - ├── config.js // 配置管理 - API端点、UI配置 - ├── utils.js // 工具函数 - 通用功能库 - ├── api.js // HTTP客户端 - 统一请求处理 - ├── ui.js // UI组件 - 提示、模态框、分页 - └── navigation.js // 导航管理 - 路由、面包屑、快捷键 -``` - -**设计模式**: 模块化 + 单例模式 -**核心特性**: -- ES6模块化,避免全局变量污染 -- 统一的配置管理和错误处理 -- 响应式UI组件和交互增强 -- 键盘快捷键和无障碍支持 - -#### 2.2.2 后端架构 -```python -# 模块化后端设计 -modules/ -├── api_routes.py // API路由定义和请求处理 -├── cassandra_client.py // Cassandra数据库连接和操作 -├── redis_client.py // Redis集群连接和操作 -├── query_engine.py // 查询引擎和SQL构建 -├── data_comparison.py // 数据比对算法和分析 -├── sharding.py // 分表计算和时间戳处理 -├── config_manager.py // 配置组管理和持久化 -├── query_logger.py // 查询日志收集和管理 -└── database.py // SQLite数据库操作 -``` - -**设计模式**: 分层架构 + 依赖注入 -**核心特性**: -- 单一职责原则,模块解耦 -- 统一的错误处理和日志记录 -- 连接池管理和资源优化 -- 配置驱动的灵活部署 - -## 3. 核心功能模块 - -### 3.1 Cassandra数据比对模块 - -#### 3.1.1 功能特性 -- **多模式查询**: 单表查询、分表查询、多主键查询 -- **时间分表支持**: TWCS (Time Window Compaction Strategy) 分表计算 -- **复合主键**: 支持多字段组合主键查询 -- **字段级比对**: 支持包含/排除字段的精细化比较 -- **JSON处理**: 智能JSON字段识别和深度比较 - -#### 3.1.2 核心算法 -```python -# 分表索引计算算法 -def calculate_shard_index(timestamp, interval_seconds, table_count): - """ - 计算分表索引 - - timestamp: 从Key中提取的时间戳 - - interval_seconds: 分表时间间隔(默认604800秒=7天) - - table_count: 分表数量(默认14张表) - """ - return int(timestamp) // interval_seconds % table_count - -# 时间戳提取算法 -def extract_timestamp_from_key(key): - """ - 从Key中提取时间戳 - 删除所有非数字字符 - 示例: 'wmid_1609459200' -> 1609459200 - """ - return re.sub(r'\D', '', key) - -# 复合主键匹配算法 -def match_composite_key(record, key_fields, key_values): - """ - 复合主键匹配逻辑 - - 支持单主键和复合主键统一处理 - - 自动类型转换和字段验证 - """ - if len(key_fields) == 1: - return str(record.get(key_fields[0])) == str(key_values[0]) - else: - return all( - str(record.get(field)) == str(value) - for field, value in zip(key_fields, key_values) - ) -``` - -### 3.2 Redis集群比对模块 - -#### 3.2.1 功能特性 -- **多数据类型支持**: String、Hash、List、Set、ZSet -- **查询模式**: 随机采样、指定Key查询 -- **集群管理**: 多节点集群配置和连接管理 -- **性能监控**: 连接状态、查询耗时统计 -- **批量操作**: 大批量Key的并行处理 - -#### 3.2.2 Redis集群架构 -```python -# Redis集群连接配置 -{ - "cluster_name": "生产集群", - "nodes": [ - {"host": "127.0.0.1", "port": 6379}, - {"host": "127.0.0.1", "port": 6380} - ], - "password": "optional_password", - "socket_timeout": 3, - "socket_connect_timeout": 3, - "max_connections_per_node": 16 -} -``` - -### 3.3 数据比对引擎 - -#### 3.3.1 比对算法 -```python -# 数据比对核心逻辑 -class DataComparison: - def compare_results(self, pro_data, test_data, key_fields): - """ - 数据比对主算法: - 1. 构建数据索引映射 (基于主键) - 2. 逐字段深度比较 - 3. JSON字段特殊处理 - 4. 数组字段顺序无关比较 - 5. 生成差异报告和统计 - """ - differences = [] - identical_results = [] - field_diff_count = {} - - # 构建生产数据索引 - pro_index = self.build_data_index(pro_data, key_fields) - test_index = self.build_data_index(test_data, key_fields) - - # 执行比对逻辑 - for key, pro_record in pro_index.items(): - if key in test_index: - test_record = test_index[key] - diffs = self.compare_records(pro_record, test_record) - if diffs: - differences.extend(diffs) - else: - identical_results.append({ - 'key': key, - 'pro_fields': pro_record, - 'test_fields': test_record - }) - - return { - 'differences': differences, - 'identical_results': identical_results, - 'field_diff_count': field_diff_count, - 'summary': self.generate_summary(differences, identical_results) - } -``` - -#### 3.3.2 JSON处理算法 -```python -def compare_json_values(pro_value, test_value): - """ - JSON值比较算法: - 1. 智能检测JSON格式 - 2. 规范化JSON字符串 - 3. 深度比较对象结构 - 4. 数组顺序无关比较 - """ - if self.is_json_field(pro_value) and self.is_json_field(test_value): - try: - pro_obj = json.loads(pro_value) - test_obj = json.loads(test_value) - return self.deep_compare_objects(pro_obj, test_obj) - except: - return pro_value == test_value - return pro_value == test_value -``` - -## 4. 数据流架构 - -### 4.1 查询执行流程 -```mermaid -graph TD - A[用户请求] --> B[前端验证] - B --> C[API路由] - C --> D{查询类型} - D -->|单表查询| E[QueryEngine.execute_query] - D -->|分表查询| F[QueryEngine.execute_sharding_query] - E --> G[数据库连接] - F --> H[分表计算] - H --> G - G --> I[并行查询执行] - I --> J[数据收集] - J --> K[DataComparison.compare_results] - K --> L[结果分析] - L --> M[日志记录] - M --> N[响应返回] -``` - -### 4.2 配置管理流程 -```mermaid -graph TD - A[配置创建/更新] --> B[ConfigManager验证] - B --> C[SQLite持久化] - C --> D[配置缓存更新] - D --> E[前端状态同步] - - F[配置加载] --> G[SQLite查询] - G --> H[配置反序列化] - H --> I[前端配置应用] -``` - -## 5. 性能优化策略 - -### 5.1 查询优化 -- **连接池管理**: 复用数据库连接,减少连接开销 -- **并行查询**: 多线程并行执行生产和测试环境查询 -- **分批处理**: 大量Key分批查询,避免内存溢出 -- **索引优化**: 合理设计Cassandra分区键和聚簇键 - -### 5.2 前端性能 -- **懒加载**: 按需加载JS模块和数据 -- **虚拟分页**: 大数据集的分页展示 -- **防抖节流**: 用户输入和搜索的性能优化 -- **缓存策略**: 查询结果和配置数据的客户端缓存 - -### 5.3 内存管理 -- **流式处理**: 大数据集的流式读取和处理 -- **及时释放**: 查询完成后及时释放数据库连接和内存 -- **垃圾回收**: Python和JavaScript的内存回收优化 - -## 6. 扩展性设计 - -### 6.1 水平扩展 -- **无状态设计**: 应用层无状态,支持负载均衡 -- **配置外部化**: 支持配置中心和环境变量 -- **容器化**: Docker容器化部署 -- **微服务拆分**: 可拆分为独立的查询服务和比对服务 - -### 6.2 功能扩展 -- **插件架构**: 支持自定义数据源和比对算法 -- **API开放**: RESTful API支持第三方集成 -- **规则引擎**: 可配置的数据验证和比对规则 -- **报告生成**: 支持多种格式的报告导出 - -## 7. 安全架构 - -### 7.1 数据安全 -- **连接加密**: 支持SSL/TLS加密连接 -- **密码管理**: 敏感信息加密存储 -- **访问控制**: 基于角色的权限管理 -- **审计日志**: 完整的操作审计记录 - -### 7.2 系统安全 -- **输入验证**: 严格的参数验证和SQL注入防护 -- **错误处理**: 不暴露敏感系统信息 -- **会话管理**: 安全的会话管理机制 -- **网络安全**: 防火墙和网络隔离 - -## 8. 监控和运维 - -### 8.1 系统监控 -- **性能指标**: 查询耗时、成功率、错误率 -- **资源监控**: CPU、内存、网络使用情况 -- **业务指标**: 查询量、用户活跃度、功能使用统计 -- **告警机制**: 异常情况的实时告警 - -### 8.2 日志管理 -- **结构化日志**: JSON格式的结构化日志 -- **日志分级**: INFO、WARNING、ERROR、DEBUG -- **日志轮转**: 自动日志清理和归档 -- **日志分析**: 支持ELK等日志分析工具 - -## 9. 技术债务和改进计划 - -### 9.1 当前技术债务 -- **单体应用**: 所有功能集中在单个Flask应用中 -- **前端技术**: 使用原生JavaScript,缺乏现代化框架 -- **测试覆盖**: 缺乏完整的单元测试和集成测试 -- **文档完善**: API文档和代码注释需要完善 - -### 9.2 改进计划 -- **微服务改造**: 逐步拆分为独立的微服务 -- **前端升级**: 考虑引入Vue.js或React框架 -- **CI/CD**: 建立完整的持续集成和部署流程 -- **性能测试**: 建立性能基准和压力测试 - ---- - -**版本**: v2.0.0 -**更新日期**: 2024-08-05 -**维护者**: DataTools Pro Team \ No newline at end of file diff --git a/docs/database-design.md b/docs/database-design.md deleted file mode 100644 index c075195..0000000 --- a/docs/database-design.md +++ /dev/null @@ -1,603 +0,0 @@ -# DataTools Pro 数据库设计文档 - -## 1. 数据库概述 - -### 1.1 数据库架构 -DataTools Pro采用多数据库架构,针对不同的数据存储需求选择最适合的数据库技术: - -``` -数据库架构图: -┌─────────────────────────────────────────────────────────┐ -│ DataTools Pro 数据库架构 │ -├─────────────────────────────────────────────────────────┤ -│ 应用层 (Application Layer) │ -│ ┌─────────────────────────────────────────────────────┐ │ -│ │ Flask应用程序 │ │ -│ └─────────────────────────────────────────────────────┘ │ -├─────────────────────────────────────────────────────────┤ -│ 数据访问层 (Data Access Layer) │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ -│ │ Cassandra │ │ Redis │ │ SQLite │ │ -│ │ Driver │ │ Client │ │ Driver │ │ -│ └─────────────┘ └─────────────┘ └─────────────────────┘ │ -├─────────────────────────────────────────────────────────┤ -│ 数据存储层 (Data Storage Layer) │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ -│ │ Apache │ │ Redis │ │ SQLite │ │ -│ │ Cassandra │ │ Cluster │ │ 本地文件 │ │ -│ │ 集群 │ │ │ │ config_groups.db │ │ -│ │ (外部数据源) │ │ (外部数据源) │ │ (配置和历史数据) │ │ -│ └─────────────┘ └─────────────┘ └─────────────────────┘ │ -└─────────────────────────────────────────────────────────┘ -``` - -### 1.2 数据库分类 - -#### 1.2.1 外部数据源 -- **Apache Cassandra**: 主要的数据比对源,存储业务数据 -- **Redis Cluster**: 缓存和高性能数据存储,支持多种数据类型 - -#### 1.2.2 内部存储 -- **SQLite**: 轻量级关系数据库,存储系统配置、查询历史和日志 - -### 1.3 设计原则 -- **数据隔离**: 不同类型数据使用不同的存储方案 -- **性能优化**: 根据访问模式选择合适的数据库 -- **易维护**: 简化数据库管理和备份恢复 -- **扩展性**: 支持数据量增长和功能扩展 - -## 2. SQLite数据库设计 - -### 2.1 数据库文件 -- **文件名**: `config_groups.db` -- **位置**: 项目根目录 -- **编码**: UTF-8 -- **版本**: SQLite 3.x - -### 2.2 表结构设计 - -#### 2.2.1 config_groups表 - 配置组管理 -```sql -CREATE TABLE config_groups ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL UNIQUE, -- 配置组名称 - description TEXT, -- 描述信息 - pro_config TEXT NOT NULL, -- 生产环境配置(JSON) - test_config TEXT NOT NULL, -- 测试环境配置(JSON) - query_config TEXT NOT NULL, -- 查询配置(JSON) - sharding_config TEXT, -- 分表配置(JSON) - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - updated_at DATETIME DEFAULT CURRENT_TIMESTAMP -); - --- 索引 -CREATE INDEX idx_config_groups_name ON config_groups(name); -CREATE INDEX idx_config_groups_created_at ON config_groups(created_at); -``` - -**字段详解**: -- `id`: 主键,自增整数 -- `name`: 配置组名称,唯一索引 -- `description`: 配置组描述,可为空 -- `pro_config`: 生产环境Cassandra配置,JSON格式 -- `test_config`: 测试环境Cassandra配置,JSON格式 -- `query_config`: 查询参数配置,JSON格式 -- `sharding_config`: 分表查询配置,JSON格式 -- `created_at`: 创建时间 -- `updated_at`: 更新时间 - -**JSON配置示例**: -```json -{ - "pro_config": { - "cluster_name": "production-cluster", - "datacenter": "datacenter1", - "hosts": ["10.0.1.100", "10.0.1.101"], - "port": 9042, - "username": "cassandra", - "password": "encrypted_password", - "keyspace": "production_ks", - "table": "user_data" - }, - "query_config": { - "keys": ["user_id"], - "fields_to_compare": ["name", "email", "status"], - "exclude_fields": ["created_at", "updated_at"] - }, - "sharding_config": { - "use_sharding_for_pro": true, - "use_sharding_for_test": false, - "interval_seconds": 604800, - "table_count": 14 - } -} -``` - -#### 2.2.2 query_history表 - 查询历史记录 -```sql -CREATE TABLE query_history ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - name TEXT NOT NULL, -- 历史记录名称 - description TEXT, -- 描述信息 - pro_config TEXT NOT NULL, -- 生产环境配置(JSON) - test_config TEXT NOT NULL, -- 测试环境配置(JSON) - query_config TEXT NOT NULL, -- 查询配置(JSON) - query_keys TEXT NOT NULL, -- 查询的键值(JSON Array) - results_summary TEXT NOT NULL, -- 结果摘要(JSON) - execution_time REAL NOT NULL, -- 执行时间(秒) - total_keys INTEGER NOT NULL, -- 总Key数量 - differences_count INTEGER NOT NULL, -- 差异数量 - identical_count INTEGER NOT NULL, -- 相同数量 - query_type TEXT NOT NULL DEFAULT 'single', -- 查询类型(single/sharding) - sharding_config TEXT, -- 分表配置(JSON) - raw_results TEXT, -- 完整查询结果(JSON) - differences_data TEXT, -- 差异详细数据(JSON) - identical_data TEXT, -- 相同数据详情(JSON) - created_at DATETIME DEFAULT CURRENT_TIMESTAMP -); - --- 索引 -CREATE INDEX idx_query_history_name ON query_history(name); -CREATE INDEX idx_query_history_query_type ON query_history(query_type); -CREATE INDEX idx_query_history_created_at ON query_history(created_at); -CREATE INDEX idx_query_history_execution_time ON query_history(execution_time); -``` - -**字段详解**: -- `id`: 主键,自增整数 -- `name`: 历史记录名称 -- `description`: 历史记录描述 -- `pro_config`: 生产环境配置快照 -- `test_config`: 测试环境配置快照 -- `query_config`: 查询配置快照 -- `query_keys`: 查询的Key值列表 -- `results_summary`: 查询结果摘要统计 -- `execution_time`: 查询执行时间 -- `total_keys`: 查询的总Key数量 -- `differences_count`: 发现的差异数量 -- `identical_count`: 相同记录数量 -- `query_type`: 查询类型(single/sharding) -- `sharding_config`: 分表配置(仅分表查询) -- `raw_results`: 完整的查询结果数据 -- `differences_data`: 差异数据详情 -- `identical_data`: 相同数据详情 -- `created_at`: 创建时间 - -#### 2.2.3 query_logs表 - 查询日志记录 -```sql -CREATE TABLE query_logs ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - batch_id TEXT NOT NULL, -- 批次ID(UUID) - history_id INTEGER, -- 关联历史记录ID - timestamp DATETIME NOT NULL, -- 日志时间戳 - level TEXT NOT NULL, -- 日志级别(INFO/WARNING/ERROR) - message TEXT NOT NULL, -- 日志消息 - query_type TEXT NOT NULL, -- 查询类型标识 - created_at DATETIME DEFAULT CURRENT_TIMESTAMP, - - FOREIGN KEY (history_id) REFERENCES query_history(id) ON DELETE SET NULL -); - --- 索引 -CREATE INDEX idx_query_logs_batch_id ON query_logs(batch_id); -CREATE INDEX idx_query_logs_history_id ON query_logs(history_id); -CREATE INDEX idx_query_logs_level ON query_logs(level); -CREATE INDEX idx_query_logs_timestamp ON query_logs(timestamp); -CREATE INDEX idx_query_logs_query_type ON query_logs(query_type); -``` - -**字段详解**: -- `id`: 主键,自增整数 -- `batch_id`: 批次标识,同一次查询操作的日志共享同一个batch_id -- `history_id`: 关联的历史记录ID,外键关联 -- `timestamp`: 日志产生的精确时间戳 -- `level`: 日志级别(INFO/WARNING/ERROR) -- `message`: 日志消息内容 -- `query_type`: 查询类型标识(cassandra_single/cassandra_sharding/redis_compare) -- `created_at`: 记录创建时间 - -### 2.3 数据库触发器 - -#### 2.3.1 自动更新updated_at触发器 -```sql --- 配置组更新时间触发器 -CREATE TRIGGER update_config_groups_updated_at - AFTER UPDATE ON config_groups - FOR EACH ROW - BEGIN - UPDATE config_groups - SET updated_at = CURRENT_TIMESTAMP - WHERE id = NEW.id; - END; -``` - -### 2.4 数据库视图 - -#### 2.4.1 查询历史统计视图 -```sql -CREATE VIEW query_history_stats AS -SELECT - query_type, - COUNT(*) as total_queries, - AVG(execution_time) as avg_execution_time, - AVG(total_keys) as avg_keys_per_query, - AVG(differences_count) as avg_differences, - AVG(CAST(differences_count AS REAL) / total_keys * 100) as avg_diff_rate, - MIN(created_at) as first_query, - MAX(created_at) as last_query -FROM query_history -GROUP BY query_type; -``` - -#### 2.4.2 日志统计视图 -```sql -CREATE VIEW query_logs_stats AS -SELECT - DATE(created_at) as log_date, - level, - query_type, - COUNT(*) as log_count -FROM query_logs -GROUP BY DATE(created_at), level, query_type -ORDER BY log_date DESC, level; -``` - -## 3. Cassandra数据库设计 - -### 3.1 数据模型理解 -DataTools Pro作为数据比对工具,**不直接管理**Cassandra的数据模型,而是连接到现有的Cassandra集群进行数据查询和比对。 - -### 3.2 支持的Cassandra特性 - -#### 3.2.1 表结构支持 -- **单表查询**: 支持任意Cassandra表结构 -- **分表查询**: 支持TWCS(Time Window Compaction Strategy)分表模式 -- **复合主键**: 支持多字段组合主键 -- **所有数据类型**: text、int、timestamp、uuid、blob等 - -#### 3.2.2 查询模式 -```cql --- 单主键查询示例 -SELECT * FROM keyspace.table_name -WHERE primary_key IN (?, ?, ?); - --- 复合主键查询示例 -SELECT * FROM keyspace.table_name -WHERE (key1='value1' AND key2='value2') - OR (key1='value3' AND key2='value4'); - --- 分表查询示例 -SELECT * FROM keyspace.table_name_0 -WHERE primary_key IN (?, ?); -SELECT * FROM keyspace.table_name_1 -WHERE primary_key IN (?); -``` - -#### 3.2.3 分表命名规范 -``` -基础表名: user_data -分表命名: user_data_0, user_data_1, user_data_2, ..., user_data_13 -分表计算: shard_index = timestamp // interval_seconds % table_count -``` - -### 3.3 连接管理 -```python -# Cassandra连接配置 -cassandra_config = { - "cluster_name": "production-cluster", - "datacenter": "datacenter1", - "hosts": ["10.0.1.100", "10.0.1.101", "10.0.1.102"], - "port": 9042, - "username": "app_user", - "password": "secure_password", - "keyspace": "application_data", - "table": "user_profiles" -} - -# 连接池配置 -connection_settings = { - "connect_timeout": 10, - "request_timeout": 30, - "load_balancing_policy": "DCAwareRoundRobinPolicy", - "retry_policy": "RetryPolicy", - "compression": "lz4" -} -``` - -## 4. Redis数据库设计 - -### 4.1 数据模型理解 -DataTools Pro支持Redis集群的数据比对,**不直接管理**Redis的数据结构,而是连接到现有的Redis集群进行数据查询和比对。 - -### 4.2 支持的Redis数据类型 - -#### 4.2.1 基本数据类型 -- **String**: 字符串类型,最常用的数据类型 -- **Hash**: 哈希表,存储字段-值对 -- **List**: 列表,有序的字符串集合 -- **Set**: 集合,无序的字符串集合 -- **Sorted Set**: 有序集合,带分数的有序字符串集合 - -#### 4.2.2 查询操作 -```python -# 不同数据类型的查询操作 -redis_operations = { - "string": "GET key", - "hash": "HGETALL key", - "list": "LRANGE key 0 -1", - "set": "SMEMBERS key", - "zset": "ZRANGE key 0 -1 WITHSCORES" -} -``` - -### 4.3 Redis集群配置 -```python -# Redis集群连接配置 -redis_config = { - "cluster_name": "production-redis", - "nodes": [ - {"host": "10.0.1.100", "port": 6379}, - {"host": "10.0.1.101", "port": 6379}, - {"host": "10.0.1.102", "port": 6379} - ], - "password": "redis_password", - "socket_timeout": 3, - "socket_connect_timeout": 3, - "max_connections_per_node": 16, - "skip_full_coverage_check": True, - "decode_responses": True -} -``` - -## 5. 数据迁移和版本管理 - -### 5.1 数据库版本控制 - -#### 5.1.1 版本信息表 -```sql -CREATE TABLE database_version ( - version TEXT PRIMARY KEY, - applied_at DATETIME DEFAULT CURRENT_TIMESTAMP, - description TEXT -); - -INSERT INTO database_version (version, description) -VALUES ('1.0.0', '初始数据库结构'); -``` - -#### 5.1.2 迁移脚本示例 -```sql --- 版本1.0.0 -> 1.1.0 迁移脚本 --- 添加Redis配置支持 -ALTER TABLE config_groups -ADD COLUMN redis_config TEXT; - -INSERT INTO database_version (version, description) -VALUES ('1.1.0', '添加Redis配置支持'); -``` - -### 5.2 数据备份策略 - -#### 5.2.1 SQLite备份 -```bash -# 完整备份 -cp config_groups.db config_groups_backup_$(date +%Y%m%d_%H%M%S).db - -# 增量备份(基于时间戳) -sqlite3 config_groups.db " -SELECT * FROM config_groups -WHERE updated_at > '2024-08-05 00:00:00';" > incremental_backup.sql -``` - -#### 5.2.2 备份恢复 -```bash -# 恢复完整备份 -cp config_groups_backup_20240805_100000.db config_groups.db - -# 恢复增量数据 -sqlite3 config_groups.db < incremental_backup.sql -``` - -## 6. 性能优化 - -### 6.1 SQLite优化 - -#### 6.1.1 配置优化 -```sql --- SQLite性能优化设置 -PRAGMA journal_mode = WAL; -- 写前日志模式 -PRAGMA synchronous = NORMAL; -- 平衡性能和安全 -PRAGMA cache_size = 10000; -- 缓存页面数量 -PRAGMA temp_store = memory; -- 临时表存储在内存 -PRAGMA mmap_size = 268435456; -- 内存映射大小(256MB) -``` - -#### 6.1.2 查询优化 -```sql --- 分页查询优化 -SELECT * FROM query_history -WHERE created_at >= ? -ORDER BY created_at DESC -LIMIT ? OFFSET ?; - --- 统计查询优化 -SELECT query_type, COUNT(*), AVG(execution_time) -FROM query_history -WHERE created_at >= DATE('now', '-30 days') -GROUP BY query_type; -``` - -### 6.2 连接池优化 - -#### 6.2.1 Cassandra连接池 -```python -# 连接池配置 -cluster = Cluster( - hosts=['10.0.1.100', '10.0.1.101'], - port=9042, - load_balancing_policy=DCAwareRoundRobinPolicy(local_dc='datacenter1'), - default_retry_policy=RetryPolicy(), - compression=True, - protocol_version=4 -) - -# 会话池管理 -session_pool = cluster.connect() -session_pool.default_timeout = 30 -``` - -#### 6.2.2 Redis连接池 -```python -# Redis集群连接池 -from rediscluster import RedisCluster - -redis_cluster = RedisCluster( - startup_nodes=[ - {"host": "10.0.1.100", "port": 6379}, - {"host": "10.0.1.101", "port": 6379} - ], - password="redis_password", - socket_timeout=3, - socket_connect_timeout=3, - max_connections_per_node=16, - skip_full_coverage_check=True -) -``` - -## 7. 数据安全 - -### 7.1 敏感数据处理 - -#### 7.1.1 密码加密 -```python -# 配置中的密码加密存储 -import base64 -from cryptography.fernet import Fernet - -def encrypt_password(password, key): - """加密密码""" - f = Fernet(key) - encrypted_password = f.encrypt(password.encode()) - return base64.b64encode(encrypted_password).decode() - -def decrypt_password(encrypted_password, key): - """解密密码""" - f = Fernet(key) - decoded_password = base64.b64decode(encrypted_password.encode()) - return f.decrypt(decoded_password).decode() -``` - -#### 7.1.2 数据脱敏 -```python -def mask_sensitive_data(config): - """配置数据脱敏显示""" - masked_config = config.copy() - if 'password' in masked_config: - masked_config['password'] = '***masked***' - return masked_config -``` - -### 7.2 访问控制 - -#### 7.2.1 数据库权限 -```sql --- SQLite访问控制(文件系统级别) -chmod 600 config_groups.db -- 仅所有者可读写 -chown app:app config_groups.db -- 设置正确的所有者 -``` - -#### 7.2.2 网络安全 -```python -# Cassandra SSL连接 -from cassandra.auth import PlainTextAuthProvider -from ssl import SSLContext, PROTOCOL_TLS - -ssl_context = SSLContext(PROTOCOL_TLS) -auth_provider = PlainTextAuthProvider(username='app_user', password='password') - -cluster = Cluster( - ['10.0.1.100'], - ssl_context=ssl_context, - auth_provider=auth_provider -) -``` - -## 8. 监控和维护 - -### 8.1 数据库监控 - -#### 8.1.1 SQLite监控 -```sql --- 数据库大小监控 -SELECT - (page_count * page_size) / 1024 / 1024 as db_size_mb -FROM pragma_page_count(), pragma_page_size(); - --- 表大小统计 -SELECT - name, - COUNT(*) as row_count -FROM sqlite_master sm -JOIN ( - SELECT 'config_groups' as name, COUNT(*) as cnt FROM config_groups - UNION ALL - SELECT 'query_history' as name, COUNT(*) as cnt FROM query_history - UNION ALL - SELECT 'query_logs' as name, COUNT(*) as cnt FROM query_logs -) t ON sm.name = t.name; -``` - -#### 8.1.2 连接监控 -```python -# 连接健康检查 -def check_database_health(): - """检查数据库连接健康状态""" - health_status = { - "sqlite": check_sqlite_health(), - "cassandra": check_cassandra_health(), - "redis": check_redis_health() - } - return health_status - -def check_sqlite_health(): - """检查SQLite健康状态""" - try: - conn = sqlite3.connect('config_groups.db') - cursor = conn.cursor() - cursor.execute("SELECT 1") - conn.close() - return {"status": "healthy", "timestamp": datetime.now()} - except Exception as e: - return {"status": "unhealthy", "error": str(e)} -``` - -### 8.2 数据维护 - -#### 8.2.1 数据清理 -```sql --- 清理30天前的查询日志 -DELETE FROM query_logs -WHERE created_at < DATE('now', '-30 days'); - --- 清理大型历史记录的详细数据 -UPDATE query_history -SET raw_results = NULL, - differences_data = NULL, - identical_data = NULL -WHERE created_at < DATE('now', '-90 days'); -``` - -#### 8.2.2 数据库维护 -```sql --- SQLite数据库优化 -VACUUM; -- 重建数据库文件,回收空间 -ANALYZE; -- 更新查询计划统计信息 -PRAGMA optimize; -- 优化数据库性能 -REINDEX; -- 重建所有索引 -``` - ---- - -**版本**: v1.0 -**更新日期**: 2024-08-05 -**维护者**: DataTools Pro Team \ No newline at end of file diff --git a/docs/deployment.md b/docs/deployment.md deleted file mode 100644 index 0f857a3..0000000 --- a/docs/deployment.md +++ /dev/null @@ -1,1427 +0,0 @@ -# DataTools Pro 部署指南 - -## 1. 部署概述 - -### 1.1 部署架构 -DataTools Pro支持多种部署方式,从简单的单机部署到企业级的容器化集群部署。 - -``` -部署架构选择: -┌─────────────────────────────────────────────────────────────┐ -│ 部署方案对比 │ -├─────────────────────────────────────────────────────────────┤ -│ 开发环境部署 │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ • 本地开发服务器 (Flask dev server) │ │ -│ │ • SQLite数据库 │ │ -│ │ • 适用于: 开发测试、功能验证 │ │ -│ └─────────────────────────────────────────────────────────┘ │ -├─────────────────────────────────────────────────────────────┤ -│ 生产环境部署 │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ • WSGI服务器 (Gunicorn/uWSGI) │ │ -│ │ • 反向代理 (Nginx/Apache) │ │ -│ │ • 进程管理 (systemd/supervisor) │ │ -│ │ • 适用于: 小型生产环境 │ │ -│ └─────────────────────────────────────────────────────────┘ │ -├─────────────────────────────────────────────────────────────┤ -│ 容器化部署 │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ • Docker容器化 │ │ -│ │ • Docker Compose编排 │ │ -│ │ • 负载均衡和高可用 │ │ -│ │ • 适用于: 中大型生产环境 │ │ -│ └─────────────────────────────────────────────────────────┘ │ -├─────────────────────────────────────────────────────────────┤ -│ Kubernetes部署 │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ • K8s Deployment和Service │ │ -│ │ • 自动扩缩容和故障恢复 │ │ -│ │ • ConfigMap和Secret管理 │ │ -│ │ • 适用于: 企业级云原生环境 │ │ -│ └─────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────┘ -``` - -### 1.2 环境要求 - -#### 1.2.1 基础环境 -- **操作系统**: Linux (推荐Ubuntu 20.04+, CentOS 8+) -- **Python版本**: Python 3.7+ -- **内存**: 最低2GB,推荐4GB+ -- **磁盘**: 最低10GB,推荐50GB+ -- **网络**: 能够访问Cassandra和Redis集群 - -#### 1.2.2 软件依赖 -```bash -# 系统包依赖 -sudo apt-get update -sudo apt-get install -y \ - python3 \ - python3-pip \ - python3-venv \ - git \ - nginx \ - supervisor \ - curl \ - wget -``` - -#### 1.2.3 Python依赖 -```txt -# requirements.txt -Flask==2.3.3 -cassandra-driver==3.29.1 -redis==4.5.4 -redis-py-cluster==2.1.3 -gunicorn==21.2.0 -gevent==23.7.0 -python-dotenv==1.0.0 -PyYAML==6.0.1 -cryptography==41.0.3 -``` - -## 2. 开发环境部署 - -### 2.1 快速启动 -```bash -# 1. 克隆项目 -git clone -cd BigDataTool - -# 2. 创建虚拟环境 -python3 -m venv venv -source venv/bin/activate # Linux/Mac -# venv\Scripts\activate # Windows - -# 3. 安装依赖 -pip install -r requirements.txt - -# 4. 初始化配置 -cp config.example.py config.py - -# 5. 启动应用 -python app.py -``` - -### 2.2 开发环境配置 -```python -# config.py - 开发环境配置 -DEBUG = True -TESTING = False - -# 数据库配置 -DATABASE_URL = 'sqlite:///config_groups.db' - -# 日志配置 -LOG_LEVEL = 'DEBUG' -LOG_FILE = 'logs/datatools.log' - -# 安全配置 -SECRET_KEY = 'dev-secret-key-change-in-production' - -# Cassandra默认配置 -DEFAULT_CASSANDRA_CONFIG = { - 'hosts': ['127.0.0.1'], - 'port': 9042, - 'keyspace': 'test_ks' -} - -# Redis默认配置 -DEFAULT_REDIS_CONFIG = { - 'host': '127.0.0.1', - 'port': 6379, - 'db': 0 -} -``` - -### 2.3 开发服务脚本 -```bash -#!/bin/bash -# dev-server.sh - 开发服务器启动脚本 - -set -e - -# 检查虚拟环境 -if [[ "$VIRTUAL_ENV" == "" ]]; then - echo "请先激活虚拟环境: source venv/bin/activate" - exit 1 -fi - -# 创建必要目录 -mkdir -p logs -mkdir -p data - -# 检查配置文件 -if [ ! -f "config.py" ]; then - echo "复制配置文件: cp config.example.py config.py" - cp config.example.py config.py -fi - -# 初始化数据库 -python -c " -from app import init_database -init_database() -print('数据库初始化完成') -" - -# 启动开发服务器 -echo "启动DataTools Pro开发服务器..." -echo "访问地址: http://localhost:5000" -python app.py -``` - -## 3. 生产环境部署 - -### 3.1 系统用户创建 -```bash -# 创建专用用户 -sudo useradd -r -s /bin/false datatools -sudo mkdir -p /opt/datatools -sudo chown datatools:datatools /opt/datatools -``` - -### 3.2 应用部署 -```bash -#!/bin/bash -# deploy-production.sh - 生产环境部署脚本 - -set -e - -APP_USER="datatools" -APP_DIR="/opt/datatools" -APP_NAME="datatools-pro" -PYTHON_VERSION="3.9" - -echo "开始部署DataTools Pro到生产环境..." - -# 1. 创建应用目录 -sudo mkdir -p $APP_DIR/{app,logs,data,backup} -sudo chown -R $APP_USER:$APP_USER $APP_DIR - -# 2. 部署应用代码 -sudo -u $APP_USER git clone $APP_DIR/app -cd $APP_DIR/app - -# 3. 创建虚拟环境 -sudo -u $APP_USER python$PYTHON_VERSION -m venv $APP_DIR/venv -sudo -u $APP_USER $APP_DIR/venv/bin/pip install --upgrade pip - -# 4. 安装依赖 -sudo -u $APP_USER $APP_DIR/venv/bin/pip install -r requirements.txt - -# 5. 创建生产配置 -sudo -u $APP_USER cp config.example.py config.py -sudo -u $APP_USER cat > config.py << 'EOF' -import os -from dotenv import load_dotenv - -# 加载环境变量 -load_dotenv() - -# 基础配置 -DEBUG = False -TESTING = False -SECRET_KEY = os.getenv('SECRET_KEY', 'change-this-in-production') - -# 数据库配置 -DATABASE_URL = os.getenv('DATABASE_URL', '/opt/datatools/data/config_groups.db') - -# 日志配置 -LOG_LEVEL = os.getenv('LOG_LEVEL', 'INFO') -LOG_FILE = '/opt/datatools/logs/datatools.log' - -# 服务器配置 -HOST = os.getenv('HOST', '127.0.0.1') -PORT = int(os.getenv('PORT', 5000)) -WORKERS = int(os.getenv('WORKERS', 4)) - -# 外部服务配置 -CASSANDRA_HOSTS = os.getenv('CASSANDRA_HOSTS', '127.0.0.1').split(',') -REDIS_HOSTS = os.getenv('REDIS_HOSTS', '127.0.0.1').split(',') -EOF - -# 6. 创建环境变量文件 -sudo -u $APP_USER cat > $APP_DIR/.env << 'EOF' -# 生产环境配置 -SECRET_KEY=your-production-secret-key-here -DATABASE_URL=/opt/datatools/data/config_groups.db -LOG_LEVEL=INFO -HOST=127.0.0.1 -PORT=5000 -WORKERS=4 - -# 外部服务 -CASSANDRA_HOSTS=10.0.1.100,10.0.1.101 -REDIS_HOSTS=10.0.2.100,10.0.2.101 -EOF - -# 7. 初始化数据库 -sudo -u $APP_USER $APP_DIR/venv/bin/python -c " -import sys -sys.path.insert(0, '$APP_DIR/app') -from app import init_database -init_database() -print('数据库初始化完成') -" - -# 8. 设置权限 -sudo chown -R $APP_USER:$APP_USER $APP_DIR -sudo chmod 600 $APP_DIR/.env -sudo chmod 755 $APP_DIR/app/app.py - -echo "应用部署完成: $APP_DIR" -``` - -### 3.3 Gunicorn配置 -```python -# gunicorn.conf.py -import os -import multiprocessing - -# 服务器socket -bind = f"{os.getenv('HOST', '127.0.0.1')}:{os.getenv('PORT', 5000)}" -backlog = 2048 - -# Worker进程 -workers = int(os.getenv('WORKERS', multiprocessing.cpu_count() * 2 + 1)) -worker_class = 'gevent' -worker_connections = 1000 -max_requests = 1000 -max_requests_jitter = 100 -preload_app = True - -# 超时设置 -timeout = 120 -keepalive = 2 -graceful_timeout = 30 - -# 日志配置 -accesslog = '/opt/datatools/logs/access.log' -errorlog = '/opt/datatools/logs/error.log' -loglevel = 'info' -access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s' - -# 进程命名 -proc_name = 'datatools-pro' - -# 用户和组 -user = 'datatools' -group = 'datatools' - -# 临时目录 -tmp_upload_dir = '/opt/datatools/tmp' - -# 启动时钩子 -def on_starting(server): - server.log.info("DataTools Pro 正在启动...") - -def when_ready(server): - server.log.info("DataTools Pro 启动完成") - -def on_exit(server): - server.log.info("DataTools Pro 正在关闭...") -``` - -### 3.4 Systemd服务配置 -```ini -# /etc/systemd/system/datatools-pro.service -[Unit] -Description=DataTools Pro - Enterprise Data Processing Platform -After=network.target -Wants=network.target - -[Service] -Type=notify -User=datatools -Group=datatools -RuntimeDirectory=datatools-pro -WorkingDirectory=/opt/datatools/app -Environment=PATH=/opt/datatools/venv/bin -EnvironmentFile=/opt/datatools/.env -ExecStart=/opt/datatools/venv/bin/gunicorn --config gunicorn.conf.py app:app -ExecReload=/bin/kill -s HUP $MAINPID -KillMode=mixed -TimeoutStopSec=30 -PrivateTmp=true -ProtectSystem=strict -ReadWritePaths=/opt/datatools -NoNewPrivileges=yes - -# 重启策略 -Restart=always -RestartSec=10 -StartLimitBurst=3 -StartLimitInterval=60 - -[Install] -WantedBy=multi-user.target -``` - -```bash -# 启用和启动服务 -sudo systemctl daemon-reload -sudo systemctl enable datatools-pro -sudo systemctl start datatools-pro -sudo systemctl status datatools-pro -``` - -### 3.5 Nginx反向代理配置 -```nginx -# /etc/nginx/sites-available/datatools-pro -upstream datatools_backend { - server 127.0.0.1:5000 fail_timeout=0; - # 如果有多个worker,可以添加多个server - # server 127.0.0.1:5001 fail_timeout=0; - # server 127.0.0.1:5002 fail_timeout=0; -} - -server { - listen 80; - listen [::]:80; - server_name datatools.yourdomain.com; - - # 重定向到HTTPS - return 301 https://$server_name$request_uri; -} - -server { - listen 443 ssl http2; - listen [::]:443 ssl http2; - server_name datatools.yourdomain.com; - - # SSL配置 - ssl_certificate /etc/ssl/certs/datatools.crt; - ssl_certificate_key /etc/ssl/private/datatools.key; - ssl_protocols TLSv1.2 TLSv1.3; - ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384; - ssl_prefer_server_ciphers off; - ssl_session_cache shared:SSL:10m; - ssl_session_timeout 10m; - - # 安全头 - add_header X-Frame-Options DENY; - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"; - - # 基础配置 - client_max_body_size 100M; - keepalive_timeout 65; - gzip on; - gzip_vary on; - gzip_types - text/plain - text/css - text/xml - text/javascript - application/javascript - application/xml+rss - application/json; - - # 静态文件缓存 - location /static/ { - alias /opt/datatools/app/static/; - expires 1y; - add_header Cache-Control "public, immutable"; - access_log off; - } - - # API接口 - location /api/ { - proxy_pass http://datatools_backend; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 120s; - proxy_buffering off; - } - - # 应用主体 - location / { - proxy_pass http://datatools_backend; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header X-Forwarded-Proto $scheme; - proxy_connect_timeout 30s; - proxy_send_timeout 30s; - proxy_read_timeout 30s; - } - - # 日志配置 - access_log /var/log/nginx/datatools-access.log; - error_log /var/log/nginx/datatools-error.log; -} -``` - -```bash -# 启用站点 -sudo ln -s /etc/nginx/sites-available/datatools-pro /etc/nginx/sites-enabled/ -sudo nginx -t -sudo systemctl reload nginx -``` - -## 4. 容器化部署 - -### 4.1 Dockerfile -```dockerfile -# Dockerfile -FROM python:3.9-slim - -# 设置工作目录 -WORKDIR /app - -# 安装系统依赖 -RUN apt-get update && apt-get install -y \ - gcc \ - g++ \ - && rm -rf /var/lib/apt/lists/* - -# 复制依赖文件 -COPY requirements.txt . - -# 安装Python依赖 -RUN pip install --no-cache-dir -r requirements.txt - -# 复制应用代码 -COPY . . - -# 创建非root用户 -RUN useradd -r -s /bin/false appuser && \ - chown -R appuser:appuser /app - -# 切换到非root用户 -USER appuser - -# 暴露端口 -EXPOSE 5000 - -# 健康检查 -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ - CMD curl -f http://localhost:5000/api/health || exit 1 - -# 启动命令 -CMD ["gunicorn", "--config", "gunicorn.conf.py", "app:app"] -``` - -### 4.2 Docker Compose配置 -```yaml -# docker-compose.yml -version: '3.8' - -services: - datatools-pro: - build: - context: . - dockerfile: Dockerfile - image: datatools-pro:latest - container_name: datatools-pro - restart: unless-stopped - ports: - - "5000:5000" - environment: - - DEBUG=False - - SECRET_KEY=${SECRET_KEY} - - DATABASE_URL=/app/data/config_groups.db - - LOG_LEVEL=INFO - - CASSANDRA_HOSTS=${CASSANDRA_HOSTS} - - REDIS_HOSTS=${REDIS_HOSTS} - volumes: - - ./data:/app/data - - ./logs:/app/logs - - ./backup:/app/backup - networks: - - datatools-network - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:5000/api/health"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 40s - - nginx: - image: nginx:alpine - container_name: datatools-nginx - restart: unless-stopped - ports: - - "80:80" - - "443:443" - volumes: - - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro - - ./nginx/conf.d:/etc/nginx/conf.d:ro - - ./ssl:/etc/ssl:ro - - ./logs/nginx:/var/log/nginx - depends_on: - - datatools-pro - networks: - - datatools-network - - redis: - image: redis:7-alpine - container_name: datatools-redis - restart: unless-stopped - ports: - - "6379:6379" - volumes: - - redis-data:/data - command: redis-server --appendonly yes - networks: - - datatools-network - -volumes: - redis-data: - driver: local - -networks: - datatools-network: - driver: bridge -``` - -### 4.3 环境变量配置 -```bash -# .env - Docker Compose环境变量 -COMPOSE_PROJECT_NAME=datatools-pro - -# 应用配置 -SECRET_KEY=your-super-secret-key-for-production -DEBUG=False -LOG_LEVEL=INFO - -# 外部服务 -CASSANDRA_HOSTS=cassandra-node1,cassandra-node2,cassandra-node3 -REDIS_HOSTS=redis-node1,redis-node2,redis-node3 - -# 数据库 -DATABASE_URL=/app/data/config_groups.db - -# 监控 -ENABLE_MONITORING=true -METRICS_PORT=9090 -``` - -### 4.4 容器化部署脚本 -```bash -#!/bin/bash -# deploy-docker.sh - Docker容器化部署脚本 - -set -e - -PROJECT_NAME="datatools-pro" -DOCKER_COMPOSE_FILE="docker-compose.yml" -ENV_FILE=".env" - -echo "开始Docker容器化部署..." - -# 1. 检查Docker环境 -if ! command -v docker &> /dev/null; then - echo "错误: Docker未安装" - exit 1 -fi - -if ! command -v docker-compose &> /dev/null; then - echo "错误: Docker Compose未安装" - exit 1 -fi - -# 2. 检查环境变量文件 -if [ ! -f "$ENV_FILE" ]; then - echo "创建环境变量文件: $ENV_FILE" - cp .env.example $ENV_FILE - echo "请编辑 $ENV_FILE 文件并重新运行部署脚本" - exit 1 -fi - -# 3. 创建必要目录 -mkdir -p {data,logs,backup,ssl,nginx/conf.d} - -# 4. 构建镜像 -echo "构建Docker镜像..." -docker-compose -f $DOCKER_COMPOSE_FILE build - -# 5. 停止旧容器 -echo "停止旧容器..." -docker-compose -f $DOCKER_COMPOSE_FILE down - -# 6. 启动新容器 -echo "启动新容器..." -docker-compose -f $DOCKER_COMPOSE_FILE up -d - -# 7. 等待容器启动 -echo "等待服务启动..." -sleep 30 - -# 8. 检查服务状态 -echo "检查服务状态..." -docker-compose -f $DOCKER_COMPOSE_FILE ps - -# 9. 健康检查 -echo "执行健康检查..." -if curl -f http://localhost/api/health > /dev/null 2>&1; then - echo "✅ 部署成功! 服务已启动" - echo "访问地址: http://localhost" -else - echo "❌ 部署失败! 服务未正常启动" - echo "查看日志: docker-compose logs" - exit 1 -fi - -# 10. 显示有用信息 -echo "" -echo "🚀 DataTools Pro 容器化部署完成!" -echo "" -echo "常用命令:" -echo " 查看日志: docker-compose logs -f" -echo " 重启服务: docker-compose restart" -echo " 停止服务: docker-compose down" -echo " 更新代码: git pull && docker-compose up -d --build" -echo "" -``` - -## 5. Kubernetes部署 - -### 5.1 Kubernetes资源清单 - -#### 5.1.1 ConfigMap配置 -```yaml -# k8s/configmap.yaml -apiVersion: v1 -kind: ConfigMap -metadata: - name: datatools-pro-config - namespace: datatools -data: - DEBUG: "False" - LOG_LEVEL: "INFO" - DATABASE_URL: "/app/data/config_groups.db" - CASSANDRA_HOSTS: "cassandra-service.database.svc.cluster.local" - REDIS_HOSTS: "redis-service.cache.svc.cluster.local" - WORKERS: "4" - HOST: "0.0.0.0" - PORT: "5000" -``` - -#### 5.1.2 Secret配置 -```yaml -# k8s/secret.yaml -apiVersion: v1 -kind: Secret -metadata: - name: datatools-pro-secret - namespace: datatools -type: Opaque -data: - SECRET_KEY: eW91ci1zdXBlci1zZWNyZXQta2V5LWZvci1wcm9kdWN0aW9u # base64 encoded -``` - -#### 5.1.3 PersistentVolume配置 -```yaml -# k8s/pvc.yaml -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: datatools-pro-data - namespace: datatools -spec: - accessModes: - - ReadWriteOnce - resources: - requests: - storage: 20Gi - storageClassName: fast-ssd -``` - -#### 5.1.4 Deployment配置 -```yaml -# k8s/deployment.yaml -apiVersion: apps/v1 -kind: Deployment -metadata: - name: datatools-pro - namespace: datatools - labels: - app: datatools-pro - version: v2.0.0 -spec: - replicas: 3 - selector: - matchLabels: - app: datatools-pro - template: - metadata: - labels: - app: datatools-pro - version: v2.0.0 - spec: - containers: - - name: datatools-pro - image: datatools-pro:2.0.0 - ports: - - containerPort: 5000 - name: http - env: - - name: SECRET_KEY - valueFrom: - secretKeyRef: - name: datatools-pro-secret - key: SECRET_KEY - envFrom: - - configMapRef: - name: datatools-pro-config - volumeMounts: - - name: data-volume - mountPath: /app/data - - name: logs-volume - mountPath: /app/logs - resources: - requests: - memory: "512Mi" - cpu: "250m" - limits: - memory: "2Gi" - cpu: "1000m" - livenessProbe: - httpGet: - path: /api/health - port: 5000 - initialDelaySeconds: 30 - periodSeconds: 30 - readinessProbe: - httpGet: - path: /api/health - port: 5000 - initialDelaySeconds: 5 - periodSeconds: 5 - securityContext: - runAsNonRoot: true - runAsUser: 1000 - readOnlyRootFilesystem: true - volumes: - - name: data-volume - persistentVolumeClaim: - claimName: datatools-pro-data - - name: logs-volume - emptyDir: {} - securityContext: - fsGroup: 1000 -``` - -#### 5.1.5 Service配置 -```yaml -# k8s/service.yaml -apiVersion: v1 -kind: Service -metadata: - name: datatools-pro-service - namespace: datatools - labels: - app: datatools-pro -spec: - selector: - app: datatools-pro - ports: - - port: 80 - targetPort: 5000 - protocol: TCP - name: http - type: ClusterIP -``` - -#### 5.1.6 Ingress配置 -```yaml -# k8s/ingress.yaml -apiVersion: networking.k8s.io/v1 -kind: Ingress -metadata: - name: datatools-pro-ingress - namespace: datatools - annotations: - kubernetes.io/ingress.class: nginx - cert-manager.io/cluster-issuer: letsencrypt-prod - nginx.ingress.kubernetes.io/ssl-redirect: "true" - nginx.ingress.kubernetes.io/proxy-body-size: "100m" - nginx.ingress.kubernetes.io/proxy-read-timeout: "120" -spec: - tls: - - hosts: - - datatools.yourdomain.com - secretName: datatools-pro-tls - rules: - - host: datatools.yourdomain.com - http: - paths: - - path: / - pathType: Prefix - backend: - service: - name: datatools-pro-service - port: - number: 80 -``` - -### 5.2 Kubernetes部署脚本 -```bash -#!/bin/bash -# deploy-k8s.sh - Kubernetes部署脚本 - -set -e - -NAMESPACE="datatools" -KUBECTL_CMD="kubectl" -KUSTOMIZE_DIR="k8s" - -echo "开始Kubernetes部署..." - -# 1. 检查kubectl -if ! command -v kubectl &> /dev/null; then - echo "错误: kubectl未安装" - exit 1 -fi - -# 2. 检查集群连接 -if ! kubectl cluster-info &> /dev/null; then - echo "错误: 无法连接到Kubernetes集群" - exit 1 -fi - -# 3. 创建命名空间 -echo "创建命名空间: $NAMESPACE" -kubectl create namespace $NAMESPACE --dry-run=client -o yaml | kubectl apply -f - - -# 4. 应用ConfigMap和Secret -echo "应用配置..." -kubectl apply -f $KUSTOMIZE_DIR/configmap.yaml -kubectl apply -f $KUSTOMIZE_DIR/secret.yaml - -# 5. 应用存储 -echo "应用存储配置..." -kubectl apply -f $KUSTOMIZE_DIR/pvc.yaml - -# 6. 等待PVC绑定 -echo "等待存储卷绑定..." -kubectl wait --for=condition=Bound pvc/datatools-pro-data -n $NAMESPACE --timeout=300s - -# 7. 应用Deployment -echo "部署应用..." -kubectl apply -f $KUSTOMIZE_DIR/deployment.yaml - -# 8. 等待Deployment就绪 -echo "等待应用就绪..." -kubectl wait --for=condition=Available deployment/datatools-pro -n $NAMESPACE --timeout=300s - -# 9. 应用Service -echo "创建服务..." -kubectl apply -f $KUSTOMIZE_DIR/service.yaml - -# 10. 应用Ingress -if [ -f "$KUSTOMIZE_DIR/ingress.yaml" ]; then - echo "创建Ingress..." - kubectl apply -f $KUSTOMIZE_DIR/ingress.yaml -fi - -# 11. 检查部署状态 -echo "检查部署状态..." -kubectl get pods -n $NAMESPACE -l app=datatools-pro -kubectl get svc -n $NAMESPACE -l app=datatools-pro - -# 12. 显示访问信息 -echo "" -echo "🚀 Kubernetes部署完成!" -echo "" -echo "查看Pod状态: kubectl get pods -n $NAMESPACE" -echo "查看日志: kubectl logs -f deployment/datatools-pro -n $NAMESPACE" -echo "端口转发测试: kubectl port-forward service/datatools-pro-service 8080:80 -n $NAMESPACE" -echo "" - -if [ -f "$KUSTOMIZE_DIR/ingress.yaml" ]; then - INGRESS_HOST=$(kubectl get ingress datatools-pro-ingress -n $NAMESPACE -o jsonpath='{.spec.rules[0].host}') - echo "访问地址: https://$INGRESS_HOST" -fi -``` - -### 5.3 HorizontalPodAutoscaler配置 -```yaml -# k8s/hpa.yaml -apiVersion: autoscaling/v2 -kind: HorizontalPodAutoscaler -metadata: - name: datatools-pro-hpa - namespace: datatools -spec: - scaleTargetRef: - apiVersion: apps/v1 - kind: Deployment - name: datatools-pro - minReplicas: 2 - maxReplicas: 10 - metrics: - - type: Resource - resource: - name: cpu - target: - type: Utilization - averageUtilization: 70 - - type: Resource - resource: - name: memory - target: - type: Utilization - averageUtilization: 80 - behavior: - scaleDown: - stabilizationWindowSeconds: 300 - policies: - - type: Percent - value: 10 - periodSeconds: 60 - scaleUp: - stabilizationWindowSeconds: 60 - policies: - - type: Percent - value: 50 - periodSeconds: 60 -``` - -## 6. 监控和日志 - -### 6.1 应用监控配置 -```python -# monitoring.py - 应用监控模块 -from prometheus_client import Counter, Histogram, Gauge, generate_latest, CONTENT_TYPE_LATEST -from flask import Response -import time -import psutil -import sqlite3 - -# 定义监控指标 -REQUEST_COUNT = Counter('datatools_requests_total', 'Total requests', ['method', 'endpoint', 'status']) -REQUEST_LATENCY = Histogram('datatools_request_duration_seconds', 'Request latency') -ACTIVE_CONNECTIONS = Gauge('datatools_active_connections', 'Active database connections') -QUERY_EXECUTION_TIME = Histogram('datatools_query_duration_seconds', 'Query execution time', ['query_type']) - -# 系统资源指标 -SYSTEM_CPU_USAGE = Gauge('datatools_system_cpu_usage_percent', 'System CPU usage') -SYSTEM_MEMORY_USAGE = Gauge('datatools_system_memory_usage_percent', 'System memory usage') -DATABASE_SIZE = Gauge('datatools_database_size_bytes', 'Database file size') - -def init_monitoring(app): - """初始化监控""" - - @app.before_request - def before_request(): - """请求前处理""" - g.start_time = time.time() - - @app.after_request - def after_request(response): - """请求后处理""" - if hasattr(g, 'start_time'): - duration = time.time() - g.start_time - REQUEST_LATENCY.observe(duration) - REQUEST_COUNT.labels( - method=request.method, - endpoint=request.endpoint or 'unknown', - status=response.status_code - ).inc() - - return response - - @app.route('/metrics') - def metrics(): - """Prometheus指标端点""" - # 更新系统指标 - update_system_metrics() - - return Response(generate_latest(), mimetype=CONTENT_TYPE_LATEST) - -def update_system_metrics(): - """更新系统指标""" - # CPU使用率 - cpu_percent = psutil.cpu_percent(interval=1) - SYSTEM_CPU_USAGE.set(cpu_percent) - - # 内存使用率 - memory = psutil.virtual_memory() - SYSTEM_MEMORY_USAGE.set(memory.percent) - - # 数据库大小 - try: - import os - db_path = 'config_groups.db' - if os.path.exists(db_path): - db_size = os.path.getsize(db_path) - DATABASE_SIZE.set(db_size) - except Exception: - pass - -def record_query_time(query_type, duration): - """记录查询执行时间""" - QUERY_EXECUTION_TIME.labels(query_type=query_type).observe(duration) -``` - -### 6.2 日志配置 -```python -# logging_config.py - 日志配置 -import logging -import logging.handlers -import os -from datetime import datetime - -def setup_logging(app): - """设置应用日志""" - - # 创建日志目录 - log_dir = app.config.get('LOG_DIR', 'logs') - os.makedirs(log_dir, exist_ok=True) - - # 配置日志格式 - formatter = logging.Formatter( - '%(asctime)s [%(levelname)s] %(name)s: %(message)s' - ) - - # 应用日志 - app_handler = logging.handlers.RotatingFileHandler( - os.path.join(log_dir, 'datatools.log'), - maxBytes=10*1024*1024, # 10MB - backupCount=10 - ) - app_handler.setFormatter(formatter) - app_handler.setLevel(logging.INFO) - - # 错误日志 - error_handler = logging.handlers.RotatingFileHandler( - os.path.join(log_dir, 'error.log'), - maxBytes=10*1024*1024, # 10MB - backupCount=5 - ) - error_handler.setFormatter(formatter) - error_handler.setLevel(logging.ERROR) - - # 访问日志 - access_handler = logging.handlers.RotatingFileHandler( - os.path.join(log_dir, 'access.log'), - maxBytes=10*1024*1024, # 10MB - backupCount=10 - ) - access_formatter = logging.Formatter( - '%(asctime)s %(remote_addr)s "%(method)s %(url)s" %(status_code)s %(response_size)s "%(user_agent)s"' - ) - access_handler.setFormatter(access_formatter) - - # 配置Flask应用日志 - app.logger.addHandler(app_handler) - app.logger.addHandler(error_handler) - app.logger.setLevel(logging.INFO) - - # 配置访问日志 - access_logger = logging.getLogger('werkzeug') - access_logger.addHandler(access_handler) - - # 配置第三方库日志级别 - logging.getLogger('cassandra').setLevel(logging.WARNING) - logging.getLogger('redis').setLevel(logging.WARNING) - logging.getLogger('urllib3').setLevel(logging.WARNING) -``` - -### 6.3 Prometheus配置 -```yaml -# prometheus.yml -global: - scrape_interval: 15s - evaluation_interval: 15s - -rule_files: - - "datatools_rules.yml" - -scrape_configs: - - job_name: 'datatools-pro' - static_configs: - - targets: ['localhost:5000'] - metrics_path: '/metrics' - scrape_interval: 30s - scrape_timeout: 10s - -alerting: - alertmanagers: - - static_configs: - - targets: - - alertmanager:9093 -``` - -### 6.4 Grafana仪表板配置 -```json -{ - "dashboard": { - "id": null, - "title": "DataTools Pro Monitoring", - "tags": ["datatools", "monitoring"], - "timezone": "browser", - "panels": [ - { - "id": 1, - "title": "Request Rate", - "type": "graph", - "targets": [ - { - "expr": "rate(datatools_requests_total[5m])", - "legendFormat": "{{method}} {{endpoint}}" - } - ] - }, - { - "id": 2, - "title": "Request Latency", - "type": "graph", - "targets": [ - { - "expr": "histogram_quantile(0.95, datatools_request_duration_seconds_bucket)", - "legendFormat": "95th percentile" - }, - { - "expr": "histogram_quantile(0.50, datatools_request_duration_seconds_bucket)", - "legendFormat": "50th percentile" - } - ] - }, - { - "id": 3, - "title": "System Resources", - "type": "graph", - "targets": [ - { - "expr": "datatools_system_cpu_usage_percent", - "legendFormat": "CPU Usage %" - }, - { - "expr": "datatools_system_memory_usage_percent", - "legendFormat": "Memory Usage %" - } - ] - }, - { - "id": 4, - "title": "Query Performance", - "type": "graph", - "targets": [ - { - "expr": "histogram_quantile(0.95, datatools_query_duration_seconds_bucket)", - "legendFormat": "{{query_type}} 95th percentile" - } - ] - } - ], - "time": { - "from": "now-1h", - "to": "now" - }, - "refresh": "30s" - } -} -``` - -## 7. 备份和恢复 - -### 7.1 数据备份脚本 -```bash -#!/bin/bash -# backup.sh - 数据备份脚本 - -set -e - -# 配置变量 -BACKUP_DIR="/opt/datatools/backup" -DATA_DIR="/opt/datatools/data" -LOG_DIR="/opt/datatools/logs" -RETENTION_DAYS=30 -DATE=$(date +%Y%m%d_%H%M%S) -BACKUP_NAME="datatools_backup_$DATE" - -echo "开始数据备份: $BACKUP_NAME" - -# 创建备份目录 -mkdir -p $BACKUP_DIR/$BACKUP_NAME - -# 1. 备份SQLite数据库 -echo "备份SQLite数据库..." -if [ -f "$DATA_DIR/config_groups.db" ]; then - sqlite3 $DATA_DIR/config_groups.db ".backup $BACKUP_DIR/$BACKUP_NAME/config_groups.db" - sqlite3 $DATA_DIR/config_groups.db ".dump" > $BACKUP_DIR/$BACKUP_NAME/config_groups.sql -fi - -# 2. 备份配置文件 -echo "备份配置文件..." -cp -r /opt/datatools/app/config.py $BACKUP_DIR/$BACKUP_NAME/ 2>/dev/null || true -cp -r /opt/datatools/.env $BACKUP_DIR/$BACKUP_NAME/ 2>/dev/null || true - -# 3. 备份日志文件(最近7天) -echo "备份日志文件..." -find $LOG_DIR -name "*.log" -mtime -7 -exec cp {} $BACKUP_DIR/$BACKUP_NAME/ \; 2>/dev/null || true - -# 4. 创建备份信息文件 -cat > $BACKUP_DIR/$BACKUP_NAME/backup_info.txt << EOF -备份时间: $(date) -备份版本: DataTools Pro 2.0 -系统信息: $(uname -a) -Python版本: $(python3 --version) -数据库大小: $(du -h $DATA_DIR/config_groups.db 2>/dev/null | cut -f1 || echo "N/A") -备份大小: $(du -sh $BACKUP_DIR/$BACKUP_NAME | cut -f1) -EOF - -# 5. 压缩备份 -echo "压缩备份文件..." -cd $BACKUP_DIR -tar -czf $BACKUP_NAME.tar.gz $BACKUP_NAME -rm -rf $BACKUP_NAME - -# 6. 清理旧备份 -echo "清理旧备份..." -find $BACKUP_DIR -name "datatools_backup_*.tar.gz" -mtime +$RETENTION_DAYS -delete - -# 7. 验证备份 -if [ -f "$BACKUP_DIR/$BACKUP_NAME.tar.gz" ]; then - BACKUP_SIZE=$(du -h $BACKUP_DIR/$BACKUP_NAME.tar.gz | cut -f1) - echo "✅ 备份完成: $BACKUP_NAME.tar.gz ($BACKUP_SIZE)" -else - echo "❌ 备份失败!" - exit 1 -fi - -# 8. 可选: 上传到远程存储 -if [ -n "$BACKUP_REMOTE_PATH" ]; then - echo "上传备份到远程存储..." - # rsync -avz $BACKUP_DIR/$BACKUP_NAME.tar.gz $BACKUP_REMOTE_PATH/ - # aws s3 cp $BACKUP_DIR/$BACKUP_NAME.tar.gz s3://your-backup-bucket/ -fi - -echo "备份脚本执行完成" -``` - -### 7.2 数据恢复脚本 -```bash -#!/bin/bash -# restore.sh - 数据恢复脚本 - -set -e - -if [ $# -eq 0 ]; then - echo "用法: $0 " - echo "示例: $0 /opt/datatools/backup/datatools_backup_20240805_100000.tar.gz" - exit 1 -fi - -BACKUP_FILE="$1" -DATA_DIR="/opt/datatools/data" -RESTORE_DIR="/tmp/datatools_restore_$$" - -echo "开始数据恢复: $BACKUP_FILE" - -# 1. 验证备份文件 -if [ ! -f "$BACKUP_FILE" ]; then - echo "错误: 备份文件不存在: $BACKUP_FILE" - exit 1 -fi - -# 2. 停止服务 -echo "停止DataTools Pro服务..." -sudo systemctl stop datatools-pro || true - -# 3. 备份当前数据 -echo "备份当前数据..." -mkdir -p $DATA_DIR.bak -cp -r $DATA_DIR/* $DATA_DIR.bak/ 2>/dev/null || true - -# 4. 解压备份文件 -echo "解压备份文件..." -mkdir -p $RESTORE_DIR -cd $RESTORE_DIR -tar -xzf $BACKUP_FILE - -# 5. 恢复数据库 -echo "恢复数据库..." -BACKUP_DB=$(find $RESTORE_DIR -name "config_groups.db" | head -1) -if [ -f "$BACKUP_DB" ]; then - cp $BACKUP_DB $DATA_DIR/config_groups.db - chown datatools:datatools $DATA_DIR/config_groups.db - chmod 644 $DATA_DIR/config_groups.db - echo "✅ 数据库恢复完成" -else - echo "❌ 未找到数据库备份文件" -fi - -# 6. 恢复配置文件 -echo "恢复配置文件..." -BACKUP_CONFIG=$(find $RESTORE_DIR -name "config.py" | head -1) -if [ -f "$BACKUP_CONFIG" ]; then - cp $BACKUP_CONFIG /opt/datatools/app/config.py - chown datatools:datatools /opt/datatools/app/config.py - echo "✅ 配置文件恢复完成" -fi - -BACKUP_ENV=$(find $RESTORE_DIR -name ".env" | head -1) -if [ -f "$BACKUP_ENV" ]; then - cp $BACKUP_ENV /opt/datatools/.env - chown datatools:datatools /opt/datatools/.env - chmod 600 /opt/datatools/.env - echo "✅ 环境变量文件恢复完成" -fi - -# 7. 验证数据库完整性 -echo "验证数据库完整性..." -if sqlite3 $DATA_DIR/config_groups.db "PRAGMA integrity_check;" | grep -q "ok"; then - echo "✅ 数据库完整性检查通过" -else - echo "❌ 数据库完整性检查失败" - echo "恢复原始数据..." - cp -r $DATA_DIR.bak/* $DATA_DIR/ - exit 1 -fi - -# 8. 启动服务 -echo "启动DataTools Pro服务..." -sudo systemctl start datatools-pro - -# 9. 等待服务启动 -echo "等待服务启动..." -sleep 10 - -# 10. 健康检查 -if curl -f http://localhost:5000/api/health > /dev/null 2>&1; then - echo "✅ 恢复完成! 服务正常运行" - rm -rf $RESTORE_DIR - rm -rf $DATA_DIR.bak -else - echo "❌ 服务启动失败,回滚到原始数据" - sudo systemctl stop datatools-pro - rm -rf $DATA_DIR/* - cp -r $DATA_DIR.bak/* $DATA_DIR/ - sudo systemctl start datatools-pro - rm -rf $RESTORE_DIR - exit 1 -fi - -echo "数据恢复脚本执行完成" -``` - -### 7.3 自动化备份Cron任务 -```bash -# 添加定时备份任务 -# crontab -e - -# 每天凌晨2点执行备份 -0 2 * * * /opt/datatools/scripts/backup.sh >> /opt/datatools/logs/backup.log 2>&1 - -# 每周日凌晨3点清理旧日志 -0 3 * * 0 find /opt/datatools/logs -name "*.log.*" -mtime +7 -delete - -# 每月1号检查数据库完整性 -0 4 1 * * sqlite3 /opt/datatools/data/config_groups.db "PRAGMA integrity_check;" >> /opt/datatools/logs/db_check.log 2>&1 -``` - ---- - -**版本**: v1.0 -**更新日期**: 2024-08-05 -**维护者**: DataTools Pro Team \ No newline at end of file diff --git a/docs/frontend-architecture.md b/docs/frontend-architecture.md deleted file mode 100644 index 6c1d376..0000000 --- a/docs/frontend-architecture.md +++ /dev/null @@ -1,1742 +0,0 @@ -# DataTools Pro 前端模块化设计文档 - -## 1. 前端架构概述 - -### 1.1 设计理念 -DataTools Pro前端采用现代化的模块化架构,基于ES6模块系统构建,追求高内聚、低耦合的设计原则,提供可维护、可扩展的前端解决方案。 - -### 1.2 技术栈 -``` -前端技术栈: -├── 核心技术 -│ ├── 原生JavaScript (ES6+) -│ ├── ES6 Modules (import/export) -│ └── 现代浏览器API (Fetch, Promise, async/await) -├── UI框架 -│ ├── Bootstrap 5.1.3 (响应式UI框架) -│ ├── Font Awesome 6.0.0 (图标库) -│ └── 原生CSS3 (自定义样式和动画) -└── 开发模式 - ├── 模块化开发 - ├── 组件化设计 - └── 事件驱动架构 -``` - -### 1.3 架构优势 -- **无构建依赖**: 直接在浏览器中运行,无需复杂的构建工具 -- **模块化设计**: 清晰的职责分离,便于维护和测试 -- **轻量级**: 没有框架包袱,性能优异 -- **现代化**: 使用最新的JavaScript特性和API -- **兼容性**: 支持现代浏览器(Chrome 61+, Firefox 60+, Safari 10.1+) - -## 2. 模块架构图 - -``` -DataTools Pro 前端模块架构 -┌─────────────────────────────────────────────────────────────┐ -│ 应用层 (App Layer) │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ app-main.js │ │ -│ │ 主应用入口和协调器 │ │ -│ │ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────┐ │ │ -│ │ │ 应用初始化 │ │ 生命周期 │ │ 全局事件管理 │ │ │ -│ │ │ 管理 │ │ 管理 │ │ │ │ │ -│ │ └─────────────┘ └─────────────┘ └─────────────────────┘ │ │ -│ └─────────────────────────────────────────────────────────┘ │ -├─────────────────────────────────────────────────────────────┤ -│ 核心模块层 (Core Modules) │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ -│ │ config.js │ │ utils.js │ │ api.js │ │ -│ │ 配置管理 │ │ 工具函数库 │ │ HTTP客户端 │ │ -│ │ ·APP_INFO │ │ ·escapeHtml │ │ ·CassandraAPI │ │ -│ │ ·API端点 │ │ ·formatDate │ │ ·RedisAPI │ │ -│ │ ·UI配置 │ │ ·debounce │ │ ·统一错误处理 │ │ -│ └─────────────┘ └─────────────┘ └─────────────────────────┘ │ -│ ┌─────────────┐ ┌─────────────────────────────────────────┐ │ -│ │ ui.js │ │ navigation.js │ │ -│ │ UI组件库 │ │ 导航管理模块 │ │ -│ │ ·AlertMgr │ │ ·面包屑导航 ·键盘快捷键 │ │ -│ │ ·ModalMgr │ │ ·活跃状态管理 ·程序化导航 │ │ -│ │ ·Pagination │ │ ·页面标题管理 │ │ -│ └─────────────┘ └─────────────────────────────────────────┘ │ -├─────────────────────────────────────────────────────────────┤ -│ 页面层 (Page Layer) │ -│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────────────┐ │ -│ │ index.html │ │db_compare. │ │ redis_compare.html │ │ -│ │ 首页模块 │ │html │ │ Redis比对模块 │ │ -│ │ ·工具展示 │ │Cassandra │ │ ·集群配置管理 │ │ -│ │ ·统计信息 │ │比对模块 │ │ ·随机采样查询 │ │ -│ │ ·导航入口 │ │·查询配置 │ │ ·指定Key查询 │ │ -│ └─────────────┘ │·分表查询 │ │ ·数据类型比对 │ │ -│ │·多主键查询 │ └─────────────────────────┘ │ -│ └─────────────┘ │ -└─────────────────────────────────────────────────────────────┘ -``` - -## 3. 核心模块详解 - -### 3.1 主应用模块 (app-main.js) - -#### 3.1.1 模块职责 -- **应用初始化**: 统一管理各模块启动和配置 -- **生命周期管理**: 处理应用启动、运行、销毁周期 -- **全局事件管理**: 统一处理全局事件和错误 -- **模块协调**: 协调各个功能模块之间的交互 - -#### 3.1.2 核心类设计 -```javascript -/** - * 主应用程序类 - */ -class DataToolsApp { - constructor() { - this.config = config; // 配置管理 - this.utils = utils; // 工具函数 - this.api = apiManager; // API管理 - this.navigation = navigationManager; // 导航管理 - this.ui = { // UI组件集合 - alert: alertManager, - modal: modalManager, - loading: loadingIndicator, - confirm: confirmDialog, - prompt: promptDialog - }; - this.isInitialized = false; - this.currentTool = null; - } - - // 核心方法 - async init() // 应用初始化 - checkDependencies() // 依赖检查 - initUI() // UI初始化 - bindGlobalEvents() // 全局事件绑定 - detectCurrentTool() // 当前工具检测 - destroy() // 应用销毁 -} -``` - -#### 3.1.3 初始化流程 -```javascript -// 应用初始化流程 -async function initApplication() { - try { - console.log('DataTools Pro 正在初始化...'); - - // 1. 检查浏览器兼容性和依赖 - checkDependencies(); - - // 2. 初始化UI组件 - initUI(); - - // 3. 启用导航和快捷键 - navigation.enableKeyboardShortcuts(); - - // 4. 绑定全局事件 - bindGlobalEvents(); - - // 5. 检测当前工具类型 - detectCurrentTool(); - - console.log('应用程序初始化完成'); - - // 6. 显示欢迎消息 - showWelcomeMessage(); - - } catch (error) { - console.error('应用程序初始化失败:', error); - ui.alert.error('应用程序初始化失败,请刷新页面重试'); - } -} -``` - -### 3.2 配置管理模块 (config.js) - -#### 3.2.1 模块结构 -```javascript -// 应用基础信息 -export const APP_INFO = { - name: 'DataTools Pro', - version: '2.0.0', - description: '企业级数据处理与比对工具平台' -}; - -// API端点配置 -export const API_ENDPOINTS = { - // Cassandra相关API - CASSANDRA: { - DEFAULT_CONFIG: '/api/default-config', - QUERY: '/api/query', - SHARDING_QUERY: '/api/sharding-query' - }, - - // Redis相关API - REDIS: { - COMPARE: '/api/redis/compare', - CONFIG: '/api/redis/config' - }, - - // 配置管理API - CONFIG_GROUPS: { - LIST: '/api/config-groups', - CREATE: '/api/config-groups', - GET: (id) => `/api/config-groups/${id}`, - DELETE: (id) => `/api/config-groups/${id}` - }, - - // 历史记录API - QUERY_HISTORY: { - LIST: '/api/query-history', - CREATE: '/api/query-history', - GET: (id) => `/api/query-history/${id}`, - RESULTS: (id) => `/api/query-history/${id}/results`, - DELETE: (id) => `/api/query-history/${id}` - }, - - // 日志管理API - QUERY_LOGS: { - LIST: '/api/query-logs', - HISTORY: (id) => `/api/query-logs/history/${id}`, - CLEAR: '/api/query-logs' - } -}; - -// UI配置 -export const UI_CONFIG = { - PAGINATION: { - DEFAULT_PAGE_SIZE: 10, - MAX_PAGE_SIZE: 100, - SHOW_SIZE_CHANGER: true - }, - - ALERT: { - AUTO_HIDE_DELAY: 3000, - MAX_ALERTS: 5 - }, - - LOADING: { - MIN_DISPLAY_TIME: 500, - TIMEOUT: 30000 - }, - - ANIMATION: { - DURATION: 300, - EASING: 'ease-in-out' - } -}; - -// 工具配置 -export const TOOLS_CONFIG = { - CASSANDRA: { - name: 'Cassandra数据比对工具', - url: '/cassandra-compare', - icon: 'fas fa-database', - description: '企业级Cassandra数据库比对分析' - }, - - REDIS: { - name: 'Redis集群比对工具', - url: '/redis-compare', - icon: 'fab fa-redis', - description: '专业的Redis集群数据比对分析' - } -}; -``` - -#### 3.2.2 配置管理类 -```javascript -class ConfigManager { - constructor() { - this.cache = new Map(); - this.listeners = new Map(); - } - - // 获取配置值 - get(key, defaultValue = null) { - const keys = key.split('.'); - let value = this; - - for (const k of keys) { - value = value[k]; - if (value === undefined) { - return defaultValue; - } - } - - return value; - } - - // 设置配置值 - set(key, value) { - this.cache.set(key, value); - this.notifyListeners(key, value); - } - - // 监听配置变更 - onChange(key, callback) { - if (!this.listeners.has(key)) { - this.listeners.set(key, new Set()); - } - this.listeners.get(key).add(callback); - } - - // 通知监听器 - notifyListeners(key, value) { - if (this.listeners.has(key)) { - this.listeners.get(key).forEach(callback => { - callback(value, key); - }); - } - } -} -``` - -### 3.3 工具函数模块 (utils.js) - -#### 3.3.1 核心工具函数 -```javascript -/** - * HTML转义,防止XSS攻击 - */ -export function escapeHtml(text) { - const div = document.createElement('div'); - div.textContent = text; - return div.innerHTML; -} - -/** - * 日期格式化 - */ -export function formatDate(date, format = 'YYYY-MM-DD HH:mm:ss') { - const d = new Date(date); - const formatMap = { - 'YYYY': d.getFullYear(), - 'MM': String(d.getMonth() + 1).padStart(2, '0'), - 'DD': String(d.getDate()).padStart(2, '0'), - 'HH': String(d.getHours()).padStart(2, '0'), - 'mm': String(d.getMinutes()).padStart(2, '0'), - 'ss': String(d.getSeconds()).padStart(2, '0') - }; - - return format.replace(/YYYY|MM|DD|HH|mm|ss/g, match => formatMap[match]); -} - -/** - * 防抖函数 - */ -export function debounce(func, wait, immediate = false) { - let timeout; - return function executedFunction(...args) { - const later = () => { - timeout = null; - if (!immediate) func.apply(this, args); - }; - const callNow = immediate && !timeout; - clearTimeout(timeout); - timeout = setTimeout(later, wait); - if (callNow) func.apply(this, args); - }; -} - -/** - * 节流函数 - */ -export function throttle(func, limit) { - let inThrottle; - return function(...args) { - if (!inThrottle) { - func.apply(this, args); - inThrottle = true; - setTimeout(() => inThrottle = false, limit); - } - }; -} - -/** - * 深度克隆对象 - */ -export function deepClone(obj) { - if (obj === null || typeof obj !== "object") { - return obj; - } - - if (obj instanceof Date) { - return new Date(obj.getTime()); - } - - if (obj instanceof Array) { - return obj.map(item => deepClone(item)); - } - - if (typeof obj === "object") { - const clonedObj = {}; - for (let key in obj) { - if (obj.hasOwnProperty(key)) { - clonedObj[key] = deepClone(obj[key]); - } - } - return clonedObj; - } -} - -/** - * 剪贴板操作 - */ -export const clipboard = { - async copy(text) { - try { - await navigator.clipboard.writeText(text); - return true; - } catch (err) { - // 降级方案 - const textArea = document.createElement('textarea'); - textArea.value = text; - document.body.appendChild(textArea); - textArea.select(); - document.execCommand('copy'); - document.body.removeChild(textArea); - return true; - } - }, - - async paste() { - try { - return await navigator.clipboard.readText(); - } catch (err) { - console.warn('无法访问剪贴板'); - return ''; - } - } -}; - -/** - * 文件操作工具 - */ -export const fileUtils = { - // 下载文件 - download(data, filename, type = 'text/plain') { - const blob = new Blob([data], { type }); - const url = URL.createObjectURL(blob); - const link = document.createElement('a'); - link.href = url; - link.download = filename; - document.body.appendChild(link); - link.click(); - document.body.removeChild(link); - URL.revokeObjectURL(url); - }, - - // 读取文件 - async readFile(file) { - return new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = e => resolve(e.target.result); - reader.onerror = reject; - reader.readAsText(file); - }); - } -}; -``` - -#### 3.3.2 数据处理工具 -```javascript -/** - * 数据验证工具 - */ -export const validator = { - // 非空验证 - required(value, message = '此字段不能为空') { - if (!value || value.toString().trim() === '') { - throw new Error(message); - } - return true; - }, - - // 邮箱验证 - email(value, message = '请输入有效的邮箱地址') { - const pattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; - if (!pattern.test(value)) { - throw new Error(message); - } - return true; - }, - - // 数字验证 - number(value, min = null, max = null, message = '请输入有效的数字') { - const num = Number(value); - if (isNaN(num)) { - throw new Error(message); - } - if (min !== null && num < min) { - throw new Error(`数值不能小于${min}`); - } - if (max !== null && num > max) { - throw new Error(`数值不能大于${max}`); - } - return true; - }, - - // JSON验证 - json(value, message = '请输入有效的JSON格式') { - try { - JSON.parse(value); - return true; - } catch (e) { - throw new Error(message); - } - } -}; - -/** - * 字符串处理工具 - */ -export const stringUtils = { - // 首字母大写 - capitalize(str) { - return str.charAt(0).toUpperCase() + str.slice(1); - }, - - // 驼峰命名转换 - camelCase(str) { - return str.replace(/-([a-z])/g, (match, letter) => letter.toUpperCase()); - }, - - // 截断字符串 - truncate(str, maxLength, suffix = '...') { - if (str.length <= maxLength) return str; - return str.substring(0, maxLength - suffix.length) + suffix; - }, - - // 格式化文件大小 - formatBytes(bytes, decimals = 2) { - if (bytes === 0) return '0 Bytes'; - const k = 1024; - const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; - const i = Math.floor(Math.log(bytes) / Math.log(k)); - return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i]; - } -}; -``` - -### 3.4 API管理模块 (api.js) - -#### 3.4.1 HTTP客户端封装 -```javascript -/** - * HTTP客户端类 - */ -class HttpClient { - constructor(baseURL = '', options = {}) { - this.baseURL = baseURL; - this.defaultOptions = { - headers: { - 'Content-Type': 'application/json', - 'Accept': 'application/json' - }, - credentials: 'same-origin', - ...options - }; - - this.interceptors = { - request: [], - response: [] - }; - } - - // 添加请求拦截器 - addRequestInterceptor(interceptor) { - this.interceptors.request.push(interceptor); - } - - // 添加响应拦截器 - addResponseInterceptor(interceptor) { - this.interceptors.response.push(interceptor); - } - - // 执行请求 - async request(url, options = {}) { - const fullUrl = this.baseURL + url; - let config = { ...this.defaultOptions, ...options }; - - // 执行请求拦截器 - for (const interceptor of this.interceptors.request) { - config = await interceptor(config); - } - - try { - let response = await fetch(fullUrl, config); - - // 执行响应拦截器 - for (const interceptor of this.interceptors.response) { - response = await interceptor(response); - } - - // 处理HTTP错误状态 - if (!response.ok) { - throw new Error(`HTTP ${response.status}: ${response.statusText}`); - } - - // 解析JSON响应 - const data = await response.json(); - return data; - - } catch (error) { - console.error('HTTP请求失败:', error); - throw error; - } - } - - // HTTP方法快捷方式 - get(url, params = {}) { - const queryString = new URLSearchParams(params).toString(); - const fullUrl = queryString ? `${url}?${queryString}` : url; - return this.request(fullUrl, { method: 'GET' }); - } - - post(url, data = {}) { - return this.request(url, { - method: 'POST', - body: JSON.stringify(data) - }); - } - - put(url, data = {}) { - return this.request(url, { - method: 'PUT', - body: JSON.stringify(data) - }); - } - - delete(url) { - return this.request(url, { method: 'DELETE' }); - } -} -``` - -#### 3.4.2 API管理器 -```javascript -/** - * API管理器类 - */ -class APIManager { - constructor() { - this.httpClient = new HttpClient(); - this.setupInterceptors(); - } - - // 设置拦截器 - setupInterceptors() { - // 请求拦截器 - 添加时间戳和请求ID - this.httpClient.addRequestInterceptor(async (config) => { - config.headers['X-Request-ID'] = this.generateRequestId(); - config.headers['X-Timestamp'] = Date.now(); - return config; - }); - - // 响应拦截器 - 统一错误处理 - this.httpClient.addResponseInterceptor(async (response) => { - const data = await response.json(); - - if (!data.success) { - throw new APIError(data.error?.message || '请求失败', data.error?.code); - } - - return data; - }); - } - - // 生成请求ID - generateRequestId() { - return 'req_' + Date.now() + '_' + Math.random().toString(36).substr(2, 9); - } - - // Cassandra API - get cassandra() { - return { - getDefaultConfig: () => - this.httpClient.get(API_ENDPOINTS.CASSANDRA.DEFAULT_CONFIG), - - executeQuery: (config) => - this.httpClient.post(API_ENDPOINTS.CASSANDRA.QUERY, config), - - executeShardingQuery: (config) => - this.httpClient.post(API_ENDPOINTS.CASSANDRA.SHARDING_QUERY, config) - }; - } - - // Redis API - get redis() { - return { - compareData: (config) => - this.httpClient.post(API_ENDPOINTS.REDIS.COMPARE, config) - }; - } - - // 配置组API - get configGroups() { - return { - list: () => - this.httpClient.get(API_ENDPOINTS.CONFIG_GROUPS.LIST), - - create: (config) => - this.httpClient.post(API_ENDPOINTS.CONFIG_GROUPS.CREATE, config), - - get: (id) => - this.httpClient.get(API_ENDPOINTS.CONFIG_GROUPS.GET(id)), - - delete: (id) => - this.httpClient.delete(API_ENDPOINTS.CONFIG_GROUPS.DELETE(id)) - }; - } - - // 查询历史API - get queryHistory() { - return { - list: (params = {}) => - this.httpClient.get(API_ENDPOINTS.QUERY_HISTORY.LIST, params), - - create: (history) => - this.httpClient.post(API_ENDPOINTS.QUERY_HISTORY.CREATE, history), - - get: (id) => - this.httpClient.get(API_ENDPOINTS.QUERY_HISTORY.GET(id)), - - getResults: (id) => - this.httpClient.get(API_ENDPOINTS.QUERY_HISTORY.RESULTS(id)), - - delete: (id) => - this.httpClient.delete(API_ENDPOINTS.QUERY_HISTORY.DELETE(id)) - }; - } - - // 日志API - get queryLogs() { - return { - list: (params = {}) => - this.httpClient.get(API_ENDPOINTS.QUERY_LOGS.LIST, params), - - getHistory: (id) => - this.httpClient.get(API_ENDPOINTS.QUERY_LOGS.HISTORY(id)), - - clear: () => - this.httpClient.delete(API_ENDPOINTS.QUERY_LOGS.CLEAR) - }; - } -} - -/** - * API错误类 - */ -class APIError extends Error { - constructor(message, code = 'UNKNOWN_ERROR') { - super(message); - this.name = 'APIError'; - this.code = code; - } -} -``` - -### 3.5 UI组件模块 (ui.js) - -#### 3.5.1 提示管理器 -```javascript -/** - * 提示信息管理器 - */ -class AlertManager { - constructor() { - this.alerts = []; - this.container = null; - this.init(); - } - - init() { - // 创建提示容器 - this.container = document.createElement('div'); - this.container.className = 'alert-container'; - this.container.style.cssText = ` - position: fixed; - top: 20px; - right: 20px; - z-index: 9999; - max-width: 400px; - `; - document.body.appendChild(this.container); - } - - show(type, message, autoHide = UI_CONFIG.ALERT.AUTO_HIDE_DELAY) { - const alertId = 'alert_' + Date.now(); - const alertElement = this.createAlertElement(alertId, type, message); - - this.container.appendChild(alertElement); - this.alerts.push({ id: alertId, element: alertElement }); - - // 限制提示数量 - if (this.alerts.length > UI_CONFIG.ALERT.MAX_ALERTS) { - this.removeOldest(); - } - - // 自动隐藏 - if (autoHide > 0) { - setTimeout(() => this.hide(alertId), autoHide); - } - - return alertId; - } - - createAlertElement(id, type, message) { - const alert = document.createElement('div'); - alert.id = id; - alert.className = `alert alert-${type} alert-dismissible fade show`; - alert.innerHTML = ` - - ${escapeHtml(message)} - - `; - - // 绑定关闭事件 - alert.querySelector('.btn-close').addEventListener('click', () => { - this.hide(id); - }); - - return alert; - } - - getIcon(type) { - const icons = { - success: 'check-circle', - error: 'exclamation-circle', - warning: 'exclamation-triangle', - info: 'info-circle' - }; - return icons[type] || 'info-circle'; - } - - hide(alertId) { - const alertIndex = this.alerts.findIndex(alert => alert.id === alertId); - if (alertIndex !== -1) { - const alert = this.alerts[alertIndex]; - alert.element.remove(); - this.alerts.splice(alertIndex, 1); - } - } - - // 便捷方法 - success(message, autoHide) { return this.show('success', message, autoHide); } - error(message, autoHide) { return this.show('error', message, autoHide); } - warning(message, autoHide) { return this.show('warning', message, autoHide); } - info(message, autoHide) { return this.show('info', message, autoHide); } -} -``` - -#### 3.5.2 分页组件 -```javascript -/** - * 分页组件 - */ -class PaginationComponent { - constructor(container, options = {}) { - this.container = typeof container === 'string' ? - document.querySelector(container) : container; - - this.options = { - pageSize: UI_CONFIG.PAGINATION.DEFAULT_PAGE_SIZE, - showSizeChanger: UI_CONFIG.PAGINATION.SHOW_SIZE_CHANGER, - showTotal: true, - showQuickJumper: true, - ...options - }; - - this.currentPage = 1; - this.totalItems = 0; - this.totalPages = 0; - - this.onPageChange = options.onPageChange || (() => {}); - this.onSizeChange = options.onSizeChange || (() => {}); - } - - // 更新分页数据 - update(totalItems, currentPage = 1) { - this.totalItems = totalItems; - this.currentPage = currentPage; - this.totalPages = Math.ceil(totalItems / this.options.pageSize); - this.render(); - } - - // 渲染分页组件 - render() { - if (!this.container) return; - - const pagination = this.createPaginationElement(); - this.container.innerHTML = ''; - this.container.appendChild(pagination); - } - - createPaginationElement() { - const nav = document.createElement('nav'); - nav.innerHTML = ` -
-
- ${this.renderTotalInfo()} -
-
    - ${this.renderPaginationItems()} -
-
- ${this.renderSizeChanger()} - ${this.renderQuickJumper()} -
-
- `; - - this.bindEvents(nav); - return nav; - } - - renderTotalInfo() { - if (!this.options.showTotal) return ''; - - const start = (this.currentPage - 1) * this.options.pageSize + 1; - const end = Math.min(this.currentPage * this.options.pageSize, this.totalItems); - - return ` - - 显示 ${start}-${end} 项,共 ${this.totalItems} 项 - - `; - } - - renderPaginationItems() { - let items = []; - - // 上一页 - items.push(` -
  • - - - -
  • - `); - - // 页码 - const pageNumbers = this.generatePageNumbers(); - pageNumbers.forEach(page => { - if (page === '...') { - items.push('
  • ...
  • '); - } else { - items.push(` -
  • - ${page} -
  • - `); - } - }); - - // 下一页 - items.push(` -
  • - - - -
  • - `); - - return items.join(''); - } - - generatePageNumbers() { - const total = this.totalPages; - const current = this.currentPage; - const pages = []; - - if (total <= 7) { - for (let i = 1; i <= total; i++) { - pages.push(i); - } - } else { - if (current <= 4) { - pages.push(1, 2, 3, 4, 5, '...', total); - } else if (current >= total - 3) { - pages.push(1, '...', total - 4, total - 3, total - 2, total - 1, total); - } else { - pages.push(1, '...', current - 1, current, current + 1, '...', total); - } - } - - return pages; - } - - bindEvents(nav) { - // 分页点击事件 - nav.addEventListener('click', (e) => { - if (e.target.matches('.page-link[data-page]')) { - e.preventDefault(); - const page = parseInt(e.target.dataset.page); - if (page > 0 && page <= this.totalPages) { - this.goToPage(page); - } - } - }); - - // 页面大小变更事件 - const sizeSelect = nav.querySelector('.page-size-select'); - if (sizeSelect) { - sizeSelect.addEventListener('change', (e) => { - this.changePageSize(parseInt(e.target.value)); - }); - } - - // 快速跳转事件 - const jumpInput = nav.querySelector('.page-jump-input'); - if (jumpInput) { - jumpInput.addEventListener('keypress', (e) => { - if (e.key === 'Enter') { - const page = parseInt(e.target.value); - if (page > 0 && page <= this.totalPages) { - this.goToPage(page); - } - } - }); - } - } - - goToPage(page) { - if (page !== this.currentPage) { - this.currentPage = page; - this.render(); - this.onPageChange(page, this.options.pageSize); - } - } - - changePageSize(pageSize) { - this.options.pageSize = pageSize; - this.currentPage = 1; - this.totalPages = Math.ceil(this.totalItems / pageSize); - this.render(); - this.onSizeChange(pageSize, this.currentPage); - } -} -``` - -### 3.6 导航管理模块 (navigation.js) - -#### 3.6.1 导航管理器 -```javascript -/** - * 导航管理器类 - */ -class NavigationManager { - constructor() { - this.currentPath = window.location.pathname; - this.breadcrumbContainer = null; - this.shortcuts = new Map(); - this.init(); - } - - init() { - this.updateActiveNavigation(); - this.createBreadcrumb(); - this.bindNavigationEvents(); - } - - // 更新活跃导航状态 - updateActiveNavigation() { - document.querySelectorAll('.nav-link').forEach(link => { - link.classList.remove('active'); - }); - - // 根据当前路径设置活跃状态 - const currentNavLink = this.findActiveNavLink(); - if (currentNavLink) { - currentNavLink.classList.add('active'); - } - } - - findActiveNavLink() { - // 直接匹配 - let link = document.querySelector(`a[href="${this.currentPath}"]`); - if (link && link.classList.contains('nav-link')) { - return link; - } - - // 路由别名匹配 - if (this.currentPath.includes('db-compare') || - this.currentPath.includes('cassandra-compare')) { - return document.querySelector('a[href="/cassandra-compare"]'); - } - - if (this.currentPath.includes('redis-compare')) { - return document.querySelector('a[href="/redis-compare"]'); - } - - if (this.currentPath === '/') { - return document.querySelector('a[href="/"]'); - } - - return null; - } - - // 创建面包屑导航 - createBreadcrumb() { - const breadcrumbItems = this.getBreadcrumbItems(); - if (breadcrumbItems.length <= 1) return; - - this.breadcrumbContainer = this.findOrCreateBreadcrumbContainer(); - this.renderBreadcrumb(breadcrumbItems); - } - - getBreadcrumbItems() { - const items = [ - { title: '首页', url: '/', icon: 'fas fa-home' } - ]; - - if (this.currentPath.includes('cassandra-compare') || - this.currentPath.includes('db-compare')) { - items.push({ - title: 'Cassandra数据比对', - url: '/cassandra-compare', - icon: 'fas fa-database' - }); - } else if (this.currentPath.includes('redis-compare')) { - items.push({ - title: 'Redis集群比对', - url: '/redis-compare', - icon: 'fab fa-redis' - }); - } - - return items; - } - - // 启用键盘快捷键 - enableKeyboardShortcuts() { - // 定义快捷键 - this.shortcuts.set('ctrl+h', { - action: () => this.navigateTo('/'), - description: '返回首页' - }); - - this.shortcuts.set('ctrl+1', { - action: () => this.navigateTo('/cassandra-compare'), - description: 'Cassandra工具' - }); - - this.shortcuts.set('ctrl+2', { - action: () => this.navigateTo('/redis-compare'), - description: 'Redis工具' - }); - - // 绑定键盘事件 - document.addEventListener('keydown', (e) => { - const key = this.getKeyString(e); - const shortcut = this.shortcuts.get(key); - - if (shortcut) { - e.preventDefault(); - shortcut.action(); - } - }); - - // 显示快捷键提示 - this.createShortcutsTooltip(); - } - - getKeyString(event) { - const keys = []; - - if (event.ctrlKey || event.metaKey) keys.push('ctrl'); - if (event.altKey) keys.push('alt'); - if (event.shiftKey) keys.push('shift'); - - keys.push(event.key.toLowerCase()); - - return keys.join('+'); - } - - createShortcutsTooltip() { - const tooltip = document.createElement('div'); - tooltip.className = 'keyboard-shortcuts-tooltip'; - tooltip.style.cssText = ` - position: fixed; - bottom: 100px; - right: 30px; - z-index: 1000; - background: rgba(0, 0, 0, 0.8); - color: white; - padding: 10px; - border-radius: 5px; - font-size: 12px; - display: none; - `; - - let html = '
    键盘快捷键:
    '; - this.shortcuts.forEach((shortcut, key) => { - const displayKey = key.replace('ctrl', 'Ctrl').replace('+', ' + '); - html += `
    ${displayKey} ${shortcut.description}
    `; - }); - - tooltip.innerHTML = html; - document.body.appendChild(tooltip); - - // 按?键显示/隐藏 - document.addEventListener('keydown', (e) => { - if (e.key === '?' && !e.ctrlKey && !e.metaKey && !e.altKey) { - e.preventDefault(); - tooltip.style.display = tooltip.style.display === 'none' ? 'block' : 'none'; - } - }); - } - - // 程序化导航 - navigateTo(url, replace = false) { - if (replace) { - window.history.replaceState(null, '', url); - } else { - window.location.href = url; - } - } - - // 更新页面标题 - updatePageTitle(title) { - const toolInfo = this.getCurrentToolInfo(); - if (toolInfo) { - document.title = `${title} - ${toolInfo.name} - DataTools Pro`; - } else { - document.title = `${title} - DataTools Pro`; - } - } -} -``` - -## 4. 模块间通信 - -### 4.1 事件驱动架构 -```javascript -/** - * 事件总线 - 模块间通信 - */ -class EventBus { - constructor() { - this.events = new Map(); - } - - // 监听事件 - on(eventName, callback) { - if (!this.events.has(eventName)) { - this.events.set(eventName, new Set()); - } - this.events.get(eventName).add(callback); - } - - // 移除监听 - off(eventName, callback) { - if (this.events.has(eventName)) { - this.events.get(eventName).delete(callback); - } - } - - // 触发事件 - emit(eventName, ...args) { - if (this.events.has(eventName)) { - this.events.get(eventName).forEach(callback => { - try { - callback(...args); - } catch (error) { - console.error(`事件处理错误 [${eventName}]:`, error); - } - }); - } - } - - // 一次性监听 - once(eventName, callback) { - const onceCallback = (...args) => { - callback(...args); - this.off(eventName, onceCallback); - }; - this.on(eventName, onceCallback); - } -} - -// 全局事件总线实例 -const eventBus = new EventBus(); -``` - -### 4.2 模块依赖注入 -```javascript -/** - * 依赖注入容器 - */ -class DIContainer { - constructor() { - this.services = new Map(); - this.instances = new Map(); - } - - // 注册服务 - register(name, factory, singleton = true) { - this.services.set(name, { factory, singleton }); - } - - // 获取服务实例 - get(name) { - if (!this.services.has(name)) { - throw new Error(`Service '${name}' not found`); - } - - const service = this.services.get(name); - - if (service.singleton) { - if (!this.instances.has(name)) { - this.instances.set(name, service.factory()); - } - return this.instances.get(name); - } else { - return service.factory(); - } - } - - // 清除实例缓存 - clear(name) { - if (name) { - this.instances.delete(name); - } else { - this.instances.clear(); - } - } -} - -// 全局DI容器 -const container = new DIContainer(); - -// 注册核心服务 -container.register('config', () => config); -container.register('utils', () => utils); -container.register('api', () => apiManager); -container.register('navigation', () => navigationManager); -container.register('eventBus', () => eventBus); -``` - -## 5. 性能优化 - -### 5.1 模块懒加载 -```javascript -/** - * 模块懒加载管理器 - */ -class LazyLoader { - constructor() { - this.loadedModules = new Set(); - this.loadingPromises = new Map(); - } - - async loadModule(modulePath) { - if (this.loadedModules.has(modulePath)) { - return Promise.resolve(); - } - - if (this.loadingPromises.has(modulePath)) { - return this.loadingPromises.get(modulePath); - } - - const loadPromise = import(modulePath).then(module => { - this.loadedModules.add(modulePath); - this.loadingPromises.delete(modulePath); - return module; - }); - - this.loadingPromises.set(modulePath, loadPromise); - return loadPromise; - } - - async loadModules(modulePaths) { - return Promise.all(modulePaths.map(path => this.loadModule(path))); - } -} -``` - -### 5.2 缓存策略 -```javascript -/** - * 缓存管理器 - */ -class CacheManager { - constructor(maxSize = 100) { - this.cache = new Map(); - this.maxSize = maxSize; - this.accessOrder = []; - } - - set(key, value, ttl = 0) { - const item = { - value, - timestamp: Date.now(), - ttl - }; - - if (this.cache.has(key)) { - this.updateAccessOrder(key); - } else { - if (this.cache.size >= this.maxSize) { - this.evictLRU(); - } - this.accessOrder.push(key); - } - - this.cache.set(key, item); - } - - get(key) { - const item = this.cache.get(key); - - if (!item) return null; - - // 检查过期时间 - if (item.ttl > 0 && Date.now() - item.timestamp > item.ttl) { - this.delete(key); - return null; - } - - this.updateAccessOrder(key); - return item.value; - } - - delete(key) { - this.cache.delete(key); - const index = this.accessOrder.indexOf(key); - if (index > -1) { - this.accessOrder.splice(index, 1); - } - } - - updateAccessOrder(key) { - const index = this.accessOrder.indexOf(key); - if (index > -1) { - this.accessOrder.splice(index, 1); - } - this.accessOrder.push(key); - } - - evictLRU() { - const oldestKey = this.accessOrder.shift(); - this.cache.delete(oldestKey); - } - - clear() { - this.cache.clear(); - this.accessOrder = []; - } -} -``` - -## 6. 错误处理和调试 - -### 6.1 全局错误处理 -```javascript -/** - * 全局错误处理器 - */ -class ErrorHandler { - constructor() { - this.setupGlobalHandlers(); - this.errorReporters = []; - } - - setupGlobalHandlers() { - // JavaScript错误 - window.addEventListener('error', (e) => { - this.handleError(e.error, 'javascript'); - }); - - // Promise拒绝错误 - window.addEventListener('unhandledrejection', (e) => { - this.handleError(e.reason, 'promise'); - e.preventDefault(); - }); - - // 资源加载错误 - window.addEventListener('error', (e) => { - if (e.target !== window) { - this.handleError(new Error(`资源加载失败: ${e.target.src || e.target.href}`), 'resource'); - } - }, true); - } - - handleError(error, type = 'unknown') { - const errorInfo = { - message: error.message || error.toString(), - stack: error.stack, - type, - timestamp: new Date().toISOString(), - url: window.location.href, - userAgent: navigator.userAgent - }; - - console.error('Global Error:', errorInfo); - - // 通知错误报告器 - this.errorReporters.forEach(reporter => { - try { - reporter(errorInfo); - } catch (reportError) { - console.error('Error reporter failed:', reportError); - } - }); - - // 显示用户友好的错误信息 - if (type !== 'resource') { - this.showUserError(error); - } - } - - showUserError(error) { - if (window.DataToolsApp && window.DataToolsApp.ui) { - window.DataToolsApp.ui.alert.error( - '系统出现错误,请刷新页面后重试' - ); - } - } - - addErrorReporter(reporter) { - this.errorReporters.push(reporter); - } -} -``` - -### 6.2 调试工具 -```javascript -/** - * 开发调试工具 - */ -class DebugTool { - constructor() { - this.isEnabled = this.checkDebugMode(); - this.logs = []; - this.maxLogs = 1000; - - if (this.isEnabled) { - this.setupDebugConsole(); - } - } - - checkDebugMode() { - return window.location.search.includes('debug=true') || - localStorage.getItem('datatools_debug') === 'true'; - } - - log(message, data = null) { - if (!this.isEnabled) return; - - const logEntry = { - timestamp: Date.now(), - message, - data, - stack: new Error().stack - }; - - this.logs.push(logEntry); - - if (this.logs.length > this.maxLogs) { - this.logs.shift(); - } - - console.log(`[DEBUG] ${message}`, data); - } - - setupDebugConsole() { - // 添加全局调试命令 - window.DataToolsDebug = { - getLogs: () => this.logs, - clearLogs: () => { this.logs = []; }, - exportLogs: () => { - const data = JSON.stringify(this.logs, null, 2); - fileUtils.download(data, 'datatools-debug.json', 'application/json'); - }, - getAppState: () => window.DataToolsApp, - getModules: () => ({ - config, - utils, - apiManager, - navigationManager - }) - }; - - console.log('DataTools Pro Debug Mode Enabled'); - console.log('Use DataToolsDebug object for debugging'); - } -} -``` - -## 7. 测试策略 - -### 7.1 单元测试框架 -```javascript -/** - * 轻量级测试框架 - */ -class TestFramework { - constructor() { - this.tests = []; - this.results = { - passed: 0, - failed: 0, - errors: [] - }; - } - - describe(description, testFn) { - console.group(`📋 ${description}`); - testFn(); - console.groupEnd(); - } - - it(description, testFn) { - try { - testFn(); - this.results.passed++; - console.log(`✅ ${description}`); - } catch (error) { - this.results.failed++; - this.results.errors.push({ description, error }); - console.error(`❌ ${description}:`, error); - } - } - - expect(actual) { - return { - toBe: (expected) => { - if (actual !== expected) { - throw new Error(`Expected ${expected}, got ${actual}`); - } - }, - toEqual: (expected) => { - if (JSON.stringify(actual) !== JSON.stringify(expected)) { - throw new Error(`Expected ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`); - } - }, - toBeTruthy: () => { - if (!actual) { - throw new Error(`Expected truthy value, got ${actual}`); - } - }, - toBeFalsy: () => { - if (actual) { - throw new Error(`Expected falsy value, got ${actual}`); - } - } - }; - } - - async runTests() { - console.log('🚀 Running DataTools Pro Tests...'); - - // 运行所有测试 - this.testUtils(); - this.testAPI(); - this.testUI(); - - // 输出结果 - console.log(`\n📊 Test Results:`); - console.log(`✅ Passed: ${this.results.passed}`); - console.log(`❌ Failed: ${this.results.failed}`); - - if (this.results.errors.length > 0) { - console.log('\n❌ Errors:'); - this.results.errors.forEach(({ description, error }) => { - console.error(` - ${description}: ${error.message}`); - }); - } - } - - testUtils() { - this.describe('Utils Module', () => { - this.it('should escape HTML correctly', () => { - const result = utils.escapeHtml(''); - this.expect(result).toBe('<script>alert("xss")</script>'); - }); - - this.it('should format date correctly', () => { - const date = new Date('2024-08-05T10:30:00Z'); - const result = utils.formatDate(date, 'YYYY-MM-DD'); - this.expect(result).toBe('2024-08-05'); - }); - - this.it('should debounce function calls', (done) => { - let callCount = 0; - const debouncedFn = utils.debounce(() => callCount++, 100); - - debouncedFn(); - debouncedFn(); - debouncedFn(); - - setTimeout(() => { - this.expect(callCount).toBe(1); - done(); - }, 150); - }); - }); - } -} -``` - -## 8. 构建和部署 - -### 8.1 开发环境 -```javascript -/** - * 开发环境配置 - */ -const devConfig = { - // 热重载 - enableHotReload: true, - - // 调试模式 - debugMode: true, - - // 本地服务器配置 - devServer: { - port: 3000, - host: 'localhost', - open: true - }, - - // 代理配置 - proxy: { - '/api': { - target: 'http://localhost:5000', - changeOrigin: true - } - } -}; -``` - -### 8.2 生产环境优化 -```javascript -/** - * 生产环境优化 - */ -const prodOptimizations = { - // 代码压缩 - minification: true, - - // 资源合并 - bundling: false, // 保持模块化 - - // 缓存策略 - caching: { - staticAssets: '1y', - api: '5m' - }, - - // CDN配置 - cdn: { - bootstrap: 'https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css', - fontawesome: 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css' - } -}; -``` - ---- - -**版本**: v2.0 -**更新日期**: 2024-08-05 -**维护者**: DataTools Pro Team \ No newline at end of file diff --git a/docs/user-manual.md b/docs/user-manual.md deleted file mode 100644 index 5d5e61d..0000000 --- a/docs/user-manual.md +++ /dev/null @@ -1,708 +0,0 @@ -# DataTools Pro 用户使用手册 - -## 1. 系统介绍 - -### 1.1 产品概述 -DataTools Pro 是一个企业级数据处理与比对工具平台,专为数据工程师和运维人员设计,提供高效、精准、可视化的数据分析解决方案。 - -### 1.2 主要功能 -- **Cassandra数据比对**: 支持生产环境与测试环境的数据差异分析 -- **Redis集群比对**: 支持多种数据类型的Redis集群数据比对 -- **分表查询**: 支持TWCS时间分表的智能查询 -- **多主键查询**: 支持复合主键的批量查询 -- **配置管理**: 可视化的数据库配置管理 -- **查询历史**: 完整的查询历史记录和结果复用 -- **实时日志**: 详细的查询执行日志和性能监控 - -### 1.3 系统要求 -- **浏览器**: Chrome 61+, Firefox 60+, Safari 10.1+, Edge 16+ -- **网络**: 能够访问目标Cassandra和Redis集群 -- **权限**: 具备目标数据库的读取权限 - -## 2. 快速入门 - -### 2.1 访问系统 -1. 打开浏览器,访问系统地址(如:http://your-domain.com) -2. 系统首页展示了可用的工具模块和功能介绍 -3. 选择需要使用的工具进入相应的功能页面 - -### 2.2 界面概览 -``` -DataTools Pro 界面布局: -┌─────────────────────────────────────────────────────────────┐ -│ 导航栏 │ -│ DataTools Pro | 首页 | Cassandra比对 | Redis比对 │ -├─────────────────────────────────────────────────────────────┤ -│ 面包屑导航 │ -│ 首页 > Cassandra数据比对工具 │ -├─────────────────────────────────────────────────────────────┤ -│ 配置管理面板 │ 查询操作面板 │ -│ ┌─────────────────┐ │ ┌─────────────────────────────┐ │ -│ │ • 配置组管理 │ │ │ • 查询模式选择 │ │ -│ │ • 数据库配置 │ │ │ • Key值输入 │ │ -│ │ • 查询历史 │ │ │ • 比对字段配置 │ │ -│ │ • 查询日志 │ │ │ • 执行按钮 │ │ -│ └─────────────────┘ │ └─────────────────────────────┘ │ -├─────────────────────────────────────────────────────────────┤ -│ 结果展示区域 │ -│ ┌─────────────────────────────────────────────────────────┐ │ -│ │ • 统计信息卡片 │ │ -│ │ • 差异详情 | 相同结果 | 原始数据 | 比较总结 │ │ -│ │ • 分页导航和搜索过滤 │ │ -│ └─────────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────┘ -``` - -### 2.3 键盘快捷键 -- `Ctrl/Cmd + H`: 返回首页 -- `Ctrl/Cmd + 1`: 切换到Cassandra工具 -- `Ctrl/Cmd + 2`: 切换到Redis工具 -- `?`: 显示/隐藏快捷键提示 - -## 3. Cassandra数据比对工具 - -### 3.1 功能概述 -Cassandra数据比对工具支持对生产环境和测试环境的Cassandra数据库进行精确的数据比对分析,支持单表查询、分表查询和多主键查询三种模式。 - -### 3.2 配置管理 - -#### 3.2.1 配置组管理 -配置组功能允许您保存和管理常用的数据库配置,避免重复输入。 - -**创建配置组**: -1. 点击"保存配置组"按钮 -2. 输入配置组名称和描述 -3. 系统将保存当前的所有配置信息 -4. 配置组创建成功后可在下拉列表中选择 - -**加载配置组**: -1. 在配置组下拉列表中选择已保存的配置组 -2. 点击"加载"按钮 -3. 系统将自动填充所有相关配置 - -**管理配置组**: -1. 点击"管理配置组"按钮 -2. 查看所有已保存的配置组 -3. 可以删除不需要的配置组 - -#### 3.2.2 数据库配置 - -**生产环境配置**: -``` -配置项说明: -• 集群名称: Cassandra集群的标识名称 -• 数据中心: 数据中心名称 (如: datacenter1) -• 主机地址: Cassandra节点地址列表 (支持多个,逗号分隔) -• 端口: 连接端口 (默认: 9042) -• 用户名: 数据库用户名 (可选) -• 密码: 数据库密码 (可选) -• 键空间: Keyspace名称 -• 表名: 要查询的表名 -``` - -**测试环境配置**: -配置项与生产环境相同,用于配置测试环境的Cassandra连接信息。 - -**一键导入功能**: -1. 点击"一键导入"按钮 -2. 可以从生产环境配置快速复制到测试环境 -3. 根据需要修改测试环境的特定配置 - -### 3.3 查询模式 - -#### 3.3.1 单表查询模式 -默认的查询模式,适用于普通的Cassandra表查询。 - -**操作步骤**: -1. 确保分表模式开关处于关闭状态 -2. 配置生产和测试环境的数据库连接 -3. 设置查询参数 -4. 输入要查询的Key值 -5. 点击"执行查询比对" - -#### 3.3.2 分表查询模式 -适用于使用TWCS (Time Window Compaction Strategy) 分表策略的Cassandra表。 - -**启用分表模式**: -1. 打开"分表模式"开关 -2. 分别配置生产和测试环境的分表参数 - -**分表参数配置**: -``` -配置说明: -• 生产环境分表: 是否对生产环境启用分表查询 -• 测试环境分表: 是否对测试环境启用分表查询 -• 时间间隔(秒): 分表的时间间隔,默认604800秒(7天) -• 分表数量: 总分表数量,默认14张表 -``` - -**分表算法说明**: -- 系统从Key中提取时间戳(删除所有非数字字符) -- 计算公式: `shard_index = timestamp // interval_seconds % table_count` -- 示例: Key为"wmid_1609459200",提取时间戳1609459200,计算得到分表索引 - -#### 3.3.3 多主键查询模式 -支持复合主键的批量查询,适用于具有多个主键字段的表。 - -**配置多主键**: -1. 在"主键字段"中输入多个字段名,用逗号分隔 - - 示例: `user_id,timestamp` 或 `docid,id` -2. 在查询Key值中输入复合主键值,每行一组,字段值用逗号分隔 - - 示例: - ``` - 1001,1609459200 - 1002,1609545600 - ``` - -### 3.4 查询配置 - -#### 3.4.1 基础查询参数 -``` -参数说明: -• 主键字段: 表的主键字段名,支持单个或多个字段 -• 比对字段: 指定要比对的字段列表 (空表示全部字段) -• 排除字段: 指定要排除的字段列表 -• 查询Key值: 要查询的主键值列表,每行一个 -``` - -#### 3.4.2 字段配置技巧 -- **全字段比对**: 比对字段留空,系统将比对所有字段 -- **指定字段比对**: 在比对字段中列出需要比对的字段名 -- **排除字段**: 在排除字段中列出不需要比对的字段(如时间戳字段) -- **字段名格式**: 使用英文逗号分隔多个字段名 - -### 3.5 执行查询 - -#### 3.5.1 查询执行流程 -1. **配置验证**: 系统验证数据库连接配置的完整性 -2. **连接测试**: 尝试连接到生产和测试环境 -3. **并行查询**: 同时执行生产和测试环境的数据查询 -4. **数据比对**: 对查询结果进行字段级比对分析 -5. **结果展示**: 生成详细的比对报告和统计信息 - -#### 3.5.2 执行过程监控 -- 查询执行时显示进度指示器 -- 实时显示执行状态和进度信息 -- 可以通过查询日志查看详细的执行过程 - -### 3.6 结果分析 - -#### 3.6.1 统计信息卡片 -查询完成后,系统会显示以下统计信息: -``` -统计指标: -• 查询总数: 本次查询的Key总数量 -• 生产记录数: 生产环境查询到的记录数 -• 测试记录数: 测试环境查询到的记录数 -• 差异数量: 发现的数据差异数量 -• 相同数量: 数据完全相同的记录数量 -• 匹配率: 数据匹配的百分比 -``` - -#### 3.6.2 结果选项卡 - -**差异详情选项卡**: -- 显示所有发现的数据差异 -- 每条差异记录包含: - - Key信息 (支持复合主键显示) - - 字段名 - - 生产环境值 - - 测试环境值 - - 差异类型说明 -- 支持分页浏览和搜索过滤 - -**相同结果选项卡**: -- 显示数据完全相同的记录 -- 包含生产和测试环境的完整字段值 -- 可用于验证数据同步的正确性 - -**原始数据选项卡**: -- 显示生产和测试环境的原始查询数据 -- 支持格式化和原始两种显示模式 -- 提供数据导出功能 - -**比较总结选项卡**: -- 提供详细的数据质量分析报告 -- 包含匹配率统计和字段级差异分析 -- 给出数据改进建议 - -#### 3.6.3 分表查询信息 -当使用分表查询模式时,结果页面会显示额外的分表信息: -``` -分表信息包含: -• 分表映射关系: 每个Key对应的分表名称 -• 分表统计: 使用的分表列表和分布情况 -• 时间戳提取: 时间戳提取成功率 -• 失败Key列表: 时间戳提取失败的Key -``` - -### 3.7 查询历史管理 - -#### 3.7.1 保存查询历史 -1. 查询执行完成后,点击"保存历史"按钮 -2. 输入历史记录名称和描述 -3. 系统将保存完整的查询配置和结果数据 - -#### 3.7.2 查看查询历史 -1. 点击"查询历史"按钮 -2. 浏览所有已保存的历史记录 -3. 可以查看历史记录的详细信息: - - 查询配置 - - 执行时间 - - 结果统计 - - 完整的差异和相同数据 - -#### 3.7.3 历史记录操作 -- **加载历史**: 从历史记录恢复查询配置 -- **查看结果**: 查看历史查询的完整结果 -- **删除记录**: 删除不需要的历史记录 - -### 3.8 查询日志 - -#### 3.8.1 日志功能 -查询日志记录了查询执行过程中的所有关键信息: -- SQL语句执行记录 -- 数据库连接状态 -- 查询耗时统计 -- 错误和警告信息 - -#### 3.8.2 日志查看 -1. 点击"查询日志"按钮 -2. 可以按日志级别过滤: - - INFO: 一般信息 - - WARNING: 警告信息 - - ERROR: 错误信息 -3. 支持按时间范围查看日志 - -#### 3.8.3 日志管理 -- **实时刷新**: 实时查看最新的日志信息 -- **清空日志**: 清除所有历史日志记录 -- **日志导出**: 导出日志用于分析和故障排查 - -## 4. Redis集群比对工具 - -### 4.1 功能概述 -Redis集群比对工具专门用于对比两个Redis集群之间的数据差异,支持所有Redis数据类型,提供随机采样和指定Key两种查询模式。 - -### 4.2 Redis集群配置 - -#### 4.2.1 集群配置参数 -``` -配置项说明: -• 集群名称: Redis集群的标识名称 -• Redis节点: 集群节点列表,支持添加多个节点 - - 主机地址: Redis节点IP地址 - - 端口: Redis端口 (默认: 6379) -• 密码: Redis认证密码 (可选) -• 连接超时: Socket连接超时时间 (默认: 3秒) -• 建立超时: Socket建立连接超时时间 (默认: 3秒) -• 最大连接数: 每个节点的最大连接数 (默认: 16) -``` - -#### 4.2.2 集群节点管理 -**添加节点**: -1. 在节点配置区域点击"添加节点"按钮 -2. 输入节点的IP地址和端口 -3. 可以添加多个节点以支持集群模式 - -**删除节点**: -1. 点击节点右侧的删除按钮 -2. 确认删除操作 - -**测试连接**: -1. 配置完成后点击"测试连接"按钮 -2. 系统将测试与集群的连接状态 -3. 显示连接结果和节点状态 - -### 4.3 查询模式 - -#### 4.3.1 随机采样模式 -适用于对Redis集群进行数据质量抽查和整体数据一致性验证。 - -**配置参数**: -``` -参数说明: -• 采样数量: 随机采样的Key数量 (1-10000) -• Key模式: Key的匹配模式 (默认: *) -• 源集群: 选择从哪个集群获取Key列表 -``` - -**操作步骤**: -1. 选择"随机采样模式" -2. 设置采样数量 (建议100-1000) -3. 设置Key模式 (如: user:*, session:*, 或 *) -4. 选择源集群 (通常选择数据较完整的集群) -5. 点击"开始Redis数据比较" - -#### 4.3.2 指定Key模式 -适用于对特定Key进行精确的数据比对。 - -**操作步骤**: -1. 选择"指定Key模式" -2. 在Key列表文本框中输入要查询的Key -3. 每行一个Key,支持大批量Key查询 -4. 建议单次不超过1000个Key -5. 点击"开始Redis数据比较" - -**Key输入示例**: -``` -user:1001 -user:1002 -session:abc123 -cache:product:12345 -``` - -### 4.4 数据类型支持 - -#### 4.4.1 支持的Redis数据类型 -Redis集群比对工具支持以下数据类型的比对: -- **String**: 字符串类型,包括JSON字符串 -- **Hash**: 哈希表,支持字段级比对 -- **List**: 列表,支持顺序和内容比对 -- **Set**: 集合,支持成员比对(顺序无关) -- **Sorted Set**: 有序集合,支持成员和分数比对 - -#### 4.4.2 数据比对逻辑 -``` -比对规则: -• String类型: 直接比较字符串值 -• Hash类型: 逐字段比较,显示字段级差异 -• List类型: 比较列表长度和元素内容 -• Set类型: 比较集合成员,忽略顺序 -• ZSet类型: 比较成员和分数的对应关系 -``` - -### 4.5 结果分析 - -#### 4.5.1 统计信息 -Redis比对完成后显示以下统计信息: -``` -统计指标: -• 查询总数: 本次查询的Key总数 -• 集群1找到: 集群1中存在的Key数量 -• 集群2找到: 集群2中存在的Key数量 -• 差异数量: 值不同的Key数量 -• 相同数量: 值完全相同的Key数量 -• 缺失数量: 在某个集群中不存在的Key数量 -``` - -#### 4.5.2 结果选项卡 - -**差异详情选项卡**: -- 显示值不同的Key详细信息 -- 包含Key名称、数据类型、两个集群的值 -- 对于复杂数据类型,显示具体的差异字段 - -**相同结果选项卡**: -- 显示完全相同的Key和值 -- 用于验证数据同步的正确性 - -**缺失数据选项卡**: -- 显示在某个集群中不存在的Key -- 分为"集群1缺失"和"集群2缺失"两个部分 - -**原生数据选项卡**: -- 显示两个集群的原始查询数据 -- 支持格式化和原始数据两种视图 -- 提供数据导出功能 - -**比较总结选项卡**: -- 生成性能报告和数据质量分析 -- 包含集群连接状态和响应时间统计 -- 提供数据一致性改进建议 - -### 4.6 性能监控 - -#### 4.6.1 集群状态监控 -系统实时监控Redis集群的运行状态: -``` -监控指标: -• 连接状态: 显示每个节点的连接状态 -• 平均响应时间: 集群的平均响应时间 -• 节点状态: 各个节点的运行状态 -• 数据传输量: 本次查询的数据传输量 -``` - -#### 4.6.2 性能统计 -查询完成后显示性能统计信息: -- 总执行时间 -- 每秒处理Key数量 -- 数据传输量统计 -- 集群负载分析 - -## 5. 高级功能 - -### 5.1 配置导入导出 - -#### 5.1.1 配置导出 -1. 在任何工具页面点击"导出配置"按钮 -2. 系统将生成包含所有配置信息的JSON文件 -3. 文件包含数据库配置、查询参数、分表配置等 - -#### 5.1.2 配置导入 -1. 点击"一键导入"或相关导入按钮 -2. 选择导入方式: - - **文本粘贴**: 直接粘贴YAML或JSON配置 - - **文件上传**: 上传配置文件或拖拽文件 -3. 预览配置内容 -4. 确认导入 - -#### 5.1.3 支持的配置格式 -**YAML格式示例**: -```yaml -clusterName: "production-cluster" -clusterAddress: "10.0.1.100:9042,10.0.1.101:9042" -keyspace: "production_ks" -table: "user_data" -username: "cassandra_user" -password: "password" -``` - -**JSON格式示例**: -```json -{ - "cluster_name": "production-cluster", - "hosts": ["10.0.1.100", "10.0.1.101"], - "port": 9042, - "keyspace": "production_ks", - "table": "user_data" -} -``` - -### 5.2 数据导出功能 - -#### 5.2.1 结果导出格式 -支持多种数据导出格式: -- **Excel格式 (.xlsx)**: 适合数据分析和报告 -- **CSV格式 (.csv)**: 通用的数据交换格式 -- **JSON格式 (.json)**: 适合程序处理 -- **HTML报告**: 可打印的详细报告 - -#### 5.2.2 导出内容选择 -可以选择导出以下内容: -- 差异数据详情 -- 相同数据记录 -- 原始查询数据 -- 统计分析报告 -- 完整的比对结果 - -#### 5.2.3 导出操作步骤 -1. 在结果页面点击"导出结果"按钮 -2. 选择导出格式和内容范围 -3. 系统生成并下载导出文件 -4. 文件名包含时间戳,便于管理 - -### 5.3 批量操作 - -#### 5.3.1 批量Key导入 -支持大批量Key的导入和处理: -- **文件导入**: 支持.txt, .csv, .xlsx格式 -- **粘贴导入**: 直接粘贴Key列表 -- **去重处理**: 自动去除重复的Key -- **格式验证**: 验证Key格式的正确性 - -#### 5.3.2 批量查询优化 -系统对批量查询进行了优化: -- **分批处理**: 大量Key自动分批查询 -- **并行执行**: 多线程并行处理提高效率 -- **进度显示**: 实时显示查询进度 -- **错误处理**: 单个Key失败不影响整体查询 - -### 5.4 数据过滤和搜索 - -#### 5.4.1 实时搜索 -在结果页面提供实时搜索功能: -- **Key搜索**: 根据Key名称搜索 -- **字段搜索**: 根据字段名搜索 -- **值搜索**: 根据字段值搜索 -- **模糊匹配**: 支持部分匹配和通配符 - -#### 5.4.2 高级过滤 -提供多种过滤条件: -- **差异类型过滤**: 按差异类型筛选 -- **字段名过滤**: 按特定字段筛选 -- **数据类型过滤**: 按Redis数据类型筛选 -- **时间范围过滤**: 按查询时间筛选 - -## 6. 故障排查 - -### 6.1 常见问题 - -#### 6.1.1 连接问题 -**问题**: 无法连接到Cassandra/Redis集群 -**解决方案**: -1. 检查网络连通性: `ping ` -2. 检查端口是否开放: `telnet ` -3. 验证用户名和密码 -4. 确认防火墙设置 -5. 检查集群状态 - -**问题**: 连接超时 -**解决方案**: -1. 增加连接超时时间 -2. 检查网络延迟 -3. 确认集群负载情况 -4. 检查DNS解析 - -#### 6.1.2 查询问题 -**问题**: 查询结果为空 -**解决方案**: -1. 验证Key是否存在于数据库中 -2. 检查表名和键空间是否正确 -3. 确认主键字段名拼写 -4. 检查数据权限 - -**问题**: 分表查询失败 -**解决方案**: -1. 验证分表参数配置 -2. 检查Key中是否包含时间戳 -3. 确认分表命名规则 -4. 验证分表数量设置 - -#### 6.1.3 性能问题 -**问题**: 查询速度慢 -**解决方案**: -1. 减少单次查询的Key数量 -2. 优化网络连接 -3. 检查数据库负载 -4. 使用更高效的查询模式 - -**问题**: 内存使用过高 -**解决方案**: -1. 分批处理大量数据 -2. 减少比对字段数量 -3. 清理历史查询记录 -4. 重启浏览器释放内存 - -### 6.2 错误信息解读 - -#### 6.2.1 连接错误 -``` -错误类型及解决方案: - -• "Connection refused" - - 检查目标主机是否可达 - - 确认端口是否正确 - - 检查防火墙设置 - -• "Authentication failed" - - 验证用户名和密码 - - 检查用户权限 - - 确认认证方式 - -• "Timeout occurred" - - 增加超时时间设置 - - 检查网络延迟 - - 确认集群健康状态 -``` - -#### 6.2.2 查询错误 -``` -错误类型及解决方案: - -• "Keyspace not found" - - 检查键空间名称拼写 - - 确认键空间是否存在 - - 验证用户访问权限 - -• "Table not found" - - 检查表名拼写 - - 确认表是否存在于指定键空间 - - 验证表访问权限 - -• "Invalid primary key" - - 检查主键字段名 - - 确认主键值格式 - - 验证复合主键配置 -``` - -### 6.3 性能优化建议 - -#### 6.3.1 查询优化 -1. **合理设置批次大小**: 建议单次查询1000个Key以内 -2. **选择合适的比对字段**: 只比对必要的字段 -3. **使用分表查询**: 对于大表使用分表查询提高效率 -4. **定期清理历史数据**: 删除不需要的历史记录和日志 - -#### 6.3.2 网络优化 -1. **就近部署**: 在靠近数据库的网络环境中使用工具 -2. **稳定网络**: 确保网络连接稳定,避免频繁重连 -3. **并发控制**: 合理设置并发连接数 -4. **压缩传输**: 启用数据传输压缩 - -#### 6.3.3 数据库优化 -1. **读取权限**: 确保使用只读权限账户 -2. **索引优化**: 确保查询字段有适当的索引 -3. **分区策略**: 合理设计Cassandra分区键 -4. **连接池**: 使用连接池避免频繁建立连接 - -## 7. 最佳实践 - -### 7.1 数据比对策略 - -#### 7.1.1 渐进式比对 -1. **小范围测试**: 先用少量Key测试配置和连接 -2. **分批比对**: 将大量数据分批进行比对 -3. **重点字段**: 优先比对关键业务字段 -4. **定期验证**: 建立定期数据比对的流程 - -#### 7.1.2 差异分析方法 -1. **分类分析**: 按字段类型分类分析差异 -2. **趋势观察**: 观察差异随时间的变化趋势 -3. **根因分析**: 深入分析差异产生的根本原因 -4. **修复验证**: 修复后重新验证数据一致性 - -### 7.2 配置管理最佳实践 - -#### 7.2.1 配置组织 -1. **命名规范**: 使用有意义的配置组名称 -2. **环境区分**: 清楚标识生产、测试、开发环境 -3. **版本管理**: 记录配置变更历史 -4. **权限控制**: 限制敏感配置的访问权限 - -#### 7.2.2 安全考虑 -1. **密码管理**: 避免在配置中硬编码密码 -2. **权限最小化**: 使用最小必要权限的数据库账户 -3. **网络隔离**: 在安全的网络环境中使用工具 -4. **审计日志**: 记录重要操作的审计日志 - -### 7.3 团队协作 - -#### 7.3.1 工作流程标准化 -1. **操作文档**: 制定标准的操作流程文档 -2. **结果记录**: 建立查询结果的记录和归档制度 -3. **问题跟踪**: 建立差异问题的跟踪和解决流程 -4. **知识分享**: 定期分享使用经验和最佳实践 - -#### 7.3.2 质量控制 -1. **双人验证**: 重要数据比对结果需要双人确认 -2. **结果审核**: 建立结果审核和批准流程 -3. **变更控制**: 对配置变更进行严格控制 -4. **定期回顾**: 定期回顾和改进数据比对流程 - -## 8. 技术支持 - -### 8.1 获取帮助 -- **在线文档**: 访问系统内置的帮助文档 -- **技术支持**: 联系技术支持团队 -- **社区论坛**: 参与用户社区讨论 -- **培训资源**: 获取相关的培训材料 - -### 8.2 反馈和建议 -我们欢迎您的反馈和建议: -- **功能建议**: 提出新功能需求 -- **问题报告**: 报告使用中遇到的问题 -- **改进意见**: 提供用户体验改进建议 -- **文档更新**: 建议文档内容的改进 - -### 8.3 版本更新 -- **更新通知**: 关注系统版本更新通知 -- **新功能**: 了解新版本的功能特性 -- **兼容性**: 注意版本兼容性说明 -- **升级指南**: 遵循版本升级指南 - ---- - -**DataTools Pro v2.0 用户使用手册** -**更新日期**: 2024-08-05 -**版权所有**: DataTools Pro Team \ No newline at end of file