Apache ShardingSphere 的读写分离功能
核心目标: 将数据库的写入操作(INSERT, UPDATE, DELETE)定向到主库(Master),将查询操作(SELECT)定向到从库(Slave),从而提升系统的读性能和整体吞吐量,缓解单点数据库的压力。
核心概念
- 主库 (Primary / Master): 负责处理所有写操作(DML)和事务性读操作的核心数据库。通常只有一个(或一个活跃的主库)。
- 从库 (Replica / Slave): 通过主从复制(如 MySQL Replication, PostgreSQL Streaming Replication)从主库异步或半同步复制数据的数据库。主要负责处理读操作(查询)。可以有多个,用于负载均衡和高可用。
- 读写分离数据源: ShardingSphere 在应用层创建的一个逻辑数据源。应用通过 JDBC 连接这个逻辑数据源,ShardingSphere 根据 SQL 类型自动路由到背后的真实主库或某个从库。
ShardingSphere 读写分离实现原理
-
配置:
- 定义真实数据源: 配置一个主库数据源(
primaryDataSourceName)和多个从库数据源(replicaDataSourceNames)。 - 配置负载均衡策略: 指定当有多个从库时,如何选择其中一个来处理读请求。内置策略:
ROUND_ROBIN: 轮询。RANDOM: 随机。WEIGHT: 基于权重的负载均衡(需配置权重)。- 自定义策略: 实现
ReplicaLoadBalanceAlgorithm接口。
- 配置规则 (
ReadwriteSplittingRuleConfiguration): 将真实数据源、主库名、从库名列表、负载均衡策略组合成一个逻辑数据源(readwriteSplittingDataSourceName)的规则。
- 定义真实数据源: 配置一个主库数据源(
-
SQL 解析与路由:
- 应用向 ShardingSphere 的逻辑数据源发起 SQL 请求。
- ShardingSphere 的 SQL 解析引擎解析 SQL 语句,判断其类型:
- 写操作 (INSERT, UPDATE, DELETE, DDL): 强制路由到主库。
- 读操作 (SELECT): 路由到配置的从库池中的一个从库(根据负载均衡策略选择)。
- 特殊情况:
- 事务内的读操作: 为了保证事务内读取到最新写入的数据(避免主从延迟导致的不一致),默认情况下,事务内的所有查询也会被路由到主库。这是关键点!
- Hint 强制主库路由: 即使是非事务中的读操作,如果业务要求必须读取绝对最新的数据(如刚写入后立即查询),可以使用 ShardingSphere 提供的 Hint 管理器 (
HintManager) 强制将当前查询(或后续一系列操作)路由到主库。例如:try (HintManager hintManager = HintManager.getInstance()) { hintManager.setWriteRouteOnly(); // 强制后续操作走主库 // 执行你的查询语句,此时会路由到主库 } - 非事务内且无 Hint 的读操作: 正常路由到从库。
-
SQL 执行:
- 根据路由决策,ShardingSphere 通过对应的数据库驱动,获取到目标主库或从库的真实数据库连接。
- 将 SQL 语句通过该连接发送到真实的数据库执行。
-
结果归并:
- 对于读操作(SELECT),ShardingSphere 接收从库返回的结果集。
- 由于读写分离通常只路由到一个从库(不像分片会路由到多个库),所以这里的结果归并相对简单,主要是将单个结果集封装返回给应用。如果是分库分表+读写分离的组合场景,归并会更复杂。
核心优势
- 提升读性能: 将读压力分散到多个从库,显著提升系统的查询吞吐量和响应速度。
- 提升整体吞吐量: 主库专注于写操作和关键事务读,从库处理大量查询,系统整体处理能力增强。
- 高可用基础: 在主库故障时,可以快速将一个从库提升为新的主库(通常需要配合数据库本身的主从切换机制和 ShardingSphere 的高可用配置),提高系统可用性。读写分离本身不直接提供故障切换,但为高可用架构奠定了基础。
- 透明性: 对应用代码基本无侵入。应用像使用单个数据库一样使用逻辑数据源,路由细节由 ShardingSphere 屏蔽。
重要注意事项
- 数据延迟: 这是读写分离架构的 核心挑战。主从复制是异步或半同步的,从库的数据相对于主库存在一定延迟(几毫秒到几秒甚至分钟,取决于网络、负载、复制机制)。应用必须能容忍这种延迟:
- 刚写入的数据可能查不到: 写入主库成功后立即查询从库,可能查不到刚写入的数据。
- 解决方案:
- 关键读走主库: 对一致性要求高的读操作,使用事务或 Hint 强制路由到主库。
- 业务容忍: 设计业务逻辑时考虑最终一致性,允许短暂延迟。
- 监控延迟: 监控主从延迟,延迟过大时告警并可能自动将读切回主库。
- 事务内读一致性: 默认事务内读走主库保证了强一致性,但也牺牲了部分读性能扩展。理解这个默认行为非常重要。
- 主库压力: 所有写操作和事务内读操作都集中在主库,主库仍然是性能和单点的瓶颈。读写分离主要解决读压力。
- 从库数量与成本: 增加从库能提升读能力,但也增加硬件成本、维护成本和主库复制压力。
- 负载均衡策略选择: 根据从库的硬件配置(权重)或简单的流量分发(轮询/随机)选择合适的策略。
配置方式 (概要 - 具体看文档/YAML示例)
ShardingSphere 支持多种配置方式,核心是定义 ReadwriteSplittingRuleConfiguration:
- Java 代码配置: 直接使用 ShardingSphere 的 API 构建配置对象 (
ReadwriteSplittingRuleConfiguration,ShardingSphereDataSource)。 - YAML 配置: (最常用) 在
server.yaml(全局) 或数据源规则配置文件中定义读写分离规则。rules: - !READWRITE_SPLITTING dataSources: pr_ds: # 逻辑数据源名称 writeDataSourceName: primary_ds # 主库数据源名称 readDataSourceNames: # 从库数据源名称列表 - replica_ds_0 - replica_ds_1 loadBalancerName: round_robin # 负载均衡器名称 loadBalancers: round_robin: type: ROUND_ROBIN # 负载均衡器类型 - Spring Boot Starter: 使用
application.properties/application.yml配置,格式与 YAML 配置类似,属性名遵循 Spring Boot 的规范。
学习建议与下一步
- 动手实践: 搭建一个简单的主从复制环境(如 Docker 启动 MySQL 主从),然后使用 ShardingSphere (JDBC 或 Proxy) 配置读写分离规则。编写测试代码,分别执行写操作和读操作,观察 SQL 实际执行的数据库。特别测试事务内的读操作和 Hint 的效果。
- 结合场景思考: 思考你的业务场景中哪些查询可以容忍延迟?哪些查询必须强一致?如何利用 Hint 或事务?
- 理解延迟影响: 深刻理解主从延迟可能带来的业务影响,并在设计和开发中规避或处理。
- 进阶:
- 结合分库分表: 读写分离常与分库分表结合使用,构建更强大的分布式数据库解决方案。学习
sharding规则如何与readwrite_splitting规则协同工作。 - 高可用集成: 了解如何配置数据库发现(如 MGR, Raft)和故障转移,让 ShardingSphere 在主库故障时能感知并切换到新的主库。
- 数据加密 / 影子库: 了解 ShardingSphere 的其他特性如何与读写分离结合使用。
- 结合分库分表: 读写分离常与分库分表结合使用,构建更强大的分布式数据库解决方案。学习
- 查阅官方示例: Apache ShardingSphere GitHub 仓库提供了丰富的读写分离配置和使用示例。
855

被折叠的 条评论
为什么被折叠?



