强曰为道
与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

rqlite 完全指南 / 第 14 章:最佳实践

第 14 章:最佳实践

何时选择 rqlite、生产环境规范、架构建议和实际经验总结。


14.1 何时选择 rqlite

14.1.1 决策矩阵

你需要分布式数据库吗?
    │
    ├── 否 → 使用 SQLite
    │
    ├── 是 → 你需要完整的 SQL 支持吗?
    │         │
    │         ├── 否 → 考虑 etcd / Consul / Redis
    │         │
    │         └── 是 → 数据规模多大?
    │                   │
    │                   ├── < 10GB → 考虑 rqlite ✅
    │                   │
    │                   ├── 10GB - 1TB → 考虑 PostgreSQL / MySQL
    │                   │
    │                   └── > 1TB → 考虑 TiDB / CockroachDB
    │
    └── 边缘场景 → IoT/嵌入式/资源受限?
                   │
                   ├── 是 → rqlite 是最佳选择 ✅
                   │
                   └── 否 → 评估团队经验和运维能力

14.1.2 推荐使用 rqlite 的场景

场景数据量读写比节点数推荐度
IoT 数据存储< 1GB8:23⭐⭐⭐⭐⭐
配置管理< 100MB9:13⭐⭐⭐⭐⭐
小型 SaaS 后端< 5GB7:33-5⭐⭐⭐⭐
CI/CD 状态存储< 1GB6:43⭐⭐⭐⭐
开发/测试环境任意任意1-3⭐⭐⭐⭐⭐
微服务元数据< 100MB8:23⭐⭐⭐⭐
边缘计算< 1GB7:33⭐⭐⭐⭐⭐

14.1.3 不推荐使用 rqlite 的场景

场景不推荐原因替代方案
TB 级数据存储SQLite 单文件限制PostgreSQL、TiDB
万级 TPS 写入Raft 复制瓶颈Redis Cluster、TiKV
复杂 OLAP 查询不支持分布式查询ClickHouse、DuckDB
多数据中心部署Raft 延迟敏感CockroachDB
需要存储过程SQLite 不支持PostgreSQL、MySQL
超低延迟读取(< 0.1ms)HTTP API 开销内嵌 SQLite + 同步复制

14.2 生产环境规范

14.2.1 部署规范

规范要求说明
节点数3 或 5必须为奇数
服务器最少 2 核 4GB根据数据量调整
磁盘SSD,≥ 50GBRaft 日志和 SQLite 文件
网络同机房,延迟 < 5msRaft 对延迟敏感
操作系统Linux(推荐 Ubuntu 22.04+)

14.2.2 启动参数规范

# 生产环境推荐启动参数
rqlited \
    -node-id=<唯一节点ID> \
    -http-addr=0.0.0.0:4001 \
    -raft-addr=0.0.0.0:4002 \
    -http-cert=/etc/rqlite/certs/server.crt \
    -http-key=/etc/rqlite/certs/server.key \
    -http-ca-cert=/etc/rqlite/certs/ca.crt \
    -node-cert=/etc/rqlite/certs/server.crt \
    -node-key=/etc/rqlite/certs/server.key \
    -node-ca-cert=/etc/rqlite/certs/ca.crt \
    -auth=/etc/rqlite/auth.json \
    -disco-mode=off \
    -fk \
    /var/lib/rqlite/data

14.2.3 认证配置规范

// /etc/rqlite/auth.json
[
    {
        "username": "admin",
        "password": "使用强密码(至少 16 字符,含大小写+数字+特殊字符)",
        "perm": "all"
    },
    {
        "username": "app_write",
        "password": "应用写入专用密码",
        "perm": "rw"
    },
    {
        "username": "app_read",
        "password": "应用只读密码",
        "perm": "ro"
    },
    {
        "username": "monitor",
        "password": "监控专用密码",
        "perm": "ro"
    }
]

安全原则: 最小权限原则。应用使用 rwro 账号,仅运维使用 all 账号。

14.2.4 systemd 服务规范

# /etc/systemd/system/rqlited.service
[Unit]
Description=rqlite distributed SQLite
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=rqlite
Group=rqlite
ExecStart=/opt/rqlite/start.sh
Restart=always
RestartSec=5
LimitNOFILE=65536

# 安全加固
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/rqlite /var/log/rqlite

# 资源限制
MemoryMax=2G
CPUQuota=200%

[Install]
WantedBy=multi-user.target

14.3 数据库设计规范

14.3.1 表设计规范

-- ✅ 推荐:使用明确的主键和类型
CREATE TABLE users (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    username TEXT NOT NULL UNIQUE,
    email TEXT NOT NULL UNIQUE,
    status TEXT CHECK(status IN ('active', 'inactive', 'banned')) DEFAULT 'active',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    updated_at DATETIME DEFAULT CURRENT_TIMESTAMP
);

-- ✅ 推荐:外键约束
CREATE TABLE orders (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    user_id INTEGER NOT NULL,
    total REAL NOT NULL CHECK(total >= 0),
    status TEXT CHECK(status IN ('pending', 'paid', 'shipped', 'completed')) DEFAULT 'pending',
    created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);

-- ✅ 推荐:为高频查询字段创建索引
CREATE INDEX idx_orders_user_status ON orders(user_id, status);
CREATE INDEX idx_orders_created ON orders(created_at DESC);
CREATE INDEX idx_users_status ON users(status);

14.3.2 索引规范

规则说明示例
为 WHERE 条件建索引高频查询字段必须有索引CREATE INDEX idx ON t(col)
复合索引顺序选择性高的列在前CREATE INDEX idx ON t(status, user_id)
避免过多索引每个索引增加写入开销只创建必要的索引
覆盖索引包含查询所需的所有列CREATE INDEX idx ON t(a, b, c)
定期 REINDEX碎片整理REINDEX idx_name

14.3.3 查询规范

-- ✅ 使用参数绑定
-- ❌ 字符串拼接(SQL 注入风险)
-- ✅ 仅选择需要的列
SELECT id, username, email FROM users WHERE id = ?;

-- ✅ 使用 LIMIT 限制结果集
SELECT * FROM orders WHERE status = 'pending' ORDER BY created_at DESC LIMIT 50;

-- ✅ 使用 EXPLAIN QUERY PLAN 分析查询
EXPLAIN QUERY PLAN SELECT * FROM orders WHERE user_id = 1 AND status = 'paid';

14.4 写入规范

14.4.1 批量写入

# ✅ 推荐:批量写入(50-100 条/批)
def batch_insert(records: list[dict], batch_size: int = 100):
    """分批插入数据"""
    for i in range(0, len(records), batch_size):
        batch = records[i:i + batch_size]
        statements = [
            ["INSERT INTO logs (level, message, ts) VALUES (?, ?, ?)",
             r["level"], r["message"], r["ts"]]
            for r in batch
        ]
        client.execute(statements)

14.4.2 读写分离

# ✅ 推荐:读写分离
def get_user(user_id: int) -> dict:
    """查询用户 — 弱一致性"""
    result = client.query(
        "SELECT * FROM users WHERE id = ?",
        params=[user_id],
        level="weak"  # 一般查询用 weak
    )
    return result

def create_order(order: dict) -> int:
    """创建订单 — 写入后读取用 strong"""
    client.execute(
        "INSERT INTO orders (user_id, product, total) VALUES (?, ?, ?)",
        params=[order["user_id"], order["product"], order["total"]]
    )
    # 写后读取用 strong 一致性
    result = client.query(
        "SELECT * FROM orders WHERE user_id = ? ORDER BY id DESC LIMIT 1",
        params=[order["user_id"]],
        level="strong"
    )
    return result["results"][0]["values"][0][0]

14.4.3 一致性级别选择指南

业务场景推荐级别理由
创建后立即查询strong保证读到刚写入的数据
列表查询weak可接受短暂延迟
统计报表none不需要实时准确
搜索建议none可接受缓存数据
下单操作strong关键业务,必须一致
日志写入任意日志可容忍少量丢失

14.5 备份与恢复规范

14.5.1 备份策略

环境频率格式保留天数存储位置
开发每天SQL dump7本地磁盘
测试每天SQL dump14本地磁盘
生产每 6 小时二进制 + SQL dump30S3 + 本地
金融每小时二进制 + SQL dump90多区域 S3

14.5.2 恢复演练

# 每月至少执行一次恢复演练
#!/bin/bash
# restore-drill.sh

BACKUP_FILE=$(ls -t /var/backup/rqlite/rqlite_*.sql.gz | head -1)
DRILL_DIR="/tmp/drill-$(date +%Y%m%d)"

mkdir -p "$DRILL_DIR/node1"

# 启动临时节点
rqlited -node-id=drill -disco-mode=off "$DRILL_DIR/node1" &
sleep 3

# 恢复数据
gunzip -c "$BACKUP_FILE" | curl -s -XPOST 'localhost:4001/db/load' \
    -H 'Content-Type: text/plain' --data-binary @-

# 验证数据
tables=$(curl -s -G 'localhost:4001/db/query' \
    --data-urlencode 'q=SELECT COUNT(*) FROM sqlite_master WHERE type="table"' \
    | python3 -c "import json,sys; print(json.load(sys.stdin)['results'][0]['values'][0][0])")

echo "恢复表数: $tables"

# 清理
kill %1
rm -rf "$DRILL_DIR"

14.6 监控规范

14.6.1 必须监控的指标

指标告警阈值说明
节点在线状态连续 30s 离线P0 告警
Leader 存在无 Leader 超过 30sP0 告警
复制延迟> 1000 条日志P2 告警
磁盘使用率> 85%P2 告警
数据库大小增长率异常P2 告警
HTTP 响应时间> 5sP2 告警
错误率> 1%P1 告警

14.6.2 健康检查脚本

#!/bin/bash
# health-check.sh — 生产环境健康检查

NODES=("node1:4001" "node2:4001" "node3:4001")
ERRORS=0

for node in "${NODES[@]}"; do
    host="${node%%:*}"
    port="${node##*:}"
    
    # 就绪检查
    code=$(curl -s -o /dev/null -w "%{http_code}" \
        "http://$node/status/ready" --connect-timeout 5)
    
    if [ "$code" != "200" ]; then
        echo "CRITICAL: $node not ready (HTTP $code)"
        ((ERRORS++))
    fi
done

if [ $ERRORS -gt 0 ]; then
    echo "CRITICAL: $ERRORS nodes unhealthy"
    exit 2
fi

echo "OK: All ${#NODES[@]} nodes healthy"
exit 0

14.7 容量规划

14.7.1 资源估算公式

内存需求 ≈ 数据大小 × 2(in-memory 模式)
         ≈ 数据大小 × 0.5 + 256MB(on-disk 模式)

磁盘需求 ≈ 数据大小 × 3(SQLite + Raft 日志 + 快照)

CPU 需求 ≈ 2 核起步,4 核推荐(取决于并发量)

14.7.2 容量规划表

数据量内存(in-memory)内存(on-disk)磁盘CPU
100 MB512 MB256 MB500 MB2 核
500 MB2 GB512 MB2 GB2 核
1 GB4 GB1 GB4 GB4 核
5 GB不推荐3 GB20 GB4 核
10 GB不推荐5 GB40 GB8 核

建议: 数据量超过 1GB 时使用 -on-disk 模式。


14.8 运维 Checklist

14.8.1 部署前检查

  • 服务器配置满足最低要求
  • 磁盘为 SSD
  • 网络延迟 < 5ms(节点间)
  • 防火墙已配置(4001、4002 端口)
  • TLS 证书已生成
  • auth.json 已创建
  • systemd 服务文件已配置
  • 备份脚本已部署
  • 监控已接入

14.8.2 日常运维检查

  • 每日检查节点状态
  • 每日检查备份执行情况
  • 每周检查磁盘使用率
  • 每月执行恢复演练
  • 每季度检查证书有效期
  • 每季度检查安全配置

14.8.3 版本升级检查

  • 阅读 Release Notes
  • 在测试环境验证
  • 备份当前数据
  • 滚动升级(先 Follower 后 Leader)
  • 升级后验证集群状态
  • 监控升级后 24 小时

14.9 架构建议

14.9.1 单集群 vs 多集群

单集群架构(推荐):
┌───────────────────────────────┐
│         rqlite 集群 (3节点)    │
│  ┌─────┐  ┌─────┐  ┌─────┐  │
│  │Node1│  │Node2│  │Node3│  │
│  └─────┘  └─────┘  └─────┘  │
└───────────────────────────────┘
适用:数据量 < 5GB,单机房

多集群架构:
┌─────────────────┐  ┌─────────────────┐
│ 集群 A (北京)    │  │ 集群 B (上海)    │
│ 3 节点           │  │ 3 节点           │
└────────┬────────┘  └────────┬────────┘
         │                    │
         └────────┬───────────┘
           应用层同步(非 Raft)
适用:跨地域部署,数据本地化

14.9.2 与其他存储组合

推荐架构:rqlite + Redis + 对象存储

┌──────────────────────────────────────────┐
│               应用层                      │
├──────────┬──────────────┬────────────────┤
│          │              │                │
│   ┌──────▼──────┐ ┌────▼─────┐ ┌───────▼───────┐
│   │   rqlite    │ │  Redis   │ │ 对象存储 (S3) │
│   │ 核心业务数据 │ │ 热数据缓存│ │ 文件/图片     │
│   │ 结构化数据   │ │ Session  │ │ 大文件        │
│   └─────────────┘ └──────────┘ └───────────────┘
│                                              │
│   rqlite: 配置、订单、用户等结构化数据         │
│   Redis: 缓存热点查询、Session、排行榜        │
│   S3: 图片、文件、备份                       │
└──────────────────────────────────────────┘

14.10 本指南总结

章节核心要点
第 1 章rqlite = SQLite + Raft,适合小到中规模
第 2 章推荐 3 节点,使用 -join 参数搭建集群
第 3 章三层架构:HTTP API → Raft → SQLite
第 4 章使用参数绑定,批量操作利用事务
第 5 章一致性级别 none/weak/strong 灵活选择
第 6 章Raft 自动选举,支持动态增删节点
第 7 章定期备份,保留 SQL dump + 二进制格式
第 8 章生产必须启用 TLS + 认证 + 防火墙
第 9 章批量写入是最重要的性能优化手段
第 10 章任何能发 HTTP 请求的语言都能作为客户端
第 11 章K8s 使用 StatefulSet + Headless Service
第 12 章Prometheus + Grafana 全面监控
第 13 章节点状态 → 集群状态 → 错误信息 → 日志
第 14 章适合场景明确,生产规范严格

扩展资源

上一章:第 13 章:故障排查