号段模式案例

wen java案例 1

本文目录导读:

号段模式案例

  1. 案例一:电商订单表按订单 ID 号段分片
  2. 案例二:银行/保险交易流水按日期(时间号段)分片
  3. 号段模式的致命弱点 & 高级优化方案(业界案例)
  4. 总结:什么业务适合用号段模式?

号段模式(也叫分段模式、Range模式)是数据库分库分表(Sharding)中非常经典的一种数据分片策略,它的核心思想是按照数据的某个连续范围(通常是ID或时间)将数据分散到不同的物理存储节点上

下面通过两个最典型的具体案例(一个按数值ID,一个按时间)来详细拆解号段模式的实战应用。


电商订单表按订单 ID 号段分片

业务场景:某电商平台订单表 t_order 数据量爆炸(已达数亿行),需要分库分表。

分片规则设定

  • 分片键:订单ID(order_id,BIGINT类型,由Snowflake算法生成)。
  • 分片策略:设定每1亿个订单ID为一个区间(段),映射到一个数据库实例。

架构示意(3库6表)

假设总共有3个数据库实例(DB0、DB1、DB2),每个库2张表(t_order_0、t_order_1):

  • DB0:存储订单ID范围 [1 ~ 1亿](t_order_0)、[1亿+1 ~ 2亿](t_order_1)
  • DB1:存储订单ID范围 [2亿+1 ~ 3亿](t_order_0)、[3亿+1 ~ 4亿](t_order_1)
  • DB2:存储订单ID范围 [4亿+1 ~ 5亿](t_order_0)、[5亿+1 ~ 6亿](t_order_1)

路由逻辑(伪代码)

当应用要查询订单时,代码首先计算订单ID所在段,再定位库和表:

public RouteResult routeByOrderId(long orderId) {
    // 1. 计算落在哪个库(按2亿/库切分)
    int dbIndex = (int) ((orderId - 1) / 200_000_000) % 3; 
    // 2. 计算落在该库的哪张表(按1亿/表切分)
    int tableSuffix = (int) ((orderId - 1) / 100_000_000) % 2; 
    return new RouteResult("DB" + dbIndex, "t_order_" + tableSuffix);
}

该模式的优缺点(在此案例中的体现)

  • 优点范围查询天然友好WHERE order_id BETWEEN 500000 AND 1000000 只需要查询DB0的t_order_0,无需全库扫描);扩容简单,只要申请一台新DB3,存放6亿+的数据即可,无需迁移旧数据(无数据Rebalance)。
  • 缺点热点问题严重,因为新订单ID总是递增,所有写入都会集中在最后一个号段节点(DB2的t_order_1),而早期的DB0、DB1数据库资源被闲置。

银行/保险交易流水按日期(时间号段)分片

业务场景:某银行核心交易流水表 t_trans_log,每日新增千万级数据,历史数据基本只读不写,且通常按日期查询。

分片规则设定

  • 分片键:交易时间(trans_time)。
  • 分片策略:按自然月切分,每个月的数据存放在独立的一个物理库中,DB_202401(存2024年1月)、DB_202402(存2024年2月)。

架构与归档策略

  • 每月1日零点,应用会自动创建下个月的新数据库分组。
  • 当月数据全部写入当前月份对应的库(如 DB_202410)。
  • 对于超过6个月的数据,业务上只做归档和财报查询,不提供秒级在线查询,系统会将老库设置成只读。

路由校验逻辑

public String getDataSourceKey(Date transTime) {
    // 根据月份直接定位库名,零计算成本
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMM");
    return "DB_" + sdf.format(transTime);
}

应用场景:针对“查上个月的账单”、“查今年1月到3月的流水”这类带时间区间的SQL,可以精确打散到对应的1~3个月库中并行查询

优缺点(在此案例中的体现)

  • 优点:写入天然均匀分布(每个月都有新写入);冷热数据分离,硬件成本控制极佳(老数据可以转移到廉价存储);极度适配财报/对账这种强时间范围的业务。
  • 缺点:如果遇到“双11”或“季末清算”等特定月份,该月的流量会突然暴增,导致单月数据库压力过大(数据倾斜);跨2个月的查询需要UNION结果集。

号段模式的致命弱点 & 高级优化方案(业界案例)

在实际互联网高并发场景下,纯号段模式(案例一)很难直接使用,因为热点无法解决,业界通常使用“基因法”或“时间混排标准号段模式”

混合号段(业务前缀+顺序号)

很多大厂会让订单号包含“用户ID的基因位”,例如订单号设计为 用户ID后4位 (4位数字) + 时间戳 (10位) + 随机数 (2位),路由规则改为:根据用户ID的后4位(0~9999)分配号段到1000个逻辑分片

  • 这样一来,同一个用户的订单永远落在同一个库(方便查询),而不同用户的订单会均匀落在不同库。
  • 成功消除了“新数据全部写在最后一个库”的热点问题,兼顾了号段模式扩容简单的优点(新增节点只需调整映射范围)。

什么业务适合用号段模式?

适合场景 不适合场景
日志、流水、审计记录(按时间归档) 微博、微信朋友圈(高频写入且追求实时全局排序)
订单总量明确且大,但活跃写入用户量巨大且均衡 低频业务但单点用户数据量极大(如某个大V发几万条长文)

核心决策点:如果你的业务查询条件常带有明确的范围(时间或ID排序),且能容忍某个时间段/区间的数据集中,那么号段模式会是非常简单高效的方案,如果无法容忍热点,则建议选用一致性哈希基因法号段模式

抱歉,评论功能暂时关闭!