全局唯一序列号生成器-支持分布式
生活随笔
收集整理的這篇文章主要介紹了
全局唯一序列号生成器-支持分布式
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
文章目錄
- 全局唯一序列號生成器-支持分布式
- 核心類
- 實體類
- 表結構
- 核心邏輯解釋
全局唯一序列號生成器-支持分布式
場景:在某些業務場景,需要生成唯一的序列號,來定位某一個條數據,且必須保證全局唯一,例如:交易流水號等。
核心類
/*** 序列號生成服務*/ @Service public class SnGenerator {private static final Logger logger = LoggerFactory.getLogger(SnGenerator.class);private HashMap<String,SeqFragmentDefine> seqMap;@ResourceTblXxxBatseqCtrlMapper tblXxxBatseqCtrlMapper;SnGenerator(){seqMap=new HashMap();}public synchronized String getSeq(String seqName,int length){//從內存中去取SeqFragmentDefine seqDefine= seqMap.get(seqName);if(seqDefine==null){//如果為空,存入新對象seqMap.put(seqName,new SeqFragmentDefine());getNewFragment(seqName) ;}else{//如果不為空,將內存中seqDefine對象seqCurrent+1seqDefine.setSeqCurrent(seqDefine.getSeqCurrent()+1);//如果當前值大于最大值,重新生成seqDefine對象if(seqDefine.getSeqCurrent()>seqDefine.getSeqFragmentMax()){getNewFragment(seqName) ;}}return String.format(String.format("%%0%dd",length),seqMap.get(seqName).getSeqCurrent());}@Transactionalprotected void getNewFragment(String seqName){logger.debug("獲取流水號段 事務開始");//從緩存中取出Seq序列號對象SeqFragmentDefine seqDefine= seqMap.get(seqName);TblXxxBatseqCtrl TblXxxBatseqCtrl=tblXxxBatseqCtrlMapper.selectForUpdateByPrimaryKey(seqName);//如果對象存在,則賦值+1if(TblXxxBatseqCtrl!=null){seqDefine.setSeqFragmentMax(TblXxxBatseqCtrl.getSeqNo()+TblXxxBatseqCtrl.getStepLength());//130000seqDefine.setSeqCurrent(TblXxxBatseqCtrl.getSeqNo()+1);TblPipXxxBatseqCtrl.setSeqNo(seqDefine.getSeqFragmentMax());//130000//TblPipXxxBatseqCtrl.setSeqNo(seqDefine.getSeqCurrent());//120001tblPipXxxBatseqCtrlMapper.updateByPrimaryKey(TblPipXxxBatseqCtrl);}else{//如果不存在對象,重新創建TblPipXxxBatseqCtrlInsert值,SeqCurrent從0開始,SeqFragmentMax(10000)TblPipXxxBatseqCtrl TblPipXxxBatseqCtrlInsert=new TblPipXxxBatseqCtrl();TblPipXxxBatseqCtrlInsert.setSeqName(seqName);TblPipXxxBatseqCtrlInsert.setStepLength(10000);TblPipXxxBatseqCtrlInsert.setSeqNo(Long.valueOf(10000));tblPipXxxBatseqCtrlMapper.insertSelective(TblXxxBatseqCtrlInsert);seqDefine.setSeqCurrent(0+1);//下一個從1開始seqDefine.setSeqFragmentMax(0+10000);//最大值為10000}logger.debug("獲取流水號段 事務結束");}class SeqFragmentDefine{//當前段的最大值(包含)private long seqFragmentMax;private long seqCurrent;public long getSeqFragmentMax() {return seqFragmentMax;}public void setSeqFragmentMax(long seqFragmentMax) {this.seqFragmentMax = seqFragmentMax;}public long getSeqCurrent() {return seqCurrent;}public void setSeqCurrent(long seqCurrent) {this.seqCurrent = seqCurrent;}} }實體類
public class TblXxxBatseqCtrl extends BaseEntity {private String seqName;private Long seqNo;private Integer stepLength;private Date recCrtTs;private Date recUpdTs;public String getSeqName() {return seqName;}public void setSeqName(String seqName) {this.seqName = seqName == null ? null : seqName.trim();}public Long getSeqNo() {return seqNo;}public void setSeqNo(Long seqNo) {this.seqNo = seqNo;}public Integer getStepLength() {return stepLength;}public void setStepLength(Integer stepLength) {this.stepLength = stepLength;}public Date getRecCrtTs() {return recCrtTs;}public void setRecCrtTs(Date recCrtTs) {this.recCrtTs = recCrtTs;}public Date getRecUpdTs() {return recUpdTs;}public void setRecUpdTs(Date recUpdTs) {this.recUpdTs = recUpdTs;} }表結構
drop table if exists tbl_Xxx_batseq_ctrl; CREATE TABLE tbl_Xxx_batseq_ctrl (seq_name varchar(20) NOT NULL, seq_no bigint NOT NULL comment '已經使用到的最大值(包含)', step_length int, rec_crt_ts timestamp DEFAULT CURRENT_TIMESTAMP, rec_upd_ts timestamp DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (seq_name)) ENGINE=InnoDB DEFAULT CHARSET=utf8 DEFAULT COLLATE=utf8_general_ci;核心邏輯解釋
- format器
String.format(String.format("%%0%dd",length),seqMap.get(seqName).getSeqCurrent())
等價于String.format("%0"+length+“d”,seqMap.get(seqName).getSeqCurrent())
例如: String.format("%08d",1)
輸出: 00000001
例如: String.format("%08d",-1)
輸出:-0000001
例如: String.format("%08d",200000001)
輸出:200000001 (超出長度,輸出原值)
- 設計邏輯
a.每次啟動,分配步長為10000的序列號給服務器節點使用
b.以損耗序列號資源來換取數據庫服務器的高性能,每個節點的序列號值,不更新到數據庫
c.由于synchronized關鍵字,解決了并發問題
- 內存圖解
學習Java的同學注意了!!!
學習過程中遇到什么問題或者想獲取學習資源的話,歡迎加入Java學習交流群,群號碼:543120397 我們一起學Java!
總結
以上是生活随笔為你收集整理的全局唯一序列号生成器-支持分布式的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 基于单片机智能交通灯控制系统设计外文文献
- 下一篇: BIOS 的详细介绍