分库之后,很多原来一条 SQL 能解决的问题都会变复杂。比如按“门店 + 时间段”统计预约单数量,如果订单按用户或会员维度分库,就不能再直接从一个库里做聚合查询。
这类问题可以按实时性、查询维度和实现成本拆开看。
直接查库为什么容易失败
如果预约单分散在多个分库里,直接查询会遇到几个问题:
- 需要跨库聚合。
- 查询链路变长。
- 分片数量越多,查询成本越高。
- 高峰期容易把数据库压垮。
所以分库后的统计查询,通常不能简单复用单库时代的写法。
Redis 计数的第一种思路
比较直观的方案是:下单时通过 MQ 消费 +1,取消时 -1,把结果写入 Redis。
Key 可以设计成:
reservation:{shop_id}:{date}:{time_slot}
这种方式的好处是原子性清楚,单个 key 的增减很好处理。问题是 key 会非常多,后续按日期或门店遍历时容易变慢。如果还依赖 SCAN 做大范围查询,就要非常小心。
Redis Hash 粗粒度聚合
另一种方式是把 key 变粗,例如按“门店 + 日期”建一个 Hash:
reservation:{shop_id}:{date}
Hash field 可以是小时段或半小时段:
07:00 -> 12
07:30 -> 8
08:00 -> 16
这样一个门店一天的数据集中在一个 Hash 里,查询当天数据会更方便。
不过生产环境不要随意对大 Hash 使用 HGETALL。如果 field 可能很多,更稳妥的是使用 HSCAN 分批读取,避免一次性拉取导致阻塞或内存压力。
Redis 方案要补哪些保护
Redis 计数不是只写 INCR 就结束,还要考虑:
- 消息重复消费时的幂等。
- 多实例消费者同时写入时的一致性。
- 取消单和下单事件乱序时的修正策略。
- Key 的 TTL 和历史数据保留周期。
- 大 key 和热 key 的监控。
如果统计维度简单、实时性要求高,Redis 很适合。但如果过滤条件越来越多,Redis key 设计会越来越难维护。
Elasticsearch 适合什么场景
如果需求变成按门店、时间、状态、业务类型等多个维度组合查询,Elasticsearch 会更适合。它的优点是:
- 多维过滤方便。
- 聚合查询能力强。
- 对后台报表类查询更友好。
- 后续扩展字段成本较低。
缺点也明显:ES 有写入延迟,不适合强实时扣减类场景。如果业务能接受秒级延迟,ES 可以作为读模型。
取舍建议
我的倾向是:
- 强实时、简单维度:Redis 计数。
- 多维过滤、后台查询、允许延迟:Elasticsearch。
- 数据库只保留事实数据,不承担高频跨片聚合。
分库后的统计设计,关键不是选一个“最强组件”,而是先确认查询是否强实时、维度是否会扩展、数据是否需要可追溯。确认这些之后,再选 Redis、ES 或两者组合会稳很多。




