Sharding Algorithms
cosid-sharding keeps the 4.x sharding algorithms (D7) and releases them with every major version. They decide which physical table, or database, a sharding value goes to, and which ones a range query has to visit. The module depends on cosid-core only.
implementation("me.ahoo.cosid:cosid-sharding")public interface Sharding<T extends Comparable<? super T>> extends PreciseSharding<T>, RangeSharding<T> {
String sharding(T shardingValue); // one value → one node
Collection<String> sharding(ShardingRange<T> range); // a range → the nodes it touches
Collection<String> getEffectiveNodes();
}ModCycle: modulo sharding
ModCycle<T extends Number> maps value mod divisor to {prefix}{index}. A range visits only the nodes it covers, and all of them once it spans divisor values.

ModCycle<Long> orders = new ModCycle<>(4, "t_order_");
orders.sharding(10L); // t_order_2
orders.sharding(ShardingRange.closed(1L, 2L)); // [t_order_1, t_order_2]
orders.sharding(ShardingRange.atLeast(0L)); // all fourIntervalTimeline: time interval sharding
IntervalTimeline cuts an effective time range into intervals of an IntervalStep (a ChronoUnit and an amount). Each interval is a node named {prefix}{suffix}, the suffix formatted by a DateTimeFormatter. Finding a node is arithmetic, not a search.

IntervalTimeline logs = new IntervalTimeline("t_log_",
ShardingRange.closed(LocalDateTime.of(2026, 1, 1, 0, 0), LocalDateTime.of(2026, 12, 31, 23, 59)),
IntervalStep.of(ChronoUnit.MONTHS), DateTimeFormatter.ofPattern("yyyyMM"));
logs.sharding(LocalDateTime.of(2026, 10, 27, 12, 0)); // t_log_202610A value outside the effective range is rejected (IllegalArgumentException); a range outside it gets no node.
Convertors
The interval algorithm shards a LocalDateTime. A convertor turns the column value into one:
| Convertor | Accepts |
|---|---|
StandardLocalDateTimeConvertor(zone, isSecondTs, formatter) | LocalDateTime, ZonedDateTime, OffsetDateTime, Instant, LocalDate, Date, YearMonth, Year, an epoch Long (milliseconds, or seconds when isSecondTs), a String in the formatter's pattern |
SnowflakeLocalDateTimeConvertor(layout, zone[, codec]) | a Snowflake id, Long or text (base 62, 11 digits, padded by default): the time it was issued, through Layout.unpack |
So a table sharded by month can be keyed by the Snowflake id alone:
var issued = new SnowflakeLocalDateTimeConvertor(Layout.SNOWFLAKE_MS, ZoneId.of("Asia/Shanghai"));
logs.sharding(issued.toLocalDateTime(orderId));CachedSharding
new CachedSharding<>(sharding) caches the range results of another algorithm. It is bounded: by default it keeps up to 10 000 ranges and empties itself once full, so lookups take no lock.
Changes from 4.x
ShardingRangereplaces Guava'sRange. It keeps Guava's factory names (closed,open,closedOpen,openClosed,atLeast,atMost,greaterThan,lessThan,all,singleton) and semantics, so porting is a rename.BoundTypeisme.ahoo.cosid.sharding.BoundType.SnowflakeLocalDateTimeConvertortakes aLayoutand a zone instead of aSnowflakeIdStateParser.cosid-shardingno longer depends on Guava or Lombok.- ShardingSphere ships its own CosId-based algorithms; they are maintained in ShardingSphere, not here.
