应用级自增ID的生成

背景:以前一直使用数据库的自增ID作为数据表的主键,ID的唯一性由数据库控制,在传统单机系统环境下,该方式一直是比较主流的方案。然而特定情况下,需要在插入数据前就获得记录的ID,对以该ID为基础做一些业务处理(如生成唯一业务编码),这就需要在应用层面由程序控制来生成该ID。虽然应用程序可以根据时间,机器MAC,随机数等一些因子来生成ID,或者直接使用UUID;但这些方案生成的ID长度均较大,无法兼容INT类型,由此产生了方案一。

方案一:

       在程序中定义一个INT值,记录当前使用的ID值,新对象的ID为该INT值加一。为保障多线程安全,使用轻量级AtomicInteger存储(也可使用ReentrantLock)。为了系统重启后仍然保持之前的ID,每次更新ID时同时将最新值记录到数据库,系统重启后优先从数据库中读取。

方案一改进:

       每次更新数据库性能太低,增加CACHE_SIZE属性,采用分配策略,程序中优先一次性预申请多个ID备用,只有当缓存的ID都用完后才再次向数据库申请新的ID,并更新数据库中的最新值。该方案可以满足大部分的应用需要,并且性能还不错。

 

方案一的缺点:

     无法在分布式环境下使用。由于数据锁是应用内控制的,在分布式环境下将失效,多个请求在向数据库申请新的ID时,会出现重复读的情况,申请ID的请求是不允许并发的,需要通过数据库层面的加锁才能实现请求的串行化。

 

方案一的再次改进(数据库加锁):

      以MySql为例,在申请前加写锁:LOCK TABLE TABLE_IDENTITY WRITE,将其他进程的读请求锁定,申请完后解锁:UNLOCK TABLES。后续请求读取的将是更新后的新ID。

方案一的再次改进(数据分区):

     为每个分布式节点分配一个唯一ID(如1,2,3),将ID按分布式节点数切分为多个数据块(如100,200,300),第一个节点可用ID范围为1-100,第二个节点可用范围为101-200,第三个节点可用范围为201-300。在系统规模可估的情况下,该方案可有效解决并发冲突,而且无需加锁。

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值