UJCMS后端二次开发教程15-主键生成

2023-12-20 23:15 阅读

常用策略

自增主键

依赖数据库的功能,mysql、sqlserver有主键自增功能,oracle、db2则没有;postgresql可以将序列值设置成默认值,实现主键自增功能。

没有跨平台需求时,可以考虑使用。分库、分表时,不能使用。

数据库序列

依赖数据库的功能,mysql没有序列。

没有跨平台需求时,可以考虑使用。分表可以使用,分库不能使用。

UUID

不依赖数据库。通过程序产生一个32位的不重复的字符串。由于字符串过长且无序,作为主键容易影响数据库性能,一般不建议使用。

Table策略

使用一个单独的数据库表来记录其它表的主键值,模仿数据库序列的功能。

缺点是ID值和数据量容易被猜测(主键自增和数据库序列都有这个问题)。

数据量不是特别大的情况下,ID值可以设置为int,占用空间少,性能较好。

通用性好,可以跨平台。分表可以使用,分库不能使用。

雪花算法

使用一个长整型作为主键ID。最高1位是符号位(一般不用),41位用于存放时间戳(共69年),10位作为机器(共2014台机器),12位作为序列号(共4096个ID)。

ID无法被猜测,且隐藏了系统中数据量的大小。

适合分库、分表场合,是分布式系统的首选。即使不分表分库也是一个很好的选择。特别是数据量敏感或者ID需保密的表。

UJCMS的Table策略主键

UJCMS(9.0及之前版本)的主键使用Table策略,主键表为ujcms_seq

主键缓存

由于获取主键需要使用数据库锁,频繁获取主键性能较低,所以一次会获取多个主键。默认一次获取50个主键。配置文件为WEB-INF/classes/application.yaml(源码则为src/resources/application.yaml),配置项为ujcms.sequence-cache-size: 50

对于个别表需要单独调整主键缓存大小的,可以设置主键表ujcms_seqcache_size_字段。该字段为0则使用上述程序中的默认大小,如指定大于0的值,则以数据库的设定为准。

由于一次取出多个主键值,一旦程序重启,未使用的主键值将会浪费,导致数据库表里的ID值不连续。这是正常现象,不影响程序使用。

主键接口

com.ujcms.cms.core.service.SeqService

    /**
     * 获取下一个序列值
     *
     * @param name 序列名称。一般为表名。
     */
    public int getNextVal(final String name) {
        ...
    }

    /**
     * 获取下一个长整型序列值
     *
     * @param name 序列名称。一般为表名。
     */
    public long getNextLongVal(final String name) {
        ...
    }

UJCMS的雪花主键

从UJCMS 9.5开始,改用雪花主键。原因如下:

  • 自增ID可猜测网站数据量。某些用户不希望泄露数据量的信息
  • 自增ID可通过穷举法抓取数据
  • 直接往数据库里插入数据时,自增ID如处理不当,容易出现ID重复的冲突

雪花主键接口

com.ujcms.commons.db.identifier.SnowflakeSequence

    /**
     * 获取下一个 ID
     *
     * @return 下一个 ID
     */
    public synchronized long nextId() {
        ...
    }

雪花主键的改进

常规的雪花主键只能使用69年,这个时间有一点偏少;而每毫秒可以产生4096个主键,每秒可以产生4,096,000个主键,则太多。

UJCMS中,增加了使用年限为552年(69*2*2*2),减少了每毫秒可产生的主键数量为5124096/2/2/2),每秒可以产生512,000个主键,即每秒51.2万个主键。足够大多数情况下的使用。

QQ咨询
电话
微信
微信扫码咨询