hello,大家好,我是灰小猿!
在做分布式项目开发进行数据表结构设计时,有时候为了提高查询性能,在进行数据库表设计时,会使用自增ID来代替UUID作为数据的主键ID,但是这样就会有一个问题,数据的自增ID应该如何获取到下一个ID并且插入到库中呢?
如果你使用的是mybatisPlus,可以使用自带的自增注解加在id字段上即可,这样在数据入库时就可以自动给数据赋值自增的主键ID,
但是对于不是使用mybatisPlus或者在数据插入之前就需要获取到对象的主键ID的情况,这种方式就变得不是那么友好,所以今天给大家分享一个使用雪花算法的方式提前获取对象的自增主键ID的方法。
下面是一个实际的使用示例,演示如何在分布式项目中使用雪花算法提前获取对象主键ID。
步骤 1: 添加依赖
首先,你需要在项目中添加雪花算法的依赖。如果你使用的是 Maven,可以在 pom.xml
中添加以下内容:
XML
<dependency>
<groupId>com.github.f4b6a3</groupId>
<artifactId>snowflake-id-worker</artifactId>
<version>1.0.0</version>
</dependency>
步骤 2: 创建雪花算法ID生成器
创建一个 IdGenerator
类来生成雪花算法的ID:
java
import com.github.f4b6a3.snowflake.Snowflake;
public class IdGenerator {
private static final Snowflake snowflake = new Snowflake(1, 1);
// 自定义机器ID和数据中心ID
public static Long generateId() {
return snowflake.nextId();
}
}
步骤 3: 在实体类中使用ID生成器
在你的实体类中,使用 IdGenerator
生成ID:
java
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
@TableName("my_entity")
public class MyEntity {
// 让MyBatis-Plus使用自定义ID
@TableId(type = IdType.INPUT)
private Long id;
private String name;
// 其他字段的getter和setter
public MyEntity() {
// 使用雪花算法生成ID
this.id = IdGenerator.generateId();
}
}
步骤 4: 使用实体类
以在Service层调用为例,在你的服务层或控制器中创建 MyEntity
实例:
java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class MyEntityService {
// MyBatis-Plus的Mapper接口
@Autowired
private MyEntityMapper myEntityMapper;
public void createEntity(String name) {
MyEntity entity = new MyEntity();
entity.setName(name);
// 插入到数据库
myEntityMapper.insert(entity);
}
}
步骤 5: 配置MyBatis-Plus
确保你的 MyBatis-Plus 配置在 application.yml
或 application.properties
中正确设置:
XML
mybatis-plus:global-config:db-config:id-type: auto
这样,当你创建 MyEntity
实例时,IdGenerator
会使用雪花算法生成唯一的主键ID。然后,你可以将实体对象插入到数据库中,主键ID将在对象创建时就被设置好。
下面我们介绍一下雪花算法使用的原理:
雪花算法原理
雪花算法生成唯一自增ID的原理主要依赖于以下几个方面:
-
时间戳:雪花算法的ID包含一个时间戳部分,表示当前时间。这个时间戳部分是自定义的,从一个固定的时间点开始计数(通常是系统启动时间或某个纪元),可以精确到毫秒级别。这使得ID在同一毫秒内生成的多个ID不会重复。
-
机器ID:雪花算法还包括机器ID(数据中心ID和工作机器ID)。这保证了在分布式系统中,不同的机器生成的ID不会冲突。通过将机器ID嵌入到生成的ID中,每台机器生成的ID都具有唯一性。
-
序列号:在同一毫秒内生成多个ID时,雪花算法会使用序列号来区分这些ID。序列号是自增的,可以在同一毫秒内生成多个唯一的ID。
-
位移:生成的ID是一个长整型值(64位),其中不同的位被分配给时间戳、机器ID和序列号。例如,时间戳占用高位,机器ID占用中间位,序列号占用低位。这样可以保证在时间和机器维度上的唯一性。
雪花算法的ID结构示例
假设一个64位的ID结构:
-
1位: 符号位,始终为0。
-
41位: 时间戳部分,表示自定义纪元以来的毫秒数。
-
10位: 机器ID,分为数据中心ID和机器ID。
-
12位: 序列号,用于同一毫秒内的不同ID。
这种设计允许在高并发环境中生成大量的唯一ID,且保证在不同机器上生成的ID是唯一的。通过将时间戳、机器ID和序列号结合,雪花算法能够有效地避免ID冲突。
以上就是在分布式项目中使用雪花算法提前获取对象主键ID的方法,
除此之外还有利用Redis分别获取每一个对象自增ID的方式,感兴趣的也可以了解一下。
我是灰小猿,我们下期见!