如何使用資料庫和Redis開發各系統獨立的自增ID生成器

安全劍客發表於2020-09-02
在分散式系統,需要生成唯一ID的系統不止一個,這些ID的生成在各自業務內是獨立的,同時包含業務規則,如果要利用資料庫自增主鍵生成唯一ID,需要每個業務部門建立一張表來為唯一ID服務。

而因為Redis的高效能和單執行緒特性,使它在這方面有獨特的優勢。

為了解決各個系統獨自生成自增的唯一ID的需求,而又實現簡單有效,做了如下設計。

各系統獨立的自增ID生成器
資料庫設計(mysql)
DROP TABLE IF EXISTS sys_id_record; 
CREATE TABLE sys_id_record( 
id INT UNSIGNED AUTO_INCREMENT, 
sys_id VARCHAR(40) NOT NULL COMMENT '子系統ID', 
sys_name VARCHAR(100) NOT NULL COMMENT '子系統名稱', 
id_from INT NOT NULL DEFAULT 1 COMMENT '子系統ID起始值', 
lenth SMALLINT NOT NULL DEFAULT 10 COMMENT '子系統ID長度', 
enabled VARCHAR(1) NOT NULL DEFAULT 'Y', 
created_by VARCHAR(40) NOT NULL COMMENT '建立人', 
created_date DATETIME COMMENT '建立時間', 
updated_by VARCHAR(40) NOT NULL COMMENT '更新人', 
updated_date DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新時間', 
PRIMARY KEY ( id ) 
)ENGINE=INNODB DEFAULT CHARSET=utf8;
主要程式碼
定義服務介面
package com.davidwang456.test; 
 
 
public interface IDGenerateService { 
  String getIDGenerateBySys(String sysId); 
}
介面服務實現
package com.davidwang456.test; 
 
import java.util.ArrayList; 
import java.util.List; 
 
import org.springframework.beans.factory.annotation.Autowired; 
import org.springframework.data.redis.core.RedisTemplate; 
import org.springframework.stereotype.Service; 
 
@Service 
public class IDGenerateServiceImpl implements IDGenerateService { 
   @Autowired 
   private SysIdRecordDao sysIdRecordDao; 
    
   @Autowired 
   private RedisTemplate redisTemplate; 
 
    @Override 
    public String getIDGenerateBySys(String sysId) { 
        init(sysId); 
        Object idSys=redisTemplate.opsForList().rightPop(sysId); 
        if(idSys==null) { 
            Listrecords=sysIdRecordDao.getEnabledSysIdRecord(sysId); 
            if(records!=null&&records.isEmpty()) { 
                SysIdRecord record=records.get(0); 
                 
                Listbuf_ids=new ArrayList<>(); 
                for(int i=1;i<1record.getlenth+1;i++) {="" buf_ids.add(record.getidfrom+i);="" }="" redistemplate.opsforlist().leftpushall(sysid,="" buf_ids);="" record.setidfrom(record.getidfrom()+record.getlenth());="" sysidrecorddao.save(record);="" idsys="redisTemplate.opsForList().rightPop(sysId);" return="" sysid+":"+idsys;="" private="" void="" init(string="" sysid)="" if(!redistemplate.haskey(sysid))="" listrecords=sysIdRecordDao.getEnabledSysIdRecord(sysId); 
            if(records==null||records.isEmpty()) { 
                SysIdRecord record=new SysIdRecord(); 
                //TODO 
                sysIdRecordDao.save(record); 
            } 
        } 
 
    } 
 
}
總結

這個設計的核心思想是資料庫控制各個子系統的起始值和步長,然後將值放到redis佇列中,從佇列中依此取值。當從redis中消耗掉後再次從資料庫中取一批值,依此迴圈。

原文地址:

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/31559985/viewspace-2716475/,如需轉載,請註明出處,否則將追究法律責任。

相關文章