优秀的编程知识分享平台

网站首页 > 技术文章 正文

主键ID的几种生成方式(主键id生成策略)

nanyue 2024-07-18 22:32:14 技术文章 7 ℃

概述

主键ID的几种生成方式,一般有以下几种:

  1. 自增
  2. UUID
  3. 雪花算法

下面针对这3种主键ID生成方式,简单的介绍一下优缺点。

自增

1、优点:

  • 简单、易用,无需额外的配置,数据库会自动生成主键ID。
  • 自增id是有序的,所以查询数据时效率高。

2、缺点:

  • 如果表中存在大量数据,会导致主键ID的空间不够用。
  • 数据库迁移或多库多表的情况下,主键ID的生成可能会出现重复。

3、优化方案:

  • 针对多主库(主从库也需同样设置),可以设置不同的初始值,步长可以根据库的数量设置。比如两个主库,主库1初始值1,主库2初始化值2,步长2,这样主库1的主键ID为1,3,5,主库2的主键ID为2,4,6,以此类推。
  • 增加ID的空间长度,可以使用无符号整型。int类型最大值是2147483647,uint类型最大值是4294967295
  • 在数据迁移或合并时,可以将自增ID与标识列做联合主键。比如:在多租户系统中,可以设置租户ID作为标识列,租户ID与自增ID联合作为主键。

UUID

1、优点:

  • UUID保证了唯一性,不会出现重复的主键ID。
  • 本地生成,代码非常简单
  • 数据迁移、合并、主从库同步等操作时,不会出现主键ID的冲突。

2、缺点:

  • UUID是无序的,查询效率低。
  • UUID占用空间大,长度至少36个字符,就算去掉分隔符也有32个字符。

3、优化方案:

  • 转换成16位字符串,减少占用空间
    private static string GenerateShortGuid()
    {
        long i = 1;
        foreach (byte b in Guid.NewGuid().ToByteArray())
        {
            i *= ((int)b + 1);
        }
        return string.Format("{0:x}", i - DateTime.Now.Ticks);
    }
  • 转换成19位的长整型,提高查询效率
    private static long GenerateLongID()
    {
        byte[] buffer = Guid.NewGuid().ToByteArray();
        return BitConverter.ToInt64(buffer, 0);
    }

雪花算法

1、雪花算法原理:

  • 时间戳(41位):占据ID的最高位,用于记录ID生成的时间。由于时间戳是毫秒级的,因此可以保证在单个节点上生成的ID是递增的。同时,时间戳也起到了区分不同节点生成ID的作用。
  • 工作机器ID(10位):包括5位的数据中心ID和5位的机器ID。这部分用于标识生成ID的节点,确保不同节点生成的ID不会冲突。
  • 序列号(12位):用于记录同一毫秒内生成的ID序号。由于序列号部分有12位,因此可以在同一毫秒内生成4096个不同的ID。

2、优点:

  • 长整型ID,支持大数据量
  • 根据时间戳有序生成,保证写入性能(因为插入数据时需要创建索引)
  • 生成ID的速度快,满足高并发场景的需求

3、缺点:

  • 依赖机器时钟,如果机器上时钟回拨,可能导致ID重复
  • 单机上生成的ID是递增的,在分布式环境下,可能不是全局递增的

其它主键生成方式

  1. 利用redis原子操作INCR生成主键ID。
  2. 利用数据库维护流水号,根据一定的规则生成主键ID。比如:[业务编号]+[yyyyMMdd]+[流水号]
最近发表
标签列表