原创
JPA使用雪花算法自动生成唯一主键ID
温馨提示:
本文最后更新于 2020年11月17日,已超过 1,479 天没有更新。若文章内的图片失效(无法正常加载),请留言反馈或直接联系我。
平常使用
UUID自动生成主键,但是尽量还是不要使用UUID作为主键,在数据量大的时候,UUID做主键稍显慢一点。
好处就是本地生成,不要基于数据库来了;不好之处就是,UUID 太长了、占用空间大,作为主键性能太差了;更重要的是,UUID 不具有有序性,会导致 B+ 树索引在写的时候有过多的随机写操作(连续的 ID 可以产生部分顺序写),还有,由于在写的时候不能产生有顺序的 append 操作,而需要进行 insert 操作,将会读取整个 B+ 树节点到内存,在插入这条记录后会将整个节点写回磁盘,这种操作在记录占用空间比较大的情况下,性能下降明显。
总而言之,就是:
- innodb中的主键索引也是聚集索引,如果插入的数据是顺序的,那么b+树的叶子基本都是满的,缓存也可以很好的发挥作用。如果插入的数据是完全无序的,那么叶子节点会频繁分裂,缓存也基本无效了。这会减少tps。
- uuid占用的空间较大。
@Id
@GeneratedValue(generator = "uuidGenerator")
@GenericGenerator(name = "uuidGenerator", strategy = "uuid")
@Column(nullable = false, length = 32)
private String id;
如何改进?
其实MySQL官方是推荐使用自增主键作为ID性能是最好的,但是在对于分布式环境中、数据量大的情况下、分库分表的时候,使用自增主键就不太好了。推荐还是使用雪花算法。那么JPA中我们知道有直接使用注解UUID的,我们可以写一个使用雪花算法的。
配置类SnowflakeProperties
雪花算法配置:
@Data
@Configuration
@ConfigurationProperties(prefix = "snowflake")
public class SnowflakeProperties {
/**
* 工作节点ID
*/
private Long workerId;
/**
* 数据中心ID
*/
private Long datacenterId;
}
初始化SnowFlake配置/Bean
初始化Bean:
@Configuration
@RequiredArgsConstructor
public class SnowFlake {
private final SnowflakeProperties snowflakeProperties;
/**
* 初始化SnowflakeIdWorker Bean
*
* @return SnowflakeIdWorker
*/
@Bean
public Snowflake snowflake() {
return new Snowflake(snowflakeProperties.getWorkerId(), snowflakeProperties.getDatacenterId());
}
}
集成JPA配置GenerateSnowflakeId
实现接口IdentifierGenerator
,类路径com.lzhpo.snowflake.GenerateSnowflakeId
:
public class GenerateSnowflakeId implements IdentifierGenerator, Configurable {
@Override
public void configure(Type type, Properties params, ServiceRegistry serviceRegistry) throws MappingException {
}
@Override
public Serializable generate(SharedSessionContractImplementor session, Object object) throws HibernateException {
return SpringUtil.getBean(Snowflake.class).nextId();
}
}
使用
使用:
com.lzhpo.snowflake.GenerateSnowflakeId
就是GenerateSnowflakeId
:
@Id
@GenericGenerator(name = "snowflakeId", strategy = "com.lzhpo.snowflake.GenerateSnowflakeId" )
@GeneratedValue(generator = "snowflakeId")
@Column(name = "id")
private Long id;
- 本文标签: Java SpringBoot Spring
- 本文链接: http://www.lzhpo.com/article/162
- 版权声明: 本文由lzhpo原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权