外卖平台每天有1000万笔订单查询怎么优化?

1. 业务场景与挑战

每日订单量1000万级,数据规模呈指数级增长:

  • 年度数据量达36亿条
  • 单表容量突破2000万性能临界点
  • 高峰期并发请求量超过5万QPS

核心挑战聚焦三大维度:

  1. 存储成本:海量数据物理存储成本激增
  2. 查询效率:多维度组合查询响应超时
  3. 并发压力:实时订单状态查询流量洪峰

2. 存储压力如何解决

  1. 如何保证大数据量存储

通过分库分表

如何拆分?买家和卖家是否需要分开存储?

分开存储扩展已经查询性能都会好一些。

  1. 如何分库?

分库策略,通过用户ID 或者订单创建时间 取模 分库数量

分表策略:每个库内按月份分表

  1. 数据都要存储到数据库吗?

对于很多数据在近期都不会被查询,所以可以将数据做一个拆分,冷数据 and 热数据。

30 天内的数据 -> MySQL

超过30天的数据 -> TiDB or ClickHouse ...

3. 复杂业务场景如何解决?

举个例子,比如查询卖家过去30天内金额>100元且为己完成状态的某类订单?

通过ES是不是更加高效?

  • 索引设计:建立seller_id + create_time + order_status联合索引
  • 数据同步:基于Binlog实现准实时同步
json 复制代码
// 多条件组合查询DSL优化
{
  "query": {
    "bool": {
      "filter": [
        {"term": {"seller_id": 98765}},
        {"range": {"create_time": {"gte": "now-30d/d"}}},
        {"script": {"script": "doc['order_amount'].value >= 100"}}
      ],
      "must": [
        {"term": {"order_status": "completed"}},
        {"match": {"order_type": "takeout"}}
      ]
    }
  },
  "preference": "primary_first" // 优先主分片提升稳定性
}
​

4. 热点数据查询如何解决?

对于热点数据,查询 ES 或者 MySQL 无疑是带来很大压力以及性能也会比较差。

举个例子,买家查询最近10条订单数?卖家最近1天内所有订单列表;

对于这种热点数据,我们可以缓存到 Redis 中,对于热点数据存储到Redis就好,查询中走Redis查询性能也会提升大一些。

  1. 比如买家查询最近10条订单(读多写少场景)
ruby 复制代码
# Key: 用户维度 + 业务标识
buyer:orders:{user_id}:recent  # 例如 buyer:orders:12345:recent
​
# Value: 用 Redis List 存储订单ID(按时间倒序)
[
  "order_id_100",  # 最新订单
  "order_id_99",
  ...
  "order_id_91"    # 第10条订单
]
​
# 或用 Hash 存储订单详情(如果需缓存完整数据)
{
  "order_id_100": "{订单JSON}",
  "order_id_99": "{订单JSON}",
  ...
}
​
  1. 卖家最近1天内订单列表(高频过滤查询)
csharp 复制代码
# Key: 卖家ID + 时间范围
seller:orders:{seller_id}:last_24h  # 例如 seller:orders:98765:last_24h
​
# Value: 用 Sorted Set (ZSET) 存储订单ID和创建时间戳
# Score = 订单时间戳, Member = 订单ID
[
  [1640995200, "order_id_100"],
  [1640995201, "order_id_101"],
  ...
]
​
# 或用 Hash 存储订单详情(按需)
{
  "order_id_100": "{订单JSON}",
  "order_id_101": "{订单JSON}",
  ...
}
​

5. 总结

对于存储压力比较大,可以采用分库分表优化,采用合理的分库分表手段以及分片键的选取。对于久远数据,为了避免干扰目前的查询,可以采用冷热数据分离。

为了解决复杂的查询条件,可以采用ES查询优化。

对于热点数据,可以采用将近期内的订单数据缓存到 Redis 中,利用 Redis 性能高的特性,以及引入本地缓存构建多级缓存体系进行优化。

相关推荐
爱勇宝15 小时前
第 1 章:别把“需求文档”当成真正的需求
前端·后端·程序员
IT_陈寒19 小时前
闭包陷阱让我加了两天班,JavaScript你真行
前端·人工智能·后端
易协同低代码20 小时前
通达OA核心类库TD类深度解析
后端
Gopher_HBo20 小时前
Go语言学习笔记(十八)Gin处理Session
后端
谭光志21 小时前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
她说..21 小时前
Java 默认值设置方式
java·开发语言·后端·springboot
foggyprojects21 小时前
从0开始,一句话启动AI DataAgent
后端·数据分析·ai编程
郡杰21 小时前
一些基础和问题解决
后端
陈随易1 天前
前端项目部署只要30秒
前端·后端·程序员
YIAN1 天前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp