プロジェクトがグローバル一意のidプライマリ・キーを生成する方法

7600 ワード

一.新規自己増分リスト方式
mysqlを使用して、idだけが自動的に増加するテーブルを新規作成し、idを取得するたびに、まず自己増順リストにデータを書き込み、idを取得します.
CREATE TABLE `org_dept`  (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`) USING BTREE
); 

欠点:
1.ライブラリシーンには適用されません
2.特高同時シーンには適用されません
メリット:
1.mysqlデータベース自体によるシンプル化
二.新規シーケンス方式
Oracle、SQLserverに適用
--      1    :
create sequence seq_id increment 1 start 1000000000000 ;

--      2    :
create sequence seq_id increment 1 start 2000000000000 ;

--       
create table t_table_name(
  n_id bigint not null default nextval('seq_id'), --          
--     
primary key(n_id)
);

メリット:
1.適用ライブラリ表
三.UUID方式
UUIDにより生成
メリット:
1.第三者に依存しない
欠点:
1.不連続
四.スノーアルゴリズム
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import lombok.ToString;

/**   
* Copyright: Copyright (c) 2019 
* 
* @ClassName: IdWorker.java
* @Description: 

SnowFlake , Twitter id 。 * : 64 bit long id。 * 64 bit , 1 bit , 41 bit , * 10 bit id,12 bit *

* @version: v1.0.0 * @author: BianPeng * @date: 2019 4 11 3:13:41 * * Modification History: * Date Author Version Description *---------------------------------------------------------------* * 2019 4 11 BianPeng v1.0.0 initialize */ @ToString public class SnowflakeIdFactory { static Logger log = LoggerFactory.getLogger(SnowflakeIdFactory.class); private final long twepoch = 1288834974657L; private final long workerIdBits = 5L; private final long datacenterIdBits = 5L; private final long maxWorkerId = -1L ^ (-1L << workerIdBits); private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits); private final long sequenceBits = 12L; private final long workerIdShift = sequenceBits; private final long datacenterIdShift = sequenceBits + workerIdBits; private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; private final long sequenceMask = -1L ^ (-1L << sequenceBits); private long workerId; private long datacenterId; private long sequence = 0L; private long lastTimestamp = -1L; public SnowflakeIdFactory(long workerId, long datacenterId) { if (workerId > maxWorkerId || workerId < 0) { throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); } if (datacenterId > maxDatacenterId || datacenterId < 0) { throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); } this.workerId = workerId; this.datacenterId = datacenterId; } public synchronized long nextId() { long timestamp = timeGen(); if (timestamp < lastTimestamp) { // ,ID . throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp)); } if (lastTimestamp == timestamp) { sequence = (sequence + 1) & sequenceMask; if (sequence == 0) { timestamp = tilNextMillis(lastTimestamp); } } else { sequence = 0L; } lastTimestamp = timestamp; return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) | (workerId << workerIdShift) | sequence; } protected long tilNextMillis(long lastTimestamp) { long timestamp = timeGen(); while (timestamp <= lastTimestamp) { timestamp = timeGen(); } return timestamp; } protected long timeGen() { return System.currentTimeMillis(); } public static void testProductIdByMoreThread(int dataCenterId, int workerId, int n) throws InterruptedException { List tlist = new ArrayList<>(); Set setAll = new HashSet<>(); CountDownLatch cdLatch = new CountDownLatch(10); long start = System.currentTimeMillis(); int threadNo = dataCenterId; Map idFactories = new HashMap<>(); for(int i=0;i<10;i++){ // map key. idFactories.put("snowflake"+i,new SnowflakeIdFactory(workerId, threadNo++)); } for(int i=0;i<10;i++){ Thread temp =new Thread(new Runnable() { @Override public void run() { Set setId = new HashSet<>(); SnowflakeIdFactory idWorker = idFactories.get(Thread.currentThread().getName()); for(int j=0;j setOne = new HashSet<>(); Set setTow = new HashSet<>(); long start = System.currentTimeMillis(); for (int i = 0; i < n; i++) { setOne.add(idWorker.nextId());// set } long end1 = System.currentTimeMillis() - start; log.info(" ID {} , {} <<<>>> :{}",n,setOne.size(),end1); for (int i = 0; i < n; i++) { setTow.add(idWorker2.nextId());// set } long end2 = System.currentTimeMillis() - start; log.info(" ID {} , {} <<<>>> :{}",n,setTow.size(),end2); setOne.addAll(setTow); log.info(" ID :{}",setOne.size()); } public static void testPerSecondProductIdNums(){ SnowflakeIdFactory idWorker = new SnowflakeIdFactory(1, 2); long start = System.currentTimeMillis(); int count = 0; for (int i = 0; System.currentTimeMillis()-start<1000; i++,count=i) { /** : ID, ID 400w+ */ //idWorker.nextId(); /** : log , ID, ID log.error() . * 10 . */ log.info(""+idWorker.nextId()); } long end = System.currentTimeMillis()-start; System.out.println(end); System.out.println(count); } public static void main(String[] args) { /** case1: id ? * : id 400w+ */ //testPerSecondProductIdNums(); /** case2: - N id, id ? * : , . */ //testProductId(1,2,10000);// ! //testProductId(1,2,20000);// ! /** case3: - N id, id ? * : , . */ try { testProductIdByMoreThread(1,2,100000);// , ! } catch (InterruptedException e) { e.printStackTrace(); } } }

メリット:
1.第三者に依存しない
2.実現が簡単
3.適用ライブラリ表