第 5 章:HTTP API 详解
第 5 章:HTTP API 详解
全面掌握 rqlite 的 HTTP API,包括参数绑定、一致性级别、事务和批量操作。
5.1 API 概述
rqlite 提供 RESTful HTTP API,所有数据库操作通过以下端点完成:
| 端点 | 方法 | 说明 | 一致性要求 |
|---|---|---|---|
/db/query | GET, POST | SQL 查询(SELECT) | 可配置 |
/db/execute | POST | SQL 执行(INSERT/UPDATE/DELETE/DDL) | 强一致性 |
/db/request | POST | 混合请求 | 按语句配置 |
/db/backup | GET | 数据库备份 | 强一致性 |
/db/load | POST | 数据加载/恢复 | 强一致性 |
/status | GET | 节点状态 | — |
/nodes | GET | 集群节点列表 | — |
/join | POST | 加入集群 | — |
/remove | POST | 移除节点 | — |
/status/ready | GET | 健康检查 | — |
/status/leader | GET | Leader 检查 | — |
5.2 查询 API (/db/query)
5.2.1 GET 方式查询
# 基本 GET 查询
curl -G 'localhost:4001/db/query' \
--data-urlencode 'q=SELECT * FROM users LIMIT 10'
# 多个查询语句
curl -G 'localhost:4001/db/query' \
--data-urlencode 'q=SELECT * FROM users' \
--data-urlencode 'q=SELECT COUNT(*) FROM orders'
# 带一致性级别
curl -G 'localhost:4001/db/query' \
--data-urlencode 'q=SELECT * FROM users' \
--data-urlencode 'level=strong'
# 带超时时间
curl -G 'localhost:4001/db/query' \
--data-urlencode 'q=SELECT * FROM users' \
--data-urlencode 'timeout=10s'
# 美化输出
curl -G 'localhost:4001/db/query' \
--data-urlencode 'q=SELECT * FROM users' \
--data-urlencode 'pretty'
5.2.2 POST 方式查询
# JSON body 方式(适合复杂参数)
curl -XPOST 'localhost:4001/db/query' \
-H 'Content-Type: application/json' \
-d '{
"statements": [
{"q": "SELECT * FROM users WHERE age > ?", "v": [25]},
{"q": "SELECT COUNT(*) FROM orders"}
],
"level": "strong",
"pretty": true
}'
5.2.3 一致性级别详解
| 级别 | 行为 | 延迟 | 适用场景 |
|---|---|---|---|
none | 任意节点本地读取,不保证一致性 | 最低 | 统计数据、缓存查询 |
weak | 尽量从 Leader 读,不确认 Leader 身份 | 低 | 一般业务查询 |
strong | 强制从 Leader 读,并确认 Leader 身份 | 高 | 事务后的读取、关键业务 |
# 不同一致性级别示例
# none — 可能从 Follower 读到过期数据
curl -G 'localhost:4001/db/query' --data-urlencode 'level=none' --data-urlencode 'q=SELECT COUNT(*) FROM orders'
# strong — 保证读到最新数据
curl -G 'localhost:4001/db/query' --data-urlencode 'level=strong' --data-urlencode 'q=SELECT COUNT(*) FROM orders'
5.2.4 查询参数汇总
| 参数 | 说明 | 默认值 |
|---|---|---|
q | SQL 查询语句 | 必填 |
level | 一致性级别 | weak |
timeout | 查询超时 | 10s |
pretty | 美化 JSON 输出 | false |
associative | 以对象数组返回结果 | false |
timings | 显示执行时间 | false |
# associative 模式 — 列名作为 key
curl -G 'localhost:4001/db/query' \
--data-urlencode 'q=SELECT * FROM users LIMIT 1' \
--data-urlencode 'associative'
响应对比:
// 默认模式 (values 数组)
{
"columns": ["id", "username", "email"],
"values": [[1, "zhangsan", "[email protected]"]]
}
// associative 模式 (对象数组)
{
"columns": ["id", "username", "email"],
"types": ["integer", "text", "text"],
"values": [
{"id": 1, "username": "zhangsan", "email": "[email protected]"}
]
}
5.3 执行 API (/db/execute)
5.3.1 基本执行
# 单条语句
curl -XPOST 'localhost:4001/db/execute' \
-H 'Content-Type: application/json' \
-d '[["INSERT INTO users (username, email, age) VALUES (?, ?, ?)", "test", "[email protected]", 20]]'
# 多条语句(同一事务)
curl -XPOST 'localhost:4001/db/execute' \
-H 'Content-Type: application/json' \
-d '[
["INSERT INTO users (username, email) VALUES (?, ?)", "user1", "[email protected]"],
["INSERT INTO users (username, email) VALUES (?, ?)", "user2", "[email protected]"],
["INSERT INTO orders (user_id, product, quantity, price) VALUES (?, ?, ?, ?)", 1, "商品A", 2, 100.0]
]'
5.3.2 JSON body 格式
curl -XPOST 'localhost:4001/db/execute' \
-H 'Content-Type: application/json' \
-d '{
"statements": [
{"q": "INSERT INTO users (username, email) VALUES (?, ?)", "v": ["user3", "[email protected]"]},
{"q": "UPDATE users SET age = ? WHERE username = ?", "v": [25, "user3"]}
],
"timings": true
}'
5.3.3 参数绑定方式
rqlite 支持两种参数绑定格式:
方式一:位置参数(Positional)
{
"q": "INSERT INTO users (username, email) VALUES (?, ?)",
"v": ["zhangsan", "[email protected]"]
}
方式二:命名参数(Named)
{
"q": "INSERT INTO users (username, email) VALUES (:name, :email)",
"v": {"name": "zhangsan", "email": "[email protected]"}
}
安全警告: 永远使用参数绑定,不要拼接 SQL 字符串!拼接 SQL 会导致注入攻击。
# ❌ 错误 — SQL 注入风险
rxe '[["INSERT INTO users (username) VALUES (\"admin\" OR 1=1 --)\"]]'
# ✅ 正确 — 参数绑定
rxe '[["INSERT INTO users (username) VALUES (?)", "admin"]]'
5.4 混合请求 API (/db/request)
/db/request 允许在同一个请求中混合查询和执行操作:
curl -XPOST 'localhost:4001/db/request' \
-H 'Content-Type: application/json' \
-d '{
"statements": [
{"q": "INSERT INTO users (username, email) VALUES (?, ?)", "v": ["newuser", "[email protected]"]},
{"q": "SELECT * FROM users ORDER BY id DESC LIMIT 1"}
]
}'
响应中既有执行结果也有查询结果:
{
"results": [
{
"last_insert_id": 10,
"rows_affected": 1,
"time": 0.000234
},
{
"columns": ["id", "username", "email", "age", "created_at"],
"types": ["integer", "text", "text", "integer", "datetime"],
"values": [[10, "newuser", "[email protected]", 0, "2026-05-10 12:00:00"]],
"time": 0.000123
}
]
}
注意:
/db/request中的所有语句在同一事务中执行,确保原子性。
5.5 事务处理
5.5.1 隐式事务
rqlite 默认将单次请求中的多条语句包装在事务中:
# 这三条语句在同一事务中执行
rxe '[
["BEGIN"],
["INSERT INTO accounts (name, balance) VALUES (?, ?)", "A", 1000],
["UPDATE accounts SET balance = balance - 100 WHERE name = ?", "A"],
["COMMIT"]
]'
5.5.2 显式事务
# 显式 BEGIN/COMMIT
rxe '[
["BEGIN"],
["UPDATE accounts SET balance = balance - 200 WHERE name = ?", "A"],
["UPDATE accounts SET balance = balance + 200 WHERE name = ?", "B"],
["COMMIT"]
]'
重要: rqlite 中 BEGIN/COMMIT 会被转换为 SQLite 本地事务。Raft 日志复制保证操作顺序,但不等同于分布式两阶段提交。
5.5.3 事务回滚
# 如果某条语句失败,整个事务回滚
rxe '[
["BEGIN"],
["INSERT INTO users (username, email) VALUES (?, ?)", "ok_user", "[email protected]"],
["INSERT INTO users (username, email) VALUES (?, ?)", "duplicate_name", "[email protected]"],
["INSERT INTO users (username, email) VALUES (?, ?)", "duplicate_name", "[email protected]"],
["COMMIT"]
]'
如果 duplicate_name 违反了唯一约束,整个请求会返回错误,所有操作被回滚。
5.6 备份与恢复 API
5.6.1 备份
# SQLite dump 格式备份
curl -s 'localhost:4001/db/backup' -o backup.sql
# 二进制数据库备份
curl -s 'localhost:4001/db/backup?fmt=binary' -o backup.db
# 加载 dump 文件恢复
curl -XPOST 'localhost:4001/db/load' \
-H 'Content-Type: text/plain' \
--data-binary @backup.sql
5.7 错误处理
5.7.1 常见 HTTP 状态码
| 状态码 | 说明 | 常见原因 |
|---|---|---|
| 200 | 成功 | — |
| 400 | 请求格式错误 | JSON 解析失败、SQL 语法错误 |
| 401 | 未认证 | 缺少认证信息 |
| 403 | 无权限 | 认证通过但权限不足 |
| 404 | 不存在 | 端点不存在或节点不存在 |
| 409 | 冲突 | 集群状态冲突(非 Leader) |
| 500 | 内部错误 | SQLite 执行错误、Raft 错误 |
| 503 | 服务不可用 | 集群无 Leader |
5.7.2 错误响应格式
{
"results": [
{
"error": "UNIQUE constraint failed: users.username"
}
],
"time": 0.000234
}
# 检查错误
curl -s -XPOST 'localhost:4001/db/execute' \
-H 'Content-Type: application/json' \
-d '[["INSERT INTO users (username, email) VALUES (?, ?)", "zhangsan", "[email protected]"]]' \
| python3 -c "
import json, sys
resp = json.load(sys.stdin)
for r in resp.get('results', []):
if 'error' in r:
print(f'Error: {r[\"error\"]}')
else:
print(f'OK: rows_affected={r[\"rows_affected\"]}')
"
5.8 实用 curl 技巧
5.8.1 美化输出脚本
#!/bin/bash
# rq.sh — rqlite 查询助手
HOST=${RQLITE_HOST:-localhost:4001}
query() {
curl -s -G "http://$HOST/db/query" \
--data-urlencode "q=$1" \
--data-urlencode "pretty" \
--data-urlencode "level=${2:-weak}" | python3 -m json.tool
}
execute() {
curl -s -XPOST "http://$HOST/db/execute" \
-H 'Content-Type: application/json' \
-d "$1" | python3 -m json.tool
}
# 使用示例
# query "SELECT * FROM users LIMIT 5"
# execute '[["INSERT INTO users (username) VALUES (?)", "test"]]'
5.8.2 超时和重试
# 设置连接超时和最大超时
curl --connect-timeout 5 --max-time 30 \
-G 'localhost:4001/db/query' \
--data-urlencode 'q=SELECT * FROM users'
# 自动重试脚本
for i in {1..3}; do
result=$(curl -s -w "%{http_code}" -G 'localhost:4001/db/query' --data-urlencode 'q=SELECT 1')
code=${result: -3}
if [ "$code" = "200" ]; then
echo "Success"
break
fi
echo "Attempt $i failed ($code), retrying..."
sleep 1
done
5.9 API 性能对比
| API | 语句数 | 平均延迟 | 吞吐量 |
|---|---|---|---|
| 单条 Execute | 1 | ~2ms | ~500 ops/s |
| 批量 Execute | 10 | ~5ms | ~2000 ops/s |
| 批量 Execute | 100 | ~25ms | ~4000 ops/s |
| Query (weak) | 1 | ~1ms | ~1000 ops/s |
| Query (strong) | 1 | ~2ms | ~500 ops/s |
| Query (none) | 1 | ~0.5ms | ~2000 ops/s |
提示: 批量操作性能显著优于逐条操作。生产环境中应尽量使用批量 API。
5.10 本章小结
| 要点 | 内容 |
|---|---|
| 查询端点 | /db/query,支持 GET 和 POST |
| 执行端点 | /db/execute,仅 POST |
| 混合端点 | /db/request,同一请求中混合读写 |
| 参数绑定 | ? 位置参数或 :name 命名参数 |
| 一致性 | none/weak/strong 三级可选 |
| 事务 | 多条语句默认在同一事务中执行 |
| 错误处理 | 检查响应中的 error 字段 |
上一章:第 4 章:基础操作 下一章:第 6 章:集群管理