数据库如何合理生成主键:UUID、雪花算法

这篇具有很好参考价值的文章主要介绍了数据库如何合理生成主键:UUID、雪花算法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

1.使用自增主键的弊端

2.主键生成算法

2.1.UUID

2.1.1.概述

2.1.2.JAVA中的UUID

2.2.雪花算法

2.2.1.概述

2.2.2.JAVA中使用雪花算法


1.使用自增主键的弊端

首先在实际工程中我们很少用1,2,3......这样的自增主键,原因如下:

  • 主键冲突
  • 性能问题
  • 安全问题

主键冲突:

比如我要跨数据库进行数据同步、或者在分布式系统中跨“分区”进行数据同步,不难想象,1,2,3......这种递增的单数字是极容易产生冲突的。

性能问题:

自增主键在数据库中使用的是自增序列来生成主键值,而在高并发情况下,多个线程可能同时请求获取下一个自增值,此时会发生竞争,因为数据库需要保证每个自增值只会被分配一次。为了保证自增值的唯一性,数据库使用锁机制来避免多个线程同时获取同一个自增值。

安全问题:

使用自增主键可以很容易地猜测出下一条记录的主键值,这可能会导致一些安全问题。

综上所述,我们可以发现使用复杂主键是很有必要的,要生成复杂且具有唯一性的主键就需要依赖主键生成算法了。

2.主键生成算法

常见的主键生成算法:

  • UUID
  • 雪花算法

2.1.UUID

2.1.1.概述

UUID,通用唯一标识符,UUID算法的核心思想是生成一个128位的唯一标识符,通常表示为32个十六进制数字的字符串。每个UUID会尽量保证其唯一性。

UUID算法目前有几个官方推出的版本,由Internet工程任务组(IETF)、国际标准化组织(ISO)和国际电信联盟(ITU)共同制定:

  1. UUIDv1:基于时间戳和MAC地址生成UUID,保证同一台计算机上生成的UUID是唯一的,但不适合在分布式系统中使用。

  2. UUIDv2:基于DCE安全机制的UUID,使用POSIX的UID/GID和当前时间生成UUID,不常用。

  3. UUIDv3:基于命名空间和字符串生成UUID,使用MD5散列算法生成UUID。

  4. UUIDv4:使用随机数生成UUID,保证在所有计算机上都是唯一的。

  5. UUIDv5:与UUIDv3类似,但使用SHA-1散列算法生成UUID。

其实本质上来说UUID只是个概念,UUID的算法我们甚至可以自己去写一个,只是我们自己写的肯定会没那么优质,保证唯一性的效果不会好。

2.1.2.JAVA中的UUID

工程上我们一般都是在JAVA后端生成UUID作为每条要插入数据库的数据的主键,JAVA中生成UUID很简单:

import java.util.UUID;

public class UUIDExample {
    public static void main(String[] args) {
        // 生成一个随机的UUID
        UUID uuid = UUID.randomUUID();
        System.out.println("Random UUID: " + uuid.toString());
    }
}

生成过程其实也很简单:

public static UUID randomUUID() {
    SecureRandom ng = Holder.numberGenerator;

    byte[] randomBytes = new byte[16];
    ng.nextBytes(randomBytes);
    randomBytes[6]  &= 0x0f;  /* clear version        */
    randomBytes[6]  |= 0x40;  /* set to version 4     */
    randomBytes[8]  &= 0x3f;  /* clear variant        */
    randomBytes[8]  |= 0x80;  /* set to IETF variant  */
    return new UUID(randomBytes);
}
  1. 首先从Holder静态内部类中获取一个SecureRandom对象。Holder类是一个懒加载的单例类,用于确保SecureRandom对象只被创建一次,并且线程安全。

  2. 然后生成一个长度为16的字节数组randomBytes,使用ng.nextBytes(randomBytes)方法填充随机数。

  3. 接下来将字节数组randomBytes中的一些特定位进行修改,以符合UUID版本4的格式要求:

    • 将第7个字节的高4位清零,再将其低4位设置为4,表示这是UUID版本4。
    • 将第9个字节的高2位清零,再将其第7位设置为1,表示这是符合IETF标准的UUID。
  4. 最后,将修改后的字节数组作为参数,调用UUID(byte[] data)构造方法生成一个UUID对象。

2.2.雪花算法

2.2.1.概述

雪花算法(Snowflake Algorithm)是Twitter公司开发的一种分布式ID生成算法,用来生成64位的唯一ID。它的核心思想是:利用一个64位的long型数字作为全局唯一ID,高位部分表示时间戳,中间部分表示机器ID,低位部分表示在此机器上的序列号。

数据库如何合理生成主键:UUID、雪花算法

雪花算法的64位long型数字由以下几个部分组成:

  • 符号位(1 bit):由于long型数字是有符号的,而雪花算法生成的ID必须是正数,所以符号位固定为0。
  • 时间戳部分(41 bit):记录时间戳,精确到毫秒级别,可以使用当前时间减去一个固定的起始时间,得到一个相对时间戳,从而可以使用41位二进制数表示该时间戳可支持的时间范围为约69年。
  • 机器ID部分(10 bit):可以配置多台机器,每台机器都分配一个唯一的ID,用于在分布式环境下防止ID重复。
  • 序列号部分(12 bit):表示在同一毫秒内生成的序列号,可以使用自增来实现,最多支持4096个ID。

2.2.2.JAVA中使用雪花算法

原生JDK中并没有提供雪花算法的实现,在一些常用的ORM框架中支持了使用雪花算法生成主键ID的功能,如hibernate、mybatis-plus。

以使用Hibernate为例:

可以在实体类的主键字段上使用@GenericGenerator注解和@GeneratedValue注解,其中@GenericGenerator注解用来指定主键生成器的名称和类型,@GeneratedValue注解则用来指定主键生成策略和生成器的名称,例如:

@Entity
@Table(name = "user")
public class User {
 
    @Id
    @GenericGenerator(name = "snowflake", strategy = "com.xxx.snowflake.SnowflakeIdGenerator")
    @GeneratedValue(generator = "snowflake")
    @Column(name = "id")
    private Long id;
 
    // ...
}

以mybatis-plus为例:

配置主键生成器为雪花算法的生成器

mybatis-plus:
  global-config:
    db-config:
      id-type: ASSIGN_ID
      key-generator: com.baomidou.mybatisplus.core.incrementer.SnowflakeKeyGenerator

然后给主件指定使用所配置的主键生成器文章来源地址https://www.toymoban.com/news/detail-435524.html

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import lombok.Data;

@Data
public class User {

    @TableId(type = IdType.ASSIGN_ID)
    private Long id;

    private String name;

    private Integer age;

    // 其他字段省略...
}

到了这里,关于数据库如何合理生成主键:UUID、雪花算法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据库的星型模型与雪花模型

    星型模式模型可以被描述为一个简单的星型结构:一个中心表包含事实数据,多个表从它向外辐射,由数据库的主键和外键连接。 在星型模式实施中,数据库的构建者将所有维度级别的维度数据存储在单个表或视图中。 例如,如果您使用星型模式实现Product维度,那么数据库

    2024年02月12日
    浏览(41)
  • 数据库----------约束、主键约束

    目录 1.简介 1.概念 2.作用 3.分类 2.主键约束  1.概念 2.操作 1.添加单列主键 2.添加多列联合主键 3. 通过修改表结构添加主键 4.删除主键 3.自增长约束(auto_increment) 1.概念 2.特点 3.指定自增字段初始值 4.delete和truncate在删除后自增列的变化 4.非空约束(not null) 1.概念 2.语法 3.添加

    2023年04月09日
    浏览(38)
  • 达梦数据库,数据库重置主键id从1开始

    今天中国国寿XX项目XC环境达梦遇到id主键自增顺序不对的问题,那么如何修改一个表的自增主键顺序呢?下边通过具体测试案例进行深入分析,通过delete/update/truncate/alter观察数据的变换总结出结论,欢迎各位喜欢达梦数据的爱国人士一起研究学习一下。 创建测试表 查看结果

    2024年02月09日
    浏览(43)
  • MySQL:创建数据库,数据表,主键和外键

    目录 前言: 安装MySQL: 打开MySQL: 创建数据库: 查看已建数据库: 查看数据库引擎: 创建数据表:  主键约束: 单字段主键: 多字段联合主键: 外键约束: MySQL数据库安装了很久,一直也没静下心来学习,因为起步太晚,所以什么都想学点,又感觉有些力不从心,目前

    2023年04月27日
    浏览(135)
  • MyBatis-Plus主键策略(雪花算法16位长度的整型id,解决默认雪花算法生成19位长度id导致JS精度丢失问题)

    js表达的最大整数2的53次方减1,精度丢失后面几位全是0! 如果内置支持不满足你的需求,可实现 IKeyGenerator 接口来进行扩展. 举个栗子 #方式一:使用配置类 #方式二:通过 MybatisPlusPropertiesCustomizer 自定义 #方式一: XML 配置 #方式二:注解配置 官方示例 官方id generator示例 htt

    2023年04月08日
    浏览(43)
  • Hibernate适配DM数据库主键自增配置

    hibernate有多种生成主键策略,例如assigned、increment、hilo、seqhilo、sequence、identity、native、uuid、guid等方法,其中native由hibernate根据使用的数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式,灵活性很强。如果能支持identity则使用identity,如果支持sequence则使用

    2023年04月24日
    浏览(47)
  • 为什么数据库要允许没有主键的表存在

    在数据库设计中,主键是一个关键概念,用于唯一标识数据库表中的每一行数据。然而,有时候数据库允许没有主键的表存在的情况,这可能会引起一些争议和疑问。本文将探讨为什么数据库允许没有主键的表以及相关的考虑因素。 主键在数据库中具有以下作用: 唯一标识

    2024年02月08日
    浏览(68)
  • Oracle 数据库实现主键字段自增的方法

    前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站,这篇文章男女通用,看懂了就去分享给你的码吧。 在 Oracle 数据库中,实现主键字段的自增功能对于确保数据的唯一性和简化数据插入操作非常重要。本文将介绍如

    2024年02月12日
    浏览(46)
  • MySQL数据库——MySQL AUTO_INCREMENT:主键自增长

    在 MySQL 中,当主键定义为自增长后,这个主键的值就不再需要用户输入数据了,而由数据库系统根据定义自动赋值。每增加一条记录,主键会自动以相同的步长进行增长。 通过给字段添加  AUTO_INCREMENT  属性来实现主键自增长。语法格式如下: 默认情况下,AUTO_INCREMENT 的初

    2024年02月11日
    浏览(37)
  • UUID的弊端以及雪花算法

    前言 问题 一般通用解决方案 雪花算法 系统唯一ID是我们在设计一个系统的时候常常会遇见的问题,也常常为这个问题而纠结。 这篇文章就是给各位看官提供一个生成分布式唯一全局id生成方案的思路,希望能帮助到大家。 不足之处,请多多指教!! 基于 Spring Boot + MyBatis

    2024年02月07日
    浏览(82)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包