你提供的是一份非常完整、专业的**慢日志平台概要设计方案**,涵盖了从**全局可视化大屏 → 下钻分析能力 → 任务跟踪看板 → 系统集成方案**的全流程设计。我将基于这份方案进行**系统性解读与补充实现细节**,并提供关键模块的代码示例(如 WebSocket 实时推送、SQL 指纹生成、ECharts 图表渲染等),帮助你更好地落地该系统。
---
## 一、全局可视化大屏
### ✅ 核心功能总结
- 实时监控:通过 WebSocket 推送 Redis 缓存中的统计结果。
- 趋势分析:慢 SQL 数量、执行时长分布、影响行数对比。
- TOP排行榜:使用 Redis Sorted Set 存储和更新。
- 健康度矩阵:热力图 + 多维评分算法。
- 告警面板:多渠道通知 + 数据聚合展示。
### 🔧 关键代码实现
#### 1. 使用 Python + Flask-SocketIO 实现 WebSocket 实时推送
```python
from flask import Flask, render_template
from flask_socketio import SocketIO, emit
import redis
import json
import time
app = Flask(__name__)
socketio = SocketIO(app, cors_allowed_origins="*")
redis_client = redis.StrictRedis(host='localhost', port=6379, db=0)
@app.route('/')
def index():
return render_template('dashboard.html') # 大屏前端页面
@socketio.on('connect')
def handle_connect():
print('Client connected')
# 连接后立即发送一次数据
send_realtime_data()
def send_realtime_data():
while True:
# 从 Redis 获取最新趋势数据
trend_data = redis_client.get("slowsql:trend:24h")
top_exec_time = redis_client.zrevrange("top:exec_time", 0, 9, withscores=True)
data = {
"trend": json.loads(trend_data) if trend_data else [],
"top_exec_time": [{"sql_fingerprint": item[0].decode(), "avg_time": item[1]} for item in top_exec_time]
}
socketio.emit('update_dashboard', data)
time.sleep(30) # 每30秒推送一次
if __name__ == '__main__':
socketio.start_background_task(send_realtime_data)
socketio.run(app, host='0.0.0.0', port=5000)
```
> **说明**:
> - 后端定时从 Redis 读取 `slowsql:trend:24h` 和 `top:exec_time` 等缓存数据。
> - 使用 `start_background_task` 在后台持续推送。
> - 前端监听 `update_dashboard` 事件更新图表。
---
#### 2. Redis 中存储 TOP 榜(Sorted Set)
```python
# 示例:插入一条慢 SQL 统计记录
redis_client.zincrby("top:exec_time", avg_exec_time, sql_fingerprint)
redis_client.zincrby("top:scan_rows", scan_count, sql_fingerprint)
redis_client.zincrby("top:lock_wait", lock_time, sql_fingerprint)
# 获取 Top 10
top_10 = redis_client.zrevrange("top:exec_time", 0, 9, withscores=True)
```
> **建议 TTL 设置**:
```python
redis_client.expire("top:exec_time", 60) # 每分钟刷新,过期时间略大于刷新周期
```
---
#### 3. ECharts 渲染趋势图(前端)
```html
<div id="trendChart" style="width: 100%; height: 300px;"></div>
<script src="https://cdn.jsdelivr.net/npm/echarts/dist/echarts.min.js"></script>
<script>
const chart = echarts.init(document.getElementById('trendChart'));
let option = {
tooltip: { trigger: 'axis' },
xAxis: { type: 'category', data: [] },
yAxis: { type: 'value', name: '慢SQL数量' },
series: [{
name: '慢SQL数量',
type: 'line',
areaStyle: {},
color: '#FF6B6B'
}]
};
chart.setOption(option);
// WebSocket 接收更新
socket.on('update_dashboard', function(data) {
const times = data.trend.map(t => t.time);
const counts = data.trend.map(t => t.count);
chart.setOption({
xAxis: { data: times },
series: [{ data: counts }]
});
});
</script>
```
> 支持渐变色填充、阈值告警变色可配置 `areaStyle.color` 为渐变对象。
---
#### 4. 实例健康度评分计算(Python 示例)
```python
def calculate_health_score(instance_id):
weights = {
'slow_count': 0.4,
'avg_duration': 0.3,
'lock_time': 0.2,
'scan_rows': 0.1
}
slow_count = redis_client.get(f"metric:{instance_id}:slow_count") or 0
avg_duration = float(redis_client.get(f"metric:{instance_id}:avg_duration") or 0)
lock_time = float(redis_client.get(f"metric:{instance_id}:lock_time") or 0)
scan_rows = int(redis_client.get(f"metric:{instance_id}:scan_rows") or 0)
# 归一化到 0-100 分(假设已知最大可能值或动态滑动窗口)
score = (
normalize(slow_count, max_slow=1000, reverse=True) * weights['slow_count'] +
normalize(avg_duration, max_dur=10, reverse=True) * weights['avg_duration'] +
normalize(lock_time, max_lock=5, reverse=True) * weights['lock_time'] +
normalize(scan_rows, max_scan=1e6, reverse=True) * weights['scan_rows']
) * 100
return min(max(score, 0), 100)
def normalize(value, max_val, reverse=False):
n = min(float(value) / max_val, 1.0)
return 1 - n if reverse else n
```
> 可以每5分钟调度一次,写入 Redis 或 MySQL。
---
## 二、下钻分析能力
### ✅ 核心功能总结
- 多维 OLAP 分析模型(时间、业务、实例、SQL 类型等)
- 四种视图切换:列表、趋势、分布、原始日志
- 根因分析:执行计划、参数差异、历史对比
### 🔧 关键实现
#### 1. SQL 指纹生成(用于聚合相同模板的 SQL)
```python
import re
def generate_sql_fingerprint(sql):
# 移除所有常量(数字、字符串)
sql = re.sub(r'\b\d+\b', '?', sql) # 数字
sql = re.sub(r"'[^']*'", "'?'", sql) # 单引号字符串
sql = re.sub(r'"[^"]*"', '"?"', sql) # 双引号字符串
sql = re.sub(r"`[^`]*`", "`?`", sql) # 反引号标识符(保留结构)
sql = re.sub(r'\s+', ' ', sql).strip() # 多空格合并
return sql.lower()
```
> 示例:
```python
sql = "SELECT * FROM users WHERE id = 123 AND name = 'Alice'"
fingerprint = generate_sql_fingerprint(sql)
# 输出: select * from users where id = ? and name = '?'
```
> 将指纹作为聚合键,可用于统计执行次数、平均耗时等。
---
#### 2. MySQL 表结构设计(分区表 + 索引优化)
```sql
CREATE TABLE slow_log_records (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
instance_id VARCHAR(64) NOT NULL,
db_name VARCHAR(64),
table_name VARCHAR(64),
sql_type ENUM('SELECT','UPDATE','DELETE','INSERT'),
sql_fingerprint TEXT NOT NULL,
original_sql LONGTEXT,
exec_time FLOAT NOT NULL, -- seconds
lock_time FLOAT,
rows_sent INT,
rows_examined INT,
user_host VARCHAR(128),
client_ip VARCHAR(45),
timestamp DATETIME NOT NULL,
app_name VARCHAR(64),
business_line VARCHAR(64),
INDEX idx_time (timestamp),
INDEX idx_fingerprint (sql_fingerprint(255)),
INDEX idx_instance_time (instance_id, timestamp),
INDEX idx_biz_sql_type (business_line, sql_type)
) ENGINE=InnoDB
PARTITION BY RANGE (YEAR(timestamp) * 100 + MONTH(timestamp)) (
PARTITION p202401 VALUES LESS THAN (202402),
PARTITION p202402 VALUES LESS THAN (202403),
PARTITION p202403 VALUES LESS THAN (202404)
);
```
> 分区按月划分,提升查询效率;复合索引支持多维筛选。
---
#### 3. 执行计划分析(调用 EXPLAIN)
```python
import pymysql
def explain_sql(instance_config, sql):
conn = pymysql.connect(**instance_config)
try:
with conn.cursor() as cursor:
cursor.execute(f"EXPLAIN {sql}")
result = cursor.fetchall()
columns = [desc[0] for desc in cursor.description]
return [dict(zip(columns, row)) for row in result]
finally:
conn.close()
# 高亮问题点
def analyze_explain(explain_rows):
issues = []
for row in explain_rows:
if row['type'] == 'ALL':
issues.append("全表扫描 detected")
if 'filesort' in (row['Extra'] or ''):
issues.append("需要 filesort")
if 'temporary' in (row['Extra'] or ''):
issues.append("使用临时表")
return issues
```
> 可结合前端高亮显示,并给出“建议添加索引”提示。
---
## 三、任务跟踪看板
### ✅ 功能亮点
- 工作流状态机管理(待处理 → 已完成)
- 看板拖拽 + 列表双模式
- 自动验证 + 提醒机制
### 🔧 数据库设计(MySQL)
```sql
CREATE TABLE optimization_tasks (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
status ENUM('pending', 'assigned', 'in_progress', 'pending_verify', 'completed', 'rejected', 'archived') DEFAULT 'pending',
priority ENUM('P0','P1','P2','P3') DEFAULT 'P2',
sql_fingerprint TEXT NOT NULL,
instance_id VARCHAR(64),
business_line VARCHAR(64),
current_avg_duration FLOAT,
target_avg_duration FLOAT,
owner_user_id VARCHAR(64),
assignee_user_id VARCHAR(64),
due_date DATETIME,
created_by VARCHAR(64),
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_status (status),
INDEX idx_assignee (assignee_user_id),
INDEX idx_due_date (due_date),
INDEX idx_fingerprint (sql_fingerprint(255))
);
-- 协作人关联表
CREATE TABLE task_collaborators (
task_id BIGINT,
user_id VARCHAR(64),
FOREIGN KEY (task_id) REFERENCES optimization_tasks(id) ON DELETE CASCADE
);
-- 操作日志
CREATE TABLE task_logs (
id BIGINT AUTO_INCREMENT PRIMARY KEY,
task_id BIGINT,
operator VARCHAR(64),
action VARCHAR(64), -- e.g., 'assigned', 'started', 'verified'
details JSON,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (task_id) REFERENCES optimization_tasks(id)
);
```
---
#### 1. WebSocket 实现看板状态同步(Vue + Socket.IO)
```javascript
// Vue 组件中监听任务状态变化
socket.on('task_updated', (updatedTask) => {
const task = this.tasks.find(t => t.id === updatedTask.id);
if (task) Object.assign(task, updatedTask);
});
```
后端在任务状态变更后广播:
```python
socketio.emit('task_updated', task_dict, room=f"board_{business_line}")
```
---
#### 2. 自动性能验证逻辑
```python
def auto_verify_task(task_id):
task = get_task(task_id)
recent_data = query_mysql(f"""
SELECT AVG(exec_time) as avg_time
FROM slow_log_records
WHERE sql_fingerprint = %s
AND timestamp > DATE_SUB(NOW(), INTERVAL 1 HOUR)
""", (task.sql_fingerprint,))
current_avg = recent_data[0]['avg_time']
if current_avg <= task.target_avg_duration:
return {"result": "passed", "current": current_avg}
else:
return {"result": "failed", "current": current_avg, "target": task.target_avg_duration}
```
> 提交验证时自动调用此函数,辅助判断是否达标。
---
## 四、系统集成方案(架构图补充)
```
+------------------+ +-------------------+
| MySQL Slow Log | --> | Kafka (日志采集) |
+------------------+ +---------+---------+
|
v
+----------------------------+
| Log Processor (Python) |
| - 生成指纹 |
| - 写入 MySQL & Redis |
+-------------+--------------+
|
+-----------------------v------------------------+
| 应用服务层 |
| Spring Boot / Flask |
| - WebSocket 推送 |
| - REST API 提供查询 |
| - 定时任务聚合统计 |
+-----------------------+------------------------+
|
+--------------------------v----------------------------+
| 前端 (Vue3 + ECharts + Element Plus) |
| - 大屏 / 下钻 / 任务看板 |
+-------------------------------------------------------+
通知系统:钉钉机器人 → Webhook 发送消息
文件导出:Celery 异步任务 → MinIO/OSS 存储 → 返回下载链接
```
---
## 总结与优势
| 模块 | 技术亮点 |
|------|----------|
| 大屏 | WebSocket + Redis + ECharts 实现实时可视化 |
| 下钻 | 多维 OLAP + SQL指纹 + 分区表加速查询 |
| 任务 | 工作流引擎 + 自动验证 + 协作提醒 |
| 架构 | 解耦清晰、扩展性强、支持高并发 |
---
##