🌟 为什么传统数据库在机器监控场景中力不从心?
当我们需要采集服务器、虚拟机或容器的性能指标时(如CPU、内存、磁盘IO等),传统关系型数据库面临三大痛点:
- 写入瓶颈:每秒数千台机器上报数据,MySQL索引维护成为性能杀手
- 存储膨胀:监控数据按分钟级采集,1年数据量轻松超TB级
- 查询缓慢:统计"过去1小时CPU使用率"需要BTree扫描时间戳字段
⚡ 时序数据库如何完美解决这些问题?
1. 超高性能写入设计
css
mermaid
graph LR
A[机器1] -->|Telegraf| B[内存缓冲时间包]
A2[机器2] -->|Telegraf| B
B --> C[批量写入磁盘] 此处写入为有序磁盘IO,且无锁介入
- 无索引负担:数据按时间顺序追加写入,无需维护B+Tree
- 实测性能:InfluxDB单节点可处理50万+数据点/秒
2. 极致存储压缩
采用三大压缩技术:
- 列式存储:CPU%、内存%、磁盘%等指标分开存储
- Delta编码:时间戳存储为差值(如+60s)
- Gorilla压缩:浮点数专用压缩算法
效果:原始100GB监控数据 → 压缩后仅3-5GB
3. 专用查询优化
sql
sql
-- 计算所有机器5分钟负载均值
SELECT mean(cpu_usage)
FROM metrics
WHERE time > now() - 1h
GROUP BY hostname, time(5m)
-- 找出最近1小时内存超90%的机器
SELECT hostname
FROM metrics
WHERE mem_usage > 90 AND time > now() - 1h
在索引性能方面,时序数据库也可以直接访问对应的事件包内部的数据,无需像B类树一样去查询 查询速度比MySQL快10-100倍!
🌟 MySQL基础知识回顾
特性 | InnoDB (事务型引擎) | MyISAM (非事务型引擎) |
---|---|---|
存储文件 | .ibd 文件(包含索引+数据) |
.MYD (数据文件) +.MYI (索引文件) |
索引结构 | B+Tree | B-Tree |
聚簇索引 | ✅ 叶子节点存储完整数据行 | ❌ 无聚簇索引 |
非聚簇索引 | 叶子节点存储主键ID(需回表查询) | 叶子节点存储数据物理地址(直接访问) |
锁机制 | 行级锁(高并发友好) | 表级锁(并发性能差) |
事务支持 | ✅ 完整ACID | ❌ 不支持 |
压缩方式 | 页压缩(支持读写): 1. 内存中不压缩 2. 异步压缩后刷盘 | 只读压缩: 1. 仅压缩 .MYD 文件 2. 类似7zip压缩 3. 压缩后不可写入 |
崩溃恢复 | 通过redo log自动恢复 | 需手动修复( REPAIR TABLE ) |
适用场景 | OLTP(高并发事务) | 读密集型操作(如报表) |
特性 | Redo Log (重做日志) | Undo Log (回滚日志) | Binlog (二进制日志) |
---|---|---|---|
所属层级 | InnoDB引擎特有 | InnoDB引擎特有 | MySQL Server层,所有引擎通用 |
日志类型 | 物理日志(记录页面的物理修改) | 逻辑日志(记录修改前的值) | 逻辑日志(SQL语句/行变更) |
主要作用 | 崩溃恢复(确保事务持久性) | 事务回滚 + MVCC实现 | 主从复制 + 时间点恢复 |
写入时机 | 事务执行中持续写入 | 事务执行中写入 | 事务提交后一次性写入 |
还没搬到仓库就断电 → 包裹全丢!客户投诉 RedoLog
MVCC 就是为了解决脏读、不可重复读、幻读而生的!
隔离问题 | MVCC 如何解决 | 示例 |
---|---|---|
脏读 | 只读已提交的事务版本 | 事务A未提交时,事务B看到的是旧数据 |
不可重复读 | 保留事务开始时的数据快照 | 事务B在事务A提交前后读同一数据,结果一致 |
幻读 | 通过版本链控制范围查询的可见性 | 事务A插入新记录,事务B的 SELECT 不会突然多出行 |
脏读: 读取到其他事务未提交的数据, 同一个事务两次读取值不一样
不可重复读: 同一个事务两次读取的内容不同
幻读: 同一事务呢两次读取数据的数量不同