中间件场景题归纳(二)

1、Nginx作为反向代理服务器,可以实现哪些负载均衡策略?如果一台上游服务器(Upstream)宕机,Nginx如何处理?

● 负载均衡策略

四大负载均衡策略,Nginx提供了多种策略,就像不同的兵法,适用于不同的作战场景。

○ 轮询 (Round Robin)

默认策略,将请求按时间顺序逐一分配到不同的后端服务器。

复制代码
http {
    upstream geek_mall {
        server 192.168.1.101:8080; # 服务器A
        server 192.168.1.102:8080; # 服务器B
        server 192.168.1.103:8080; # 服务器C
    }
​
    server {
        listen 80;
        location / {
            proxy_pass http://geek_mall;
        }
    }
}
  • 请求流向:第1个请求 -> A,第2个请求 -> B,第3个请求 -> C,第4个请求 -> A,如此循环。

  • 适用场景所有后端服务器硬件配置、性能几乎完全相同的情况。这是最单纯、最公平的策略。

○ 加权轮询 (Weighted Round Robin):

根据服务器配置和性能,为其分配不同的权重。权重越高,被分配到的请求越多。

复制代码
upstream geek_mall {
    server 192.168.1.101:8080 weight=3; # 高性能服务器,权重3
    server 192.168.1.102:8080 weight=2; # 中等性能,权重2
    server 192.168.1.103:8080 weight=1; # 旧机器,权重1
}
  • 请求流向:在多个请求周期内,请求会按3:2:1的比例分配。比如,前6个请求的分配可能是:A, A, A, B, B, C。

  • 适用场景后端服务器性能不均。新采购的高配置服务器理应承担更多流量,充分发挥集群价值。

  • 对比分析:与简单轮询相比,加权轮询考虑了服务器的异构性,避免了"大锅饭"式的平均主义,资源利用率更高。

○ IP哈希 (ip_hash):

根据客户端IP的哈希结果分配请求,同一个IP的客户端总会访问到同一个后端服务器,可解决会话(Session)保持问题。

复制代码
upstream geek_mall {
    ip_hash; # 启用IP哈希策略
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}
  • 请求流向 :Nginx会对客户端的IP地址进行哈希计算,得到一个数值,然后根据服务器数量取模,确保同一个IP的请求永远落到同一台后端服务器上

  • 解决核心问题Session保持(会话保持)。如果用户的登录状态(Session)只存储在服务器B的内存里,那么他下次请求如果被分配到服务器C,就会被提示"未登录",体验极差。IP哈希从根本上解决了这个问题。

  • 潜在缺点:如果某个IP的用户特别活跃(比如爬虫或网红主播),会导致其对应的服务器压力过大,破坏了负载均衡的初衷。

○ 最少连接 (least_conn):

将请求优先分配给当前活跃连接数最少的后端服务器。

复制代码
upstream geek_mall {
    least_conn; # 启用最少连接策略
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
}
  • 请求流向:Nginx会实时跟踪每个后端服务器当前的活跃连接数,新的请求会被发送给连接数最少的那台服务器。

  • 适用场景 :请求处理时间长短不一的场景。比如,有些请求是简单的商品查询(快),有些是复杂的订单生成(慢)。最少连接数策略能动态地将新请求导向当前相对"清闲"的服务器,避免某些服务器因处理长任务而积压请求。

● 故障处理:

模式一:被动健康检查(默认熔断机制)

这是Nginx自带的、开箱即用的功能。就像电路中的"保险丝"。

复制代码
upstream geek_mall {
    server 192.168.1.101:8080 max_fails=2 fail_timeout=30s;
    server 192.168.1.102:8080 max_fails=2 fail_timeout=30s;
    server 192.168.1.103:8080 max_fails=2 fail_timeout=30s;
}
  • 核心参数

    • max_fails:在 fail_timeout时间内,连续失败多少次,才标记服务器不可用。默认是1次

    • fail_timeout:有两个含义:1) 计算失败次数的时间窗口;2) 服务器被标记为不可用后,多久后再去尝试探测是否恢复。默认是10秒

故障发生时的流程

  1. 用户请求到来:Nginx将请求转发给服务器B。

  2. 首次失败:连接超时或收到错误码(如502 Bad Gateway)。Nginx记下一次失败。

  3. 二次失败 :在接下来的30秒内,又一个请求被分给B,再次失败。失败次数达到 max_fails=2

  4. 熔断 :Nginx立即将服务器B标记为"不可用",并启动一个30秒的"熔断计时器"。在接下来的30秒内,所有新请求都会跳过B,只发给A和C。系统实现了快速自保

  5. 探活与自愈 :30秒的 fail_timeout过后,Nginx会"小心翼翼地"尝试将下一个新请求再次发给B。

    • 如果成功:B被重置为"健康"状态,重新加入集群,熔断结束。

    • 如果依然失败:B继续被标记为不可用,再进入下一个30秒的熔断期。

模式二:主动健康检查

Nginx通过主动健康检查(需要集成nginx_upstream_check_module模块)或被动健康检查(默认)来探测上游服务器状态。

被动检查有个缺点:必须等到有真实用户请求失败时才会触发。这意味着总要有一个"倒霉"的用户去触发这个错误。

对于要求高可用的金融、支付等核心业务,我们需要更主动的机制。这通常需要集成第三方模块,如 nginx_upstream_check_module

复制代码
upstream geek_mall {
    server 192.168.1.101:8080;
    server 192.168.1.102:8080;
    server 192.168.1.103:8080;
    check interval=3000 rise=2 fall=3 timeout=1000 type=http;
    check_http_send "HEAD /health_check.html HTTP/1.0\r\n\r\n";
    check_http_expect_alive http_2xx http_3xx;
}
  • 工作机制

    • interval=3000:每3秒检查一次。

    • type=http:发送HTTP请求进行检查。

    • check_http_send:定义发送的请求内容,比如请求一个特定的健康检查页面。

    • check_http_expect_alive:如果返回2xx或3xx状态码,则认为健康。

    • fall=3:连续失败3次,才标记为不健康。

    • rise=2:从不健康状态恢复,需要连续成功2次。

  • 巨大优势在用户请求到达之前,Nginx就已经知道了服务器B宕机了。 当故障发生时,Nginx能瞬间 将B从可用列表中剔除,没有任何用户会感受到故障。实现了无缝故障转移

HTTP状态码分类(解释 check_http_expect_alive:如果返回2xx或3xx状态码,则认为健康)

状态码范围 类别 含义 常见状态码示例
2xx 成功 请求已被服务器成功处理 200 OK, 201 Created
3xx 重定向 需要客户端进一步操作 301 Moved Permanently
4xx 客户端错误 请求包含错误语法或无法完成 404 Not Found, 403 Forbidden
5xx 服务器错误 服务器处理请求失败 500 Internal Server Error

2、在Kafka、RocketMQ、RabbitMQ之间进行技术选型时,你会考虑哪些因素?

场景1:电商平台订单系统

业务需求:

  • 订单创建、支付、发货的状态流转必须严格有序

  • 双11期间需要处理百万级订单消息

  • 需要保证消息不丢失(资金相关)

  • 可能需要延迟消息(如30分钟未支付自动取消)

RocketMQ 最优

  • 严格的消息顺序保证

  • 完整的事务消息支持

  • 内置延迟消息功能

  • 经过阿里双11验证的稳定性

场景2:日志收集与实时分析系统

业务需求:

  • 收集上千个微服务的运行日志

  • 每秒处理百万条日志消息

  • 消息允许少量丢失(日志可重复)

  • 需要支持多个消费者组(监控、分析、归档)

Kafka 最优

  • 天然的高吞吐设计

  • 完善的多消费者组机制

  • 海量消息堆积能力

  • 成熟的流处理生态(Kafka Streams)

场景3:企业级ERP系统集成

业务需求:

  • 多个异构系统间消息路由(CRM、财务、仓储)

  • 复杂的消息路由规则(基于header、Topic路由)

  • 需要多种消息模式(点对点、发布订阅)

  • 企业级管理界面和监控

RabbitMQ 最优

  • 灵活的Exchange路由机制

  • 多种协议支持(AMQP、MQTT等)

  • 完善的Web管理界面

  • 丰富的客户端支持

3、请简要描述Elasticsearch写入数据和全文检索的基本原理

写入原理 (Write)

1、文档首先被写入内存缓冲区和事务日志 (Translog) 中(用于保证数据不丢失)。

2、默认每1秒,内存缓冲区中的文档会被刷新(refresh)到文件系统缓存中,形成一个新的不可变的段 (Segment)。此时文档才变得可被搜索(Near Real-Time)。

3、 随着段的数量增多,ES会定期进行段合并 (Segment Merge),将小段合并成大段,并物理删除标记为删除的文档。

4、 Translog会不断增长,ES会在段被刷盘 (Flush) 到磁盘后清空旧的Translog。

整体流程图如下:

1、内存缓冲区 + Translog(双保险机制)

如果没有Translog会怎样?

  • 如果只有内存缓冲区,当服务器突然断电时,所有在内存中未持久化的数据都会丢失

  • Translog的作用:类似于MySQL的Redlog日志,可以有安全性

复制代码
// 索引设置,控制刷新频率
PUT /blog_articles
{
  "settings": {
    "index": {
      "refresh_interval": "1s",      // 每秒刷新一次
      "translog": {
        "sync_interval": "5s",      // Translog刷盘间隔
        "durability": "request"     // 每次请求都写Translog(最安全)
      }
    }
  }
}

2、Refresh操作:近实时搜索的关键

ES是写入数据后搜索延迟的,大概延迟在1秒内,数据先到文件系统缓存,再异步刷盘(不同于传统型数据库:数据直接写入磁盘,可立即查询)

3. 段合并(Segment Merge):空间与性能的权衡

复制代码
假设连续写入5篇文章:
文档1 → 生成Segment A
文档2 → 生成Segment B
文档3 → 生成Segment C
文档4 → 生成Segment D
文档5 → 生成Segment E

合并过程

复制代码
时间点T1: Segment A + Segment B → 合并为 Segment AB
时间点T2: Segment C + Segment D → 合并为 Segment CD  
时间点T3: Segment AB + Segment CD + Segment E → 合并为最终段

合并的好处

  • 减少文件句柄数

  • 提升搜索性能(减少要搜索的段数)

  • 物理删除标记为删除的文档

检索原理 (Search)

分词

查询语句会被分词器 (Analyzer) 拆分成一系列的词条(Token),如"Hello World" -> ["hello", "world"]。

不同分词器的效果

复制代码
// 标准分词器(默认)
"Elasticsearch搜索原理" → ["elasticsearch", "搜", "索", "原", "理"]

// IK智能分词器(中文优化)
"Elasticsearch搜索原理" → ["elasticsearch", "搜索", "原理"]

// 关键字分词器(不分词)
"Elasticsearch搜索原理" → ["elasticsearch搜索原理"]

倒排索引 (Inverted Index)

正排索引 vs 倒排索引对比

索引类型 类比 数据结构 查询方式
正排索引 书的内容 文档ID → 文档内容 按文档ID查找内容
倒排索引 书的索引 关键词 → 文档ID列表 按关键词查找文档
复制代码
# 文档数据
doc1 = {"id": 1, "title": "Elasticsearch原理", "content": "学习ES基本原理"}
doc2 = {"id": 2, "title": "搜索技术", "content": "Elasticsearch是优秀搜索引擎"}
doc3 = {"id": 3, "title": "大数据原理", "content": "ES在大数据中的应用"}

# 倒排索引构建
倒排索引 = {
    "elasticsearch": [1, 2],    # 出现在文档1和2中
    "原理": [1, 3],              # 出现在文档1和3中  
    "搜索": [2, 3],              # 出现在文档2和3中
    "技术": [2],
    "学习": [1],
    "基本": [1],
    "优秀": [2],
    "大数据": [3],
    "应用": [3]
}

相关性算分

根据TF-IDF或BM25等算法,计算查询词条与每个文档的相关性分数。

返回结果

按分数排序后,返回最相关的文档列表。

简单案例

复制代码
GET /blog_articles/_search
{
  "query": {
    "match": {
      "title": "Elasticsearch搜索原理"
    }
  }
}
ES大致的执行过程
复制代码
1、查询解析:识别为match查询,针对title字段
2、分词处理:将查询词分为["elasticsearch", "搜索", "原理"]
3、倒排索引查找:
3.1"elasticsearch" → [文档1, 文档5, 文档8]
3.2"搜索" → [文档1, 文档3, 文档5]
3.2"原理" → [文档1, 文档8, 文档10]
4、文档集合操作:求交集得到[文档1]
5、相关性评分:计算每个匹配文档的BM25分数
6、结果返回:按分数排序返回

4、ShardingSphere有哪些分片算法?以及适合的分片业务场景!

简介ShardingSphere及其分片概念

  • ShardingSphere是一个开源的分布式数据库中间件生态圈,它由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar组成。

  • 分片(Sharding)指的是将数据库中的数据按照某种规则分散存储到多个数据节点上,以达到分散负载、提升性能的目的。

分片算法分类

  • 根据分片键的数量,分片算法可以分为单分片键算法和复合分片键算法。

  • 根据分片算法的特性,可以分为精确分片算法、范围分片算法、复合分片算法等。

1、 取模分片算法(MOD)

  • 描述:根据分片键的哈希值或直接值对分片数取模,得到分片位置。

  • 配置示例:算法名称:MOD,属性:sharding-count(分片数量)

  • 场景:适用于分片键为整数类型,且数据分布均匀的场景。例如,用户ID按4取模,分成4个表。

配置信息:

maven依赖

复制代码
      <dependency>
            <groupId>org.apache.shardingsphere</groupId>
            <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
            <version>5.1.1</version>
        </dependency>

application.properties

复制代码
#--分片算法
spring.shardingsphere.rules.sharding.sharding-algorithms.table-mod.type=MOD
spring.shardingsphere.rules.sharding.sharding-algorithms.table-mod.props.sharding-count=2

适用场景:

  • 用户表按user_id分片(用户ID通常是自增数字)

  • 订单表按order_id分片(订单ID为数值类型)

  • 需要数据均匀分布的业务场景

  • 分片键为整数类型且分布均匀的情况

优势:

  • 数据分布均匀,避免热点问题

  • 简单高效,计算开销小

  • 易于理解和维护

局限性:

  • 分片键必须是整数类型

  • 扩容困难,需要数据迁移

  • 不支持非数值类型分片键

2、哈希分片算法(HASH)

  • 描述:对分片键进行哈希运算,然后根据哈希值分布到不同的分片。

  • 配置示例:算法名称:HASH,属性:sharding-count(分片数量)

  • 场景:适用于分片键为非整数类型,或者希望将数据均匀分布的场景。例如,用用户名分片,先对用户名进行哈希,再取模。

application.properties

复制代码
#--分片算法
spring.shardingsphere.rules.sharding.sharding-algorithms.table-mod.type=MOD
spring.shardingsphere.rules.sharding.sharding-algorithms.table-mod.props.sharding-count=2

spring.shardingsphere.rules.sharding.sharding-algorithms.table-hash-mod.type=HASH_MOD
spring.shardingsphere.rules.sharding.sharding-algorithms.table-hash-mod.props.sharding-count=2

适用场景:

  • 用户名、手机号、邮箱等字符串类型分片键

  • 需要将非数值数据均匀分布的场景

  • 分布式会话存储(按session_id分片)

  • 商品SKU分片(按sku_code哈希)

优势:

  • 支持任意数据类型分片键

  • 数据分布相对均匀

  • 适用于高基数字段

局限性:

  • 哈希冲突可能导致数据分布不均

  • 范围查询效率低

  • 扩容需要数据重分布

3、 范围分片算法(RANGE)

  • 描述:根据分片键的值范围进行分片。例如,0-1000在分片1,1001-2000在分片2。

  • 配置示例:算法名称:RANGE,属性:ranges(范围定义,如"0-1000,1001-2000")

  • 场景:适用于分片键是连续数值,且需要按范围查询的场景。例如,按订单金额分片,可以方便地进行范围查询,但可能导致数据倾斜。

application.properties

复制代码
# 按金额范围分片
spring.shardingsphere.rules.sharding.sharding-algorithms.amount_range.type=BOUNDARY_RANGE
spring.shardingsphere.rules.sharding.sharding-algorithms.amount_range.props.sharding-ranges=1000,5000,10000,50000,100000

# 分片解释:
# amount < 1000 → 分片0(小额订单)
# 1000 <= amount < 5000 → 分片1(中等订单)
# 5000 <= amount < 10000 → 分片2(大额订单)
# 10000 <= amount < 50000 → 分片3(超大额订单)
# amount >= 50000 → 分片4(特殊订单)

适用场景:

  • 按订单金额分片(小额、中额、大额订单分离)

  • 会员等级分片(普通会员、VIP会员、SVIP会员)

  • 地区编码分片(按行政区划范围)

  • 产品价格区间分片

优势:

  • 支持范围查询优化

  • 便于按业务特性分区管理

  • 适合有明确数值区间的业务

局限性:

  • 容易产生数据倾斜(热点问题)

  • 需要预估数据分布

  • 边界值调整复杂

4、时间分片算法(根据日期分片)

  • 描述:根据分片键的日期进行分片,可以按年、月、日等。

  • 配置示例:算法名称:INTERVAL,属性:datetime-pattern(日期格式),datetime-lower(开始时间),datetime-upper(结束时间),sharding-suffix-pattern(分片后缀模式,如yyyyMM)

  • 场景:适用于按时间增长的数据,如日志、订单等。例如,可以按月分片,每个月一张表。

application.properties

复制代码
#--分片算法:monthly_interval
spring.shardingsphere.rules.sharding.sharding-algorithms.monthly_interval.type=INTERVAL
spring.shardingsphere.rules.sharding.sharding-algorithms.monthly_interval.props.datetime-pattern=yyyy-MM-dd HH:mm:ss
spring.shardingsphere.rules.sharding.sharding-algorithms.monthly_interval.props.datetime-lower=2023-01-01 00:00:00
spring.shardingsphere.rules.sharding.sharding-algorithms.monthly_interval.props.datetime-upper=2025-12-31 23:59:59
spring.shardingsphere.rules.sharding.sharding-algorithms.monthly_interval.props.sharding-suffix-pattern=yyyyMM
spring.shardingsphere.rules.sharding.sharding-algorithms.monthly_interval.props.datetime-interval-amount=1
spring.shardingsphere.rules.sharding.sharding-algorithms.monthly_interval.props.datetime-interval-unit=MONTHS

适用场景:

  • 日志表按月/按周分片(访问日志、操作日志)

  • 订单表按创建时间分片(支持时间范围查询)

  • 监控数据按时序分片(指标数据、性能数据)

  • 财务流水按会计期间分片

优势:

  • 天然支持时间范围查询

  • 便于历史数据归档和清理

  • 自动分片,无需手动干预

  • 适合时序数据场景

局限性:

  • 时间戳字段必须有索引

  • 早期分片可能数据量小,后期分片数据量大

  • 需要合理设置时间上下限

5、行表达式分片算法(INLINE)

  • 描述:使用Groovy表达式在配置中直接编写分片规则,简单灵活。

  • 配置示例:算法类型:INLINE,属性:algorithm-expression(表达式,如ds_${order_id % 4})

  • 场景:适用于简单的分片规则,且不想编写代码的场景。例如,根据分片键取模分片。

application.properties

复制代码
# 行表达式分片
spring.shardingsphere.rules.sharding.sharding-algorithms.inline-mod.type=INLINE
spring.shardingsphere.rules.sharding.sharding-algorithms.inline-mod.props.algorithm-expression=db${order_id % 4}

适用场景:

  • 简单的取模分片逻辑

  • 快速原型开发和测试环境

  • 分片规则固定的简单业务

  • 不希望编写Java代码的场景

优势:

  • 配置简单,无需编码

  • 灵活性强,支持Groovy表达式

  • 适合规则固定的简单分片

局限性:

  • 复杂逻辑表达能力有限

  • 调试和排查问题困难

  • 性能可能不如自定义算法

6、标准分片算法(STANDARD)

  • 描述:允许用户通过实现PreciseShardingAlgorithm和RangeShardingAlgorithm接口来自定义精确分片和范围分片行为。

  • 配置示例:算法类型:STANDARD,属性:algorithm-class(自定义算法类)

  • 场景:适用于需要自定义分片逻辑的场景。例如,根据分片键的前缀或后缀进行分片。

application.properties

java 复制代码
## 标准分片算法(STANDARD)
# 分片算法配置
spring.shardingsphere.rules.sharding.sharding-algorithms.order-precise.type=CUSTOM
spring.shardingsphere.rules.sharding.sharding-algorithms.order-precise.props.sharding-algorithm-class-name=com.mashibing.shardingjdbc.OrderPreciseSharding

# 表分片规则配置
spring.shardingsphere.rules.sharding.tables.t_order.actual-data-nodes=ds_${0..9}.t_order_${0..9}
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.column=order_id
spring.shardingsphere.rules.sharding.tables.t_order.key-generate-strategy.key-generator-name=snowflake
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-column=order_id
spring.shardingsphere.rules.sharding.tables.t_order.database-strategy.standard.sharding-algorithm-name=order-precise


import org.apache.shardingsphere.api.sharding.standard.PreciseShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.standard.PreciseShardingValue;

import java.util.Collection;

public class OrderPreciseSharding implements PreciseShardingAlgorithm<Long> {
    @Override
    public String doSharding(Collection<String> availableTargetNames,
                             PreciseShardingValue<Long> shardingValue) {
        // 获取分片值(订单ID)
        Long orderId = shardingValue.getValue();
        // 计算分片后缀(订单ID最后一位)
        int suffix = (int) (orderId % 10);
        // 返回目标数据源名称(db0 ~ db9),实际可能没这么多
        return "db" + suffix;
    }
}

关键配置解析

  1. 分片算法类型 type: CUSTOM 表示使用自定义分片算法

  2. 算法类路径 sharding-algorithm-class-name 需指定实现类的全限定名

  3. 分片规则绑定tables配置中通过 sharding-algorithm-name关联算法

  4. 分片值处理 doSharding方法参数说明:

    • availableTargetNames:可用分片名集合(如ds_0,ds_1)

    • shardingValue:包含分片键值和分片列信息

注意事项

  1. 类扫描路径 确保自定义算法类在Spring Boot主应用类或配置类的包路径下,或通过 @ComponentScan扫描

  2. 分片值范围 示例中按订单ID最后一位分片(0-9),需确保分片后缀与 actual-data-nodes配置匹配

  3. 分布式ID生成 示例中配置了Snowflake生成器,需确保分片键与主键生成策略一致

  4. 多分片维度 如需同时按用户ID分片,需在 shardingValue中获取用户ID值,并组合分片逻辑

适用场景:

  • 复杂的分片业务逻辑

  • 需要多字段组合分片

  • 特殊的分片规则需求

  • 性能优化要求高的场景

优势:

  • 完全自定义分片逻辑

  • 支持复杂业务规则

  • 性能优化空间大

  • 灵活应对特殊需求

局限性:

  • 需要编写和维护代码

  • 部署和测试相对复杂

  • 对开发人员要求较高

7、 复合分片算法(COMPLEX)

  • 描述:支持多个分片键,用户可以通过实现ComplexKeysShardingAlgorithm接口来自定义多分片键的逻辑。

  • 配置示例:算法类型:COMPLEX,属性:algorithm-class(自定义算法类)

  • 场景:适用于多个分片键共同决定分片位置的场景。例如,同时根据用户ID和订单ID分片。

application.properties

复制代码
# 复合分片算法配置
spring.shardingsphere.rules.sharding.sharding-algorithms.user-order-complex.type=CLASS_BASED
spring.shardingsphere.rules.sharding.sharding-algorithms.user-order-complex.props.strategy=COMPLEX
spring.shardingsphere.rules.sharding.sharding-algorithms.user-order-complex.props.algorithmClassName=com.mashibing.shardingjdbc.UserOrderComplexSharding

# 分表策略
spring.shardingsphere.rules.sharding.tables.orders.actual-data-nodes=db${0..9}.t_order_${0..9}
spring.shardingsphere.rules.sharding.tables.orders.table-strategy.complex.sharding-columns=user_id, order_id
spring.shardingsphere.rules.sharding.tables.orders.table-strategy.complex.sharding-algorithm-name=user-order-complex

import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.complex.ComplexKeysShardingValue;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

public class UserOrderComplexSharding implements ComplexKeysShardingAlgorithm<Long> {

    @Override
    public Collection<String> doSharding(Collection<String> availableTargetNames,
                                         ComplexKeysShardingValue<Long> shardingValue) {
        Set<String> result = new HashSet<>();

        // 获取用户ID分片值
        Collection<Long> userIds = shardingValue.getColumnNameAndShardingValuesMap().get("user_id");
        // 获取订单ID分片值
        Collection<Long> orderIds = shardingValue.getColumnNameAndShardingValuesMap().get("order_id");

        // 组合分片逻辑
        for (Long userId : userIds) {
            int userSuffix = (int) (userId % 10);
            for (Long orderId : orderIds) {
                int orderSuffix = (int) (orderId % 10);
                // 组合分片键:用户ID取模 + 订单ID取模
                String target = "db" + (userSuffix * 10 + orderSuffix);
                if (availableTargetNames.contains(target)) {
                    result.add(target);
                }
            }
        }

        return result;
    }
}

适用场景:

  • 多维度分片需求(用户+时间)

  • 关联查询优化(主子表同库分片)

  • 复杂业务规则分片

  • 需要避免跨分片关联的场景

优势:

  • 支持多分片键组合

  • 优化关联查询性能

  • 灵活应对复杂业务

  • 减少跨分片操作

局限性:

  • 算法复杂度高

  • 调试和维护困难

  • 需要深入理解业务

业务场景匹配

业务场景 推荐算法 理由 示例
用户系统 MOD 用户ID为数值,分布均匀 user_id % 16
订单系统 COMPLEX 多维度查询(用户+时间) 用户分片+时间分片
日志系统 INTERVAL 按时间序列自动分片 按月分片
商品目录 HASH_MOD SKU编码为字符串 sku_code哈希分片
财务系统 RANGE 按金额区间管理 小额、中额、大额分片
监控数据 INTERVAL 时序数据特性 按天/按时分片
会话存储 HASH_MOD session_id均匀分布 session_id哈希分片
相关推荐
勇往直前plus1 小时前
大模型开发手记(九):LangChain Agent 中间件-提升Agent的可靠性与可控性
中间件·langchain
隔壁小邓19 小时前
数据库中间件全景解析:从连接管理到分布式协同
数据库·分布式·中间件
爱喝可乐的老王1 天前
LangChain内置中间件总结
中间件·langchain
marsh02061 天前
12 openclaw中间件开发:打造可复用的业务逻辑组件
ai·中间件·编程·技术
爱喝可乐的老王1 天前
LangChain自定义中间件
中间件·langchain
汀沿河1 天前
3 LangChain 1.0 中间件(Middleware)- after_model、after_agent
前端·中间件·langchain
xht08321 天前
docker离线安装及部署各类中间件(x86系统架构)
docker·中间件·系统架构
汀沿河2 天前
LangChain 1.0 中间件(Middleware)- before_agent、before_model
中间件·langchain
汀沿河2 天前
2 LangChain 1.0 中间件(Middleware)- wrap_model_call、wrap_tool_call
spring·中间件·langchain