1. 业务场景与挑战
每日订单量1000万级,数据规模呈指数级增长:
- 年度数据量达36亿条
- 单表容量突破2000万性能临界点
- 高峰期并发请求量超过5万QPS
核心挑战聚焦三大维度:
- 存储成本:海量数据物理存储成本激增
- 查询效率:多维度组合查询响应超时
- 并发压力:实时订单状态查询流量洪峰
2. 存储压力如何解决
- 如何保证大数据量存储
通过分库分表
如何拆分?买家和卖家是否需要分开存储?
分开存储扩展已经查询性能都会好一些。
- 如何分库?
分库策略,通过用户ID 或者订单创建时间 取模 分库数量
分表策略:每个库内按月份分表
- 数据都要存储到数据库吗?
对于很多数据在近期都不会被查询,所以可以将数据做一个拆分,冷数据 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查询性能也会提升大一些。
- 比如买家查询最近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天内订单列表(高频过滤查询)
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 性能高的特性,以及引入本地缓存构建多级缓存体系进行优化。