RFC-001 (Draft, author Steper, 2025-11-12) proposes migrating zhichai.net's business ID generation from Redisson RAtomicLong counters to the Snowflake algorithm, implemented via Hutool.
Background and Problem
The current BusinessIdGeneratorService uses Redis atomic increment for ten ID types (user, server, channel, message, role, attachment, reaction, thread, audit log, ban record), with Neo4j UNIQUE constraints on all ID fields. Issues discovered:
- Test environment: concurrent test classes allocated the same IDs, causing
ConstraintValidationFailederrors (e.g., duplicaterole_id = 1001). Temporarily mitigated by starting sequences at1_000_000_000 + (currentTimeMillis % 1_000_000_000). - Production risks: single point of failure (Redis unavailable = no IDs), ~1-5ms network round-trip per ID, sequence reset on Redis data loss, cross-region latency, no horizontal scaling, and no strict ordering guarantee across instances.
- Chosen scheme: Snowflake over Redisson counters, UUID, database sequences, or a dedicated ID microservice — it meets all core requirements, fits the Spring Boot microservice architecture, is battle-tested (Twitter, Meituan, Baidu), and is cheap to adopt via Hutool.
- 64-bit layout: 1 sign bit | 41-bit ms timestamp (epoch
1735660800000L, 2025-01-01 08:00:00, ~69-year span) | 10-bit worker ID (1024 instances) | 12-bit sequence (4096 IDs/ms → ~4.09M QPS theoretical). - Implementation:
SnowflakeIdGeneratorServiceuses aConcurrentHashMap<String, Snowflake>with per-type worker ID offsets;extractTimestamp(id)recovers(id >> 22) + EPOCHfor debugging. - Worker ID allocation: static config short-term (
WORKER_IDenv var; ranges: dev 0-99, test 100-199, staging 200-299, prod 300-1023); K8s usesPOD_INDEX. Long-term option: Redis-lock-based auto allocation. - Clock rollback: detect and throw, wait for clock to catch up, or compensate with local sequence.
- Worker ID conflict: strict config management, startup uniqueness checks, alerting.
- Sequence overflow: wait for next millisecond; monitor usage.
- Rollback tooling: config flip, git revert + redeploy (<30 min), and Cypher cleanup scripts for test-env Snowflake-generated nodes plus duplicate detection/repair scripts (keep earliest node,
DETACH DELETEthe rest). - Twitter Snowflake
- Leaf - Meituan distributed ID service
- Hutool IdUtil / Snowflake docs
- Baidu UidGenerator
Requirements
Global uniqueness, trend-increasing IDs, high availability, 10,000+ QPS per instance, 64-bit Long, optional embedded timestamps, multi-datacenter friendly.
Key points
Migration plan (zero downtime, 4 phases)
1. Preparation (1-2 days): add Snowflake service alongside the Redis one; a @Primary HybridIdGeneratorService adapter switches on zhichai.id.strategy (snowflake | redis); unit tests for uniqueness (1M concurrent), monotonicity, and clock rollback.
2. Gray testing (3-5 days): full switch in test; production dual-writes (Snowflake ID used, Redis ID logged for comparison). Monitor latency P50/P99/P999, uniqueness scans, clock-rollback counts, sequence overflow.
3. Production cutover (1 day): low-traffic window (e.g., 02:00), gradual rollout 10% → 30% → 50% → 100%, observe 24h; rollback = flip strategy: redis (<5 min).
4. Cleanup (1 week later): delete the Redis generator, counter keys (biz:id:*), and the strategy switch.
Compatibility: no data migration needed — old and new IDs are both Long, and Snowflake IDs (≈16 digits) never collide with old Redis IDs (4-10 digits).
Risks and mitigations
Monitoring
Prometheus metrics for generation duration histogram, generation counters, clock-rollback count, sequence overflow; AlertManager rules for P99 latency > 10ms, any clock-rollback rate > 0, and any Neo4j constraint violations (critical).
Decisions and open items
| Decision | Choice | Rationale | |---|---|---| | ID strategy | Snowflake | Performance, availability, distributed-friendly | | Worker ID allocation | Static config | Simple, controllable; upgradeable later | | Library | Hutool | Already a dependency, mature | | Migration | Gray-scale cutover | Minimal risk |
Open items: production worker ID allocation rules (static vs. auto), monitoring dashboard ownership, and whether to expose an ID-parsing API.