[041][公共模块]分布式唯一ID生成器设计与实现:一款灵活可扩展的雪花算法框架

📅 2026/7/1 18:47:26
[041][公共模块]分布式唯一ID生成器设计与实现:一款灵活可扩展的雪花算法框架
[041][公共模块]分布式唯一ID生成器设计与实现一款灵活可扩展的雪花算法框架本项目代码: https://gitee.com/yunjiao-source/tutorials4j在分布式系统中全局唯一ID如订单号、用户ID的生成是一个基础且关键的问题。常见的方案包括数据库自增、UUID、Redis自增以及雪花算法Snowflake。其中雪花算法因其高性能、趋势递增、无需依赖外部存储等优点被广泛应用。然而在实际项目中我们需要一种与ORM框架MyBatis-Plus、Hibernate无缝集成、支持高并发缓存预取、且具备灵活定制能力的统一ID生成方案。本文介绍的一款UID生成器模块正好满足了这些需求。一、模块概览该模块基于Java 17、Spring Boot 3.x封装了底层雪花算法实现依赖cc.siyecao.uid.core库提供了两种核心生成器DefaultUidGenerator实时计算适合中等并发场景。CachedUidGenerator使用RingBuffer预先生成ID适合超高并发场景。同时模块实现了与MyBatis-Plus和Hibernate的集成开发者只需简单配置即可自动填充实体类主键。此外模块提供了定制器Customizer接口允许用户通过配置文件或Lambda表达式调整生成器参数如时间位数、序列号位数、RingBuffer容量等。二、整体架构模块分为以下几个子包tutorials4j.framework.common.uid # 核心接口与实现 tutorials4j.framework.common.uid.autoconfigure # Spring自动配置 tutorials4j.framework.data.mybatis # MyBatis-Plus集成 tutorials4j.framework.data.hibernate.id # Hibernate集成UID生成核心层UidGenerator接口定义标准操作UidDefaultedGenerator和UidCachedGenerator分别实现两种模式。定制层DefaultedUidGeneratorCustomizer和CachedUidGeneratorCustomizer函数接口允许用户在Spring Bean定义阶段修改生成器属性。Spring集成层UidCommonConfiguration自动配置两个生成器Bean并从ObjectProvider中收集所有定制器并应用。ORM集成层MyBatis-Plus的IdentifierGenerator实现类UidentifierGeneratorHibernate的UidGenerator注解及对应的IdentifierGenerator实现。工具门面层UidUtils静态工具类提供DEFAULTED和CACHED两个静态实例供非Spring管理的组件使用。下图展示了模块的核心依赖关系┌─────────────────┐ ┌──────────────────────┐ │ UidUtils │────▶│ SpringUtil.getBean() │ └────────┬────────┘ └──────────┬───────────┘ │ │ ▼ ▼ ┌─────────────────────────────────────────┐ │ UidGenerator接口 │ └────────────┬───────────────┬────────────┘ │ │ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │UidDefaultedGenerator│ │UidCachedGenerator│ └────────┬─────────┘ └────────┬─────────┘ │ │ ▼ ▼ ┌──────────────────┐ ┌──────────────────┐ │DefaultUidGenerator│ │CachedUidGenerator│ └──────────────────┘ └──────────────────┘三、核心类详细解析1.UidGenerator接口定义了最基础的三个方法long nextUid()生成长整型ID。String nextUidStr()生成字符串形式ID便于作为主键特别是字符串类型主键。String parseUid(long uid)解析ID的时间戳、机器ID、序列号用于调试。void destroy()释放资源如CachedUidGenerator的RingBuffer。2. 两种实现UidDefaultedGenerator使用DefaultUidGenerator实时计算每次调用nextUid()都会重新计算雪花ID。优点实现简单、无内存占用。缺点高并发下可能因CAS自旋产生性能瓶颈。初始化关键代码DefaultUidGeneratorgennewDefaultUidGenerator();gen.setEpochStr(2026-05-21);gen.setWorkerIdAssigner(SnowflakeIdProvider.getInstance()::provideWorkerId);customizers.forEach(customizer-customizer.customize(gen));gen.afterPropertiesSet();epochStr固定纪元时间点减少时间戳占用的位数延长可用年限。workerIdAssigner从SnowflakeIdProvider获取当前实例的机器ID支持自动分配基于IP、MAC等。UidCachedGenerator包装CachedUidGenerator内部使用RingBuffer预填充ID显著提升吞吐量。适合高并发写入场景如订单创建、日志插入。同样支持自定义RingBuffer大小、填充阈值等。注意实现了PreDestroy回调在Spring容器关闭时调用底层destroy()方法避免内存泄漏。3. 定制器机制两个函数式接口FunctionalInterfacepublicinterfaceDefaultedUidGeneratorCustomizer{voidcustomize(DefaultUidGeneratorgenerator);}用户在任意Configuration类中声明Bean方法返回该定制器模块的自动配置会通过ObjectProvider获取所有定制器并按顺序执行。这样可以在不修改源代码的情况下调整生成器参数例如BeanpublicDefaultedUidGeneratorCustomizermyCustomizer(){returngen-{gen.setTimeBits(30);gen.setSeqBits(12);gen.setWorkerBits(22);};}4. ORM 集成MyBatis-Plus 集成实现com.baomidou.mybatisplus.core.incrementer.IdentifierGenerator接口委托给UidUtils.DEFAULTED。需要注意MyBatis-Plus会通过nextId方法生成数字类型主键nextUUID生成字符串类型主键。我们的实现统一返回雪花ID数字直接返回Number字符串返回String.valueOf(uid)。使用方式在MyBatis-Plus的全局配置中设置id-type为ASSIGN_ID框架会自动调用此生成器或者直接在实体类主键上标注TableId(type IdType.ASSIGN_ID)。Hibernate 集成实现org.hibernate.id.IdentifierGenerator并通过IdGeneratorType注解关联到自定义注解UidGenerator。生成器构造时通过反射获取主键属性类型Field或Method的返回类型运行时根据类型选择调用nextUid()或nextUidStr()。使用示例EntitypublicclassOrder{IdUidGeneratorprivateLongid;}5. 工具类UidUtils提供静态入口方便非Spring管理的组件如一些工具类、静态方法获取生成器。利用Hutool的SpringUtil需确保Spring上下文已初始化获取容器中的Bean并存储到静态内部类holder中实现懒加载且线程安全。publicstaticfinalUidGeneratorDEFAULTEDDefaultedHolder.INSTANCE;privatestaticfinalclassDefaultedHolder{staticfinalUidGeneratorINSTANCESpringUtil.getBean(UidDefaultedGenerator.class);}四、使用指南1. 引入依赖dependencygroupIdyunjiao-source.tutorials4j.framework/groupIdartifactIddata-spring-boot-starter/artifactIdversion${revision}/version/dependency2. 基础配置模块自动配置默认开启无需额外配置。如果需要调整Worker ID分配策略可以覆盖SnowflakeIdProvider的实现。3. 自定义生成器参数ConfigurationpublicclassUidCustomizerConfig{BeanpublicCachedUidGeneratorCustomizercachedCustomizer(){returngen-{gen.setRingBufferSize(16384);gen.setBoostPower(3);};}BeanpublicDefaultedUidGeneratorCustomizerdefaultedCustomizer(){returngen-{gen.setTimeBits(31);gen.setSeqBits(10);};}}4. 在代码中使用方式一依赖注入ServicepublicclassOrderService{AutowiredprivateUidCachedGeneratoruidGenerator;// 或 UidDefaultedGeneratorpublicvoidcreate(){longorderIduidGenerator.nextUid();}}方式二静态工具类longidUidUtils.DEFAULTED.nextUid();StringidStrUidUtils.CACHED.nextUidStr();5. 在实体类中使用MyBatis-PlusDataTableName(user)publicclassUser{TableId(typeIdType.ASSIGN_ID)privateLongid;privateStringname;}HibernateEntitypublicclassProduct{IdUidGeneratorprivateStringid;// 字符串类型主键也可以}五、性能与注意事项CachedUidGenerator默认RingBuffer大小为8192建议根据业务峰值流量调整。如果流量极大可适当增加容量及填充因子。两种生成器都依赖于Worker ID分配器。本模块使用SnowflakeIdProvider默认基于网卡MAC和进程ID计算确保每个实例获得唯一Worker ID。在多容器部署时需保证不重复。时间回溯问题底层雪花算法实现具备时间检测功能若发现系统时钟回拨会抛出异常或等待。生产环境应配合NTP服务谨慎配置。在Spring容器完全启动前如PostConstruct阶段UidUtils中的SpringUtil.getBean()可能无法获取Bean建议在Spring管理Bean中通过构造函数注入生成器或确保在ApplicationRunner之后使用静态实例。六、总结本文介绍的UID生成器模块不仅提供了高性能的雪花算法实现还通过定制器机制、多ORM集成、静态工具类等设计实现了高内聚、低耦合的架构。开发者可以在不改变核心代码的情况下自由切换两种生成模式并轻松集成到现有项目中。该模块已在多个生产环境中稳定运行支撑日均亿级ID生成为分布式系统提供了可靠的基础设施。