跪拜 Guibai
← All articles
Backend

Spring Boot 3 + ShardingSphere-JDBC: One Configuration That Runs Read-Write Splitting and Sharding Together

By 70后写java的老码农 ·
Read original on juejin.cn ↗ Google Translate ↗ Alt translation

ShardingSphere-JDBC collapses read-write splitting and sharding into a single JVM-level driver, so developers can keep writing ordinary SQL while the middleware owns routing. The trade-off is real operational overhead: you still create physical tables, maintain replicas, and design sharding keys carefully, and any miss on the key turns a fast single-table query into a broadcast across all shards.

Summary

A practical walkthrough wires read-write splitting and table sharding into a Spring Boot 3 application using ShardingSphere-JDBC 5.5.2. The middleware acts as an enhanced JDBC driver, not a separate proxy, and handles SQL parsing, routing, rewriting, and merging before any statement reaches MySQL. Business code keeps writing plain logical table names like `t_order`, while the engine rewrites them to `t_order_0` or `t_order_1` based on the sharding key.

The configuration in `sharding-ms.yaml` defines a write datasource and a read datasource, then groups them into a logical `readwrite_ds`. The sharding rule uses `user_id % 2` to distribute rows across two physical tables. A distributed primary key strategy via MyBatis-Plus's `ASSIGN_ID` replaces auto-increment to avoid collisions across shards. The guide also shows how `transactionalReadQueryStrategy: PRIMARY` forces reads inside a transaction to hit the primary, avoiding the "write then read stale" problem.

Verification steps demonstrate the routing logs, a batch insert that produces 1000 rows spread evenly across shards, and the performance difference between a shard-key query and a broadcast query. The author lists the operational caveats: physical tables must be created manually, master-slave replication is not handled by ShardingSphere, cross-shard pagination degrades sharply without a sharding key, and distributed transactions beyond a single shard are out of scope.

Takeaways
— ShardingSphere-JDBC is an enhanced JDBC driver embedded in the app JVM, not a standalone proxy; it parses, routes, rewrites, and merges SQL locally.
— The demo routes writes to a primary datasource and reads to a replica via a logical group named `readwrite_ds`, with a RANDOM load balancer for replicas.
— The sharding rule maps the logical table `t_order` to physical tables `t_order_0` and `t_order_1` using `user_id % 2` as the sharding expression.
— `transactionalReadQueryStrategy: PRIMARY` forces all SELECT statements inside a `@Transactional` context to execute against the primary, preventing stale reads after writes.
— MyBatis-Plus `@TableId(type = IdType.ASSIGN_ID)` generates snowflake-based global unique Long IDs, replacing auto-increment which would collide across shards.
— Queries without a sharding key get broadcast to all shards and merged in memory, which is functionally correct but scales poorly; cross-shard pagination gets slower as page depth increases.
— ShardingSphere does not handle master-slave data synchronization, replication latency, multi-primary writes, or transaction consistency across the replication group; all of that must be managed externally.
— To add more shards, you must create the new physical tables, update `actualDataNodes` to `${0..3}`, change the algorithm to `% 4`, and migrate existing data.
— Multiple replicas are added simply by listing more data source names under `readDataSourceNames`, and the load balancer will distribute reads among them.
Conclusions

The real burden of sharding is not the routing logic but the operational duties ShardingSphere deliberately leaves out: schema creation, replication, and data migration are all on you, and the guide treats them as prerequisites.

The `transactionalReadQueryStrategy: PRIMARY` setting is what makes the pattern usable for transactional business flows; without it, every "order now, query immediately" path would need its own consistency hack.

Cross-shard pagination is a trap because the middleware fetches enough rows from every shard to sort and then truncates, so deep pages degrade badly; the recommended escape is a dedicated wide table, which is a design decision many teams postpone.

Version differences in ShardingSphere's YAML structure (e.g., `dataSourceGroups` only appears in 5.5.x) mean that copying old config examples will silently fail at startup, so pinning versions matters more than usual.

Concepts & terms
ShardingSphere-JDBC
A Java middleware that acts like a JDBC driver. It intercepts SQL before execution, parses it, routes it to the correct datasource or table, rewrites logical table names to physical ones, and merges results from multiple shards.
INLINE sharding algorithm
A ShardingSphere algorithm that uses Groovy expressions to compute the target table. For example, `t_order_${user_id % 2}` sends rows with even user IDs to `t_order_0` and odd IDs to `t_order_1`.
Binding tables
A ShardingSphere configuration that groups tables sharded by the same key. When joining such tables, the engine avoids Cartesian products by keeping matching shards together.
Snowflake ID
A 64-bit distributed ID generation scheme that produces globally unique, roughly time-ordered numeric IDs. It is used as a primary key replacement after sharding because auto-increment would repeat across physical tables.
From the discussion
Featured comments
卷土的土

Expanding shards still requires migrating existing data.

See top comments, translated →
Source: juejin.cn ↗ Google Translate ↗ Backup ↗