文章目录
引言
在
架构思维:构建高并发写服务_从分库分表到全局 ID 策略与中间件选型和架构思维:构建随时可写的高可用写服务_从分库分表到无状态存储架构中,我们通过分库分表和无状态存储集群,保障了写业务的高可用和海量存储能力。但数据被严格按路由字段(如 userId)散布后,当需要按其他维度(如商家、来源、时间区间……)做查询时,传统分库分表架构就显得力不从心。
接下来将介绍三种主流方案,在不牺牲写性能和高可用的前提下,实现多维度富查询。
一、方案一:异构定制化实现
1. 思路
- 针对每种“非路由”维度,异构一套专用存储(例:按商家维度建商家库、按来源维度建来源库)。
- 同步方式常用 Binlog:实时订阅主库变更,写入异构存储。
2. 弊端
- 人力成本高:每来一个新维度,都需编写新的同步程序;
- 资源浪费:数据量成倍增长,存储与运维开销大。
二、方案二:借助分库网关实现
1. 代理式分库中间件
-
当 SQL 带路由字段,可直接路由至对应分库;
-
无路由字段时,网关多线程并发请求所有分库,合并结果:
- 精确查询(按订单号):向每库发单条查询;
- 排序+Limit:向每库各请求 N 条,再全局排序取 Top N。
2. 实践考量
- 调用量爆炸:分库数 M,每次查询需 M 倍后端请求;
- 网关压力大:CPU/内存消耗高,尤其是合并排序与深翻页场景;
- 内嵌式不合适:会占用业务机资源,影响写服务稳定性。
三、方案三:基于 ElasticSearch 实现
1. ES 优势
- 分布式、高可用:自带分片与副本机制,应对海量数据;
- 近实时索引:写入后可秒级搜索,无需批量异构;
- 丰富检索功能:倒排索引支持全文、精确、聚合、模糊等多种查询。
2. 架构与流程
-
Binlog 异构:订阅主库变更,将数据实时推送至 ES;
-
索引设计:
- 用 宽表 Document 代替多表关联(Nested 类型支持一对多);
- 对需模糊匹配字段分词,不需分词的用 keyword;
- 根据查询需求冗余必要字段(如省市县名称);
-
查询路由:所有 ES 节点均可接收请求,负责 fan-out 至分片并汇总结果;
-
深翻页问题:
- ES 默认最大取 10 000 条,超出报错;
- 推荐游标分页(search_after),避免深度偏移开销。
四、深翻页与游标分页
对于“第 1000 页”一类深翻页需求,无论是分库网关还是 ES,均不建议使用 offset+limit。这会造成前面 N 条数据全量扫描与排序,性能极差。正确做法是:
-- SQL 示例(ID 单调递增)
SELECT *
FROM t_order
WHERE createdTime > :lastTime
OR (createdTime = :lastTime AND id > :lastId)
ORDER BY createdTime, id
LIMIT :pageSize;
或 ES 的 search_after
参数,携带上次排序字段,保证高效分页。
五、方案优缺点对比与选型建议
方案 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
异构定制化 | 业务隔离、查询效率高 | 人力、资源开销大 | 维度固定、访问量大且对实时性要求不高 |
分库网关多库扫描 | 无需新存储,快速上线 | 调用量与网关压力暴增;深翻页严重受限 | 临时小流量搜索、精确查询场景 |
ElasticSearch 实时检索 | 功能丰富、支持复杂聚合与模糊、多维度实时查询 | 需运维 ES 集群、存储开销高;近实时有小延迟 | 多维度、模糊、聚合、全文检索场景;对实时性要求秒级 |
小结
分库分表后,面对无路由字段的查询,不能止步于“单一方案”,而要结合场景选择:
- 若维度数少且稳定,可用异构定制化;
- 若查询量小且对实时要求低,分库网关扫描可临时应急;
- 若多维度、模糊、聚合需求丰富,ES 是更成熟的解决方案。
在选型时,还需考虑组织对新技术的学习与运维能力,以及系统对延迟、吞吐与成本的平衡。