3.1 什么是数据库路由?
在分库分表或多数据库实例架构中,**数据库路由模块(SQL Router)**的作用是:
将客户端发来的 SQL 请求路由到正确的后端数据库实例或分片表中执行。
它是数据库中间件的核心组件之一。
3.2 数据库路由的关键职责
职责 | 说明 |
---|---|
SQL 分析 | 对接收到的 SQL 做语义分析 |
路由决策 | 根据 SQL 类型、表名、路由规则等判断目标节点 |
请求重写 | 根据路由规则修改 SQL(如表名改为 user_01 ) |
多节点分发 | 将请求发往多个节点并聚合结果(如跨库分页) |
3.3 路由流程概览
以下为典型的路由流程:
-
客户端发送 SQL 到中间件
-
中间件解析 SQL(抽取表名、操作类型、条件等)
-
根据规则生成路由策略(如哈希取模、范围映射)
-
重写 SQL(如修改表名、拼接 LIMIT)
-
发送到对应数据库节点执行
-
中间件接收返回并聚合(如 JOIN 结果)
3.4 常见路由策略(SQL Routing Strategy)
① 静态路由(Static Routing)
-
固定 SQL 请求指向某一数据库
-
适用于主备读写分离、特定业务专库场景
② 哈希路由(Hash Routing)
-
按某字段(如 user_id)取哈希,再对分片数取模
-
target_db = hash(user_id) % N
③ 范围路由(Range Routing)
-
按某个字段的值落入的范围选择分库
-
例:
user_id in 1~10000
→ DB1,10001~20000
→ DB2
④ 标签路由(Tag Routing)
-
根据请求来源、业务标签、租户 ID 等进行路由
-
多租户 SaaS 场景常用
⑤ 广播路由(Broadcast Routing)
-
执行同一 SQL 到所有分库,适用于查询类语句
-
查询后中间件合并结果
3.5 路由模块原型设计(Python 示意)
python
class SQLRouter:
def __init__(self, shards):
self.shards = shards # 模拟数据库节点:['db1', 'db2', 'db3']
def route(self, sql, shard_key=None):
if "INSERT" in sql.upper() and shard_key is not None:
index = hash(shard_key) % len(self.shards)
return self.shards[index]
elif "SELECT" in sql.upper():
return "broadcast"
else:
return self.shards[0]
# 使用示例
router = SQLRouter(["db1", "db2", "db3"])
sql1 = "INSERT INTO users (id, name) VALUES (1001, 'Tom')"
sql2 = "SELECT * FROM users WHERE id = 1001"
print(router.route(sql1, shard_key=1001)) # 可能为 db2
print(router.route(sql2)) # broadcast
3.6 SQL 分析与重写技术
在路由前通常需要对 SQL 做如下处理:
-
语法分析:使用 SQL 解析器抽取语句类型、表名、WHERE 条件
-
抽象语法树(AST):构建并遍历 AST 节点确定字段值
-
重写 SQL :将逻辑表
user
改写为物理表user_01
、添加数据库前缀等
可使用开源 SQL Parser 工具(如 sqlparse、TiDB parser)
3.7 跨分片查询处理策略
场景 | 处理方式 |
---|---|
多表 JOIN | 拆分后在中间件做 JOIN 聚合 |
ORDER BY + LIMIT | 各库查询后聚合再排序截断 |
聚合函数(COUNT、SUM) | 各库执行后结果合并 |
💡 建议设计之初尽量避免跨分片 JOIN 和分页。
3.8 路由模块设计要点
-
🧱 支持灵活规则配置(支持多策略并存)
-
⚙️ 高性能 SQL 解析器
-
🧭 清晰的路由决策逻辑
-
🔐 读写分离策略支持
-
🧩 SQL 重写模块与执行器解耦
小结
-
SQL 路由模块是中间件的核心,决定请求如何分发
-
关键能力包括:SQL 分析、路由决策、SQL 重写
-
常见策略有哈希、范围、标签、广播等
-
实际中需兼顾性能、可维护性、扩展性