分库分表(四)

真实互联网公司常见的订单分库分表架构设计。这个设计基本是很多大厂(电商、外卖、支付系统)使用的模式。🚀

我会从 设计目标 → 分片键选择 → 分库分表结构 → 表结构设计 → 查询优化 → 扩容方案 一步一步讲。


一、订单系统的真实规模

假设一个电商系统:

指标 数量
每天订单 1000万
每年订单 36亿
订单表数据 几十亿

如果只有一张表:

复制代码

order

问题:

  • 表太大(几十亿行)

  • 索引巨大

  • 查询慢

  • MySQL 扛不住

所以必须:

复制代码

分库 + 分表


二、常见分库分表结构

典型架构:

复制代码

Application

ShardingSphere

┌───────────┼───────────┐

│ │ │

DB0 DB1 DB2 DB3

order_0..7 order_0..7 order_0..7 order_0..7

总表数量:

复制代码

4库 × 8表 = 32张订单表

逻辑表:

复制代码

order

真实表:

复制代码

db0.order_0

db0.order_1

...

db3.order_7


三、为什么订单要按 user_id 分片(重点)

很多人第一反应:

复制代码

按 order_id 分片

大厂基本不会这样做

原因:

1 用户订单查询最多

用户最常见操作:

复制代码

查看我的订单

SQL:

复制代码

SELECT * FROM order WHERE user_id = ?

如果按 user_id 分片:

复制代码

user_id % 32

只查:

复制代码

1张表

如果按 order_id 分片:

复制代码

必须扫描32张表

性能很差。


2 用户订单列表

例如:

复制代码

用户订单列表

SQL:

复制代码

SELECT * FROM order

WHERE user_id = 1001

ORDER BY create_time DESC

LIMIT 10

按 user_id 分片:

复制代码

只查一个表

速度极快。


四、分片算法设计

假设:

复制代码

4库

8表

总分片数:

复制代码

32

算法:

复制代码

dbIndex = user_id % 4

tableIndex = user_id % 8

最终表:

复制代码

db{dbIndex}.order_{tableIndex}

例子:

复制代码

user_id = 1001

计算:

复制代码

1001 % 4 = 1

1001 % 8 = 1

路由:

复制代码

db1.order_1


五、ShardingSphere 配置示例

复制代码

spring:

shardingsphere:

datasource:

names: ds0,ds1,ds2,ds3

rules:

sharding:

tables:

order:

actual-data-nodes: ds-\>{0..3}.order_->{0..7}

database-strategy:

standard:

sharding-column: user_id

sharding-algorithm-name: db_inline

table-strategy:

standard:

sharding-column: user_id

sharding-algorithm-name: order_inline

sharding-algorithms:

db_inline:

type: INLINE

props:

algorithm-expression: ds$->{user_id % 4}

order_inline:

type: INLINE

props:

algorithm-expression: order_$->{user_id % 8}


六、订单表真实结构(非常重要)

互联网订单表一般不会只存 ID。

典型结构:

复制代码

CREATE TABLE order_0 (

id BIGINT PRIMARY KEY,

user_id BIGINT,

user_name VARCHAR(64),

shop_id BIGINT,

shop_name VARCHAR(128),

product_id BIGINT,

product_name VARCHAR(128),

price DECIMAL(10,2),

status INT,

create_time DATETIME

);

注意:

复制代码

user_name

shop_name

product_name

这些都是:

复制代码

冗余字段

原因:

避免 JOIN。


七、订单系统为什么大量冗余字段

如果不冗余:

复制代码

SELECT *

FROM order o

JOIN user u

JOIN product p

在分库环境:

复制代码

非常慢

互联网解决方案:

复制代码

订单快照

订单生成时:

复制代码

复制用户信息

复制商品信息

所以订单表里会有:

复制代码

buyer_name

buyer_phone

product_name

shop_name

好处:

复制代码

订单查询无需 join


八、订单表必须有的索引

订单系统最常见查询:

1 用户订单

复制代码

WHERE user_id

索引:

复制代码

(user_id, create_time)


2 单个订单

复制代码

WHERE id

主键:

复制代码

id


3 商家订单

复制代码

WHERE shop_id

索引:

复制代码

(shop_id, create_time)


九、主键生成(雪花算法)

订单 ID 不用自增。

因为:

复制代码

分库后无法自增

一般用:

复制代码

Snowflake

64位ID:

复制代码

时间戳 + 机器ID + 序列号

ShardingSphere 自带:

复制代码

key-generators:

snowflake:

type: SNOWFLAKE

优点:

复制代码

全局唯一

高性能


十、历史订单如何处理

订单表会越来越大。

解决方案:

复制代码

冷热数据分离

例如:

复制代码

order_hot (最近3个月)

order_hist (历史订单)

查询:

复制代码

最近订单 → hot

历史订单 → hist


十一、未来扩容问题

假设:

复制代码

32表

不够用了。

扩容:

复制代码

32 → 64

问题:

复制代码

旧数据怎么办?

解决:

复制代码

一致性哈希

双写迁移

很多公司用:

复制代码

ShardingSphere Scaling

在线迁移数据。


十二、完整订单系统架构

真实架构:

复制代码

API

Order Service

ShardingSphere

┌───────────┼───────────┐

│ │ │

DB0 DB1 DB2

order_0..7 order_0..7 order_0..7

配合:

复制代码

Redis 订单缓存

Kafka 订单消息

ES 订单搜索


十三、真实互联网订单查询流程

用户打开订单列表:

复制代码

APP

API

OrderService

ShardingSphere

db1.order_3

只查:

复制代码

1张表

速度:

复制代码

毫秒级


十四、总结(核心设计)

互联网订单系统核心设计:

1 分片键

复制代码

user_id

原因:

复制代码

用户查询最多


2 分库分表

复制代码

4库 × 8表


3 冗余字段

避免:

复制代码

跨库 join


4 雪花ID

保证:

复制代码

全局唯一


十五、一个真正的架构经验(非常重要)

很多新系统一开始:

复制代码

只建一张 order 表

等数据上亿:

复制代码

再拆分

这会非常痛苦。

正确方式:

复制代码

一开始就设计分库分表

即使:

复制代码

只有几万数据

相关推荐
gmaajt19 小时前
mysql如何备份与恢复函数定义_mysql mysqldump导出存储对象
jvm·数据库·python
阿丰资源20 小时前
基于SpringBoot的在线视频教育平台的设计与实现(附源码+数据库+文档,一键运行)
数据库·spring boot·后端
qq_4609784020 小时前
Python爬虫怎么模拟手机端抓取_设置手机型号User-Agent字符串
jvm·数据库·python
m0_617881421 天前
如何高效进行堆叠分类器的超参数调优:解决 GridSearchCV 卡顿问题
jvm·数据库·python
编程自留地1 天前
项目sql语句
前端·数据库·sql
m0_588758481 天前
如何高效批量删除SQL数据_使用脚本分段删除降低压力
jvm·数据库·python
abc123456sdggfd1 天前
Layui表单验证失败时如何修改默认弹出的Tips气泡颜色
jvm·数据库·python
Bert.Cai1 天前
MySQL TRIM()函数详解
数据库·mysql
2301_800976931 天前
数据库的基本操作后续
java·数据库·sql
SECS/GEM1 天前
SECS/GEM如何实现越南现场自定义消息
java·服务器·数据库