如何优雅的使用雪花算法生成分布式唯一ID

1、概述

分布式唯一ID生成方式有很多,如大名鼎鼎的雪花算法、使用UUID生成、Redis自增、Zookeeper生成、数据库自增主键生成等等。

如果你使用的ORM框架是Mybatis Plus,且版本在3.3.0及以上,它提供了一种优雅的ID生成方式。
注:详情可参考MyBatis Plus官网。

如果你使用的是Mybatis,强烈建议切换到Mybatis Plus。注:Mybatis Plus特性。

2、用法

环境:SpringBoot + MySQL + MyBatisPlus

  • 导入Maven依赖
<dependency>
    <groupId>com.baomidougroupId>
    <artifactId>mybatis-plus-boot-starterartifactId>
    <version>3.3.0version>
dependency>
  • 修改application.yml,添加MyBatis Plus相关配置信息
mybatis-plus:
  mapper-location:- classpath: mapper/*Mapper.xml
  global-config:
    db-config:
      id-type: assign_id #自3.3.0开始,默认使用雪花算法+UUID
      table-underline: true
    banner: false
  configuration:
    log-impl: org.apache.ibatis.logging.stdout.StdOutImpl #打印SQL便于调试

这里的重点是 id-type: assign_id

  • 代码使用方式
@Override
public void add(Article article) {
    // 只需调用MyBatis Plus内置的insert即可
    this.baseMapper.insert(article);
}

如果使用的是NoSQL,如MongoDB,那么该如何使用呢?

比如文章评论点赞、吐槽等信息就很适合使用MongoDB。

  • 导入Maven依赖(和上面一致)
  • 修改SpringBoot主类
/*
    这里无需加载整个MyBatis Plus,因为只用到了ID生成器。	
    @SpringBootApplication注解包含了@EnableAutoConfiguration注解,@EnableAutoConfiguration会自动注入各种信息...
    MyBatis Plus的MybatisPlusAutoConfiguration类注解上有一个@AutoConfigureAfter注解:@AutoConfigureAfter({DataSourceAutoConfiguration.class, MybatisPlusLanguageDriverAutoConfiguration.class})
    因此,不加载 DataSourceAutoConfiguration,就不会加载MybatisPlusAutoConfiguration了。
 */
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
public class SpitApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpitApplication.class, args);
    }

    /**
     * 利用MyBatis Plus的主键ID生成器生成全局唯一ID
     * @return
     */
    @Bean
    public IdWorker idWorker() {
        return new IdWorker();
    }
}
  • 代码使用方式
@Autowired
private IdWorker idWorker;

public void add(Spit spit) {
    spit.set_id(idWorker.getIdStr());
    // TODO:执行其他操作,如初始化操作,入库等
}

3、原理

MyBatis Plus中雪花算法的实现主要在IdWorker类中。

public class IdWorker {

    /**
     * 主机和进程的机器码
     */
    private static IdentifierGenerator IDENTIFIER_GENERATOR = new DefaultIdentifierGenerator();

    /**
     * 毫秒格式化时间
     */
    public static final DateTimeFormatter MILLISECOND = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS");

    /**
     * 获取唯一ID
     *
     * @return id
     */
    public static long getId() {
        return getId(new Object());
    }

    /**
     * 获取唯一ID
     *
     * @return id
     */
    public static long getId(Object entity) {
        return IDENTIFIER_GENERATOR.nextId(entity).longValue();
    }

    /**
     * 获取唯一ID
     *
     * @return id
     */
    public static String getIdStr() {
        return getIdStr(new Object());
    }

    /**
     * 获取唯一ID
     *
     * @return id
     */
    public static String getIdStr(Object entity) {
        return IDENTIFIER_GENERATOR.nextId(entity).toString();
    }

    /**
     * 格式化的毫秒时间
     */
    public static String getMillisecond() {
        return LocalDateTime.now().format(MILLISECOND);
    }

    /**
     * 时间 ID = Time + ID
     * 

例如:可用于商品订单 ID

*/
public static String getTimeId() { return getMillisecond() + getIdStr(); } /** * 有参构造器 * * @param workerId 工作机器 ID * @param dataCenterId 序列号 * @see #setIdentifierGenerator(IdentifierGenerator) */ public static void initSequence(long workerId, long dataCenterId) { IDENTIFIER_GENERATOR = new DefaultIdentifierGenerator(workerId, dataCenterId); } /** * 自定义id 生成方式 * * @param identifierGenerator id 生成器 * @see GlobalConfig#setIdentifierGenerator(IdentifierGenerator) */ public static void setIdentifierGenerator(IdentifierGenerator identifierGenerator) { IDENTIFIER_GENERATOR = identifierGenerator; } /** * 使用ThreadLocalRandom获取UUID获取更优的效果 去掉"-" */ public static String get32UUID() { ThreadLocalRandom random = ThreadLocalRandom.current(); return new UUID(random.nextLong(), random.nextLong()).toString().replace(StringPool.DASH, StringPool.EMPTY); } }

示例代码如下:

  • MySQL示例:https://github.com/panjings/developer-community/tree/master/dc-article
  • MongoDB示例:https://github.com/panjings/developer-community/tree/master/dc-spit

你可能感兴趣的:(java)