主键生成策略

本文介绍了如何设计一个高效的主键生成策略,通过数据库存储过程预先生成批量主键并存入系统缓存,以提高数据插入效率。在程序中,使用缓存池存储主键,当缓存不足时再从数据库获取。这种方式适用于单服务部署,但不适用于集群环境,若要集群部署,需考虑使用分布式缓存如Redis。此外,主键由日期和递增序列号组成,确保表内唯一,但不同表间可能存在相同ID。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

介绍一个建的主键生成策略.
大体思路是这样子的:
程序中免不了要对数据进行新增操作, 而新增数据就需要一个id. 当每次插入数据时,使用数据库直接生成效率不高, 一种比较好的方法是 , 先使用数据库的sql语句(比如存储过程,函数)一次性生成1000条数据, 然后将这1000条数据放到系统缓存中. 每一次新增数据时, 从缓存中取出一条id , 这样就不用每次都从数据库直接生成. 当缓存中的数据不够用时, 我们再调用存储过程或函数, 一次性生成1000条放到缓存中.

有了这个思路, 我们就可以开始了.
我们先从数据库端开始, 因为要用数据库批量的生产主键.
先定义一个主键格式 , 格式为: yyyyMMdd + 12位序列号 (序列号递增,首端用0填充)
好了, 我们开始设计一个函数.
定义一个函数 : A( 参数1: 表名称table, 参数2: 主键数 num)
A() {
if(table中没有数据)
获取今天的日期 yyyyMMdd
生成 日期 + 序列号 的主键id
生成num条
if(table中有数据)
获取表中数据总数sum
获取今天的日期 yyyyMMdd
生成 日期 + (sum+1)开始的主键id
生成num条
返回num条主键id
}

定义一个存储过程, 存储过程调用这个函数A();
到这里, 数据库端我们就设计完成了, 每次调用存储过程, 都能拿到num条主键id .我们只需要传入表名和主键数量, 就能获取该表的新生成的主键

现在我们从程序入手, 看看程序上怎么设计
首先需要定义一个主键生成类,
类中有一个属性 Map<String , Vector> keyCatche , 这是个主键id缓存池, 我们从数据库中获取到的主键id都放在这里面, 是一个map结构的数据, 其中key存的是表名, vector存的是对应吧表生成的id.

我们还要定义一个常量, 代表缓存池的大小. 比如1000. 就代表缓存中每个表一次能存1000条主键id

我们定义一个函数来完成从数据库拿到一批主键的功能
函数GenIds( tableName , idNum)
{
创建数据库链接
调用存储过程(传入tableName , idNum)
得到一批主键
关闭数据库链接
}

我们接着来定义一个函数, 用来从缓存中获取主键id
// 参数1 tableName代表要获取那个表的ID, 参数2 idNum代表要获取多少个, 一般一次一个
函数getId(tableName , idNum)
{
if(keyCatche没有 tableName )
在缓存中新增一个tableName , Vector为空
if(keyCatche存在tableName )
Vector v = keyCatche.get(tableName)
if tableName在缓存中的id大于0
获取当前时间, 格式化时间为 yyyyMMdd , 一共8位 ,代表年月日
获取缓存中第一个id , 截取id的前8位, 和当前时间比较, 看看缓存中的id 是不是今天生成的.
如果不是,将缓存中的id清零 , 我们只要当天的id. (今天插入的id 必须要用今天的日期为id开头)
if v.size < idNum
缓存中的id个数 小于我们希望拿到的id个数 , 我们要从数据库重新去拿.
number = idNum + 1000 - v.size
// 调用我们定义的从数据库获取id的函数
list = GenIds( tableName , number )
//把新生成的id放到表对应的id缓存中
v.add(list)
//从当前缓存中顺序获取idNum个id作为函数返回值
v.get(0 , idNum)
然后从当前缓存中移除0~idNum个id , 就是说用N个id , 就要从缓存中删N个id
}

到这里, 整个设计就完成了.

需要注意的是
这样生成的id 只能保证表内唯一. 因为他的生成规则是 日期+ 递增序列号 , 不同表之间id是有可能一样的.
这样的id生成策略不支持服务的集群部署. 因为id是存在系统缓存中的. 集群部署时每个服务都有一个缓存池, 那样id换乱. 要集群部署, 起码的把id缓存池单独放在一个redis中 , 不能放在系统变量中.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值