您好,登錄后才能下訂單哦!
本篇內容主要講解“數據庫如何使用數據生成Sequence”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“數據庫如何使用數據生成Sequence”吧!
twitter 開源的分布式 id 生成算法,使用64 位的 long 型的 id。
41 bit,時間戳,單位為毫秒,2^41 - 1 換算成年可以表示69年的時間
10 bit,其中5個表示機房,5個表示機器ID
12 bit,錄同一個毫秒內產生的不同 id,2^12 - 1 = 4096,可以表示同一個毫秒內的 4096 個不同的 id
支持每秒幾萬并發
public class UniqueOrderGenerate {// ==============================Fields===========================================/** 開始時間截 (2018-07-03) */private final long twepoch = 1530607760000L;/** 機器id所占的位數 */private final long workerIdBits = 5L;/** 數據標識id所占的位數 */private final long datacenterIdBits = 5L;/** 支持的最大機器id,結果是31 (這個移位算法可以很快的計算出幾位二進制數所能表示的最大十進制數) */private final long maxWorkerId = -1L ^ (-1L << workerIdBits);/** 支持的最大數據標識id,結果是31 */private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);/** 序列在id中占的位數 */private final long sequenceBits = 12L;/** 機器ID向左移12位 */private final long workerIdShift = sequenceBits;/** 數據標識id向左移17位(12+5) */private final long datacenterIdShift = sequenceBits + workerIdBits;/** 時間截向左移22位(5+5+12) */private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;/** 生成序列的掩碼,這里為4095 (0b111111111111=0xfff=4095) */private final long sequenceMask = -1L ^ (-1L << sequenceBits);/** 工作機器ID(0~31) */private long workerId;/** 數據中心ID(0~31) */private long datacenterId;/** 毫秒內序列(0~4095) */private long sequence = 0L;/** 上次生成ID的時間截 */private long lastTimestamp = -1L;//==============================Constructors=====================================/** * 構造函數 * @param workerId 工作ID (0~31) * @param datacenterId 數據中心ID (0~31) */public UniqueOrderGenerate(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;}// ==============================Methods==========================================/** * 獲得下一個ID (該方法是線程安全的) * @return SnowflakeId */public synchronized long nextId() {long timestamp = timeGen();//如果當前時間小于上一次ID生成的時間戳,說明系統時鐘回退過這個時候應當拋出異常if (timestamp < lastTimestamp) {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;}//上次生成ID的時間截lastTimestamp = timestamp;//移位并通過或運算拼到一起組成64位的IDreturn (((timestamp - twepoch) << timestampLeftShift) //| (datacenterId << datacenterIdShift) //| (workerId << workerIdShift) //| sequence);}/** * 阻塞到下一個毫秒,直到獲得新的時間戳 * @param lastTimestamp 上次生成ID的時間截 * @return 當前時間戳 */protected long tilNextMillis(long lastTimestamp) {long timestamp = timeGen();while (timestamp <= lastTimestamp) {timestamp = timeGen();}return timestamp;}/** * 返回以毫秒為單位的當前時間 * @return 當前時間(毫秒) */protected long timeGen() {return System.currentTimeMillis();}//==============================Test=============================================/** 測試 */public static void main(String[] args) {UniqueOrderGenerate idWorker = new UniqueOrderGenerate(0, 0);for (int i = 0; i < 1000; i++) {long id = idWorker.nextId();//System.out.println(Long.toBinaryString(id));System.out.println(id);}}}
在數據庫中維護一張表
CREATE TABLE `sequence` ( `ID` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT 'ID', `unique_id` bigint(18) DEFAULT NULL COMMENT 'unique_id', `UPDATED_TIME` timestamp NOT NULL COMMENT '更新時間', PRIMARY KEY (`ID`))
初始化:
設置步長step=5000, min = 0, max = 5000
截取時間字符串到當天,curTime = ‘20190520’
和步長拼接,uniqueId = curTime + step = 201905201000
主要思路:
每臺應用服務器預先取步長,存在JVM內存中,nextKey++,步長用盡,更新數據庫。
數據庫建表,保存uniqueId,updateTime
設置數據庫更新步長,每次到達步長更新數據庫
根據業務量設置uniqueId長度,可以使用bigInt
時間加步長拼接作為唯一id
偽代碼
取步長 getUniqueueId() {if nextKey > max || curTime == null operaDb() nextKey++ seq = curTime + step}操作數據庫 operatDb() {查詢db當前uniqueId 當前uniqueId + step}
到此,相信大家對“數據庫如何使用數據生成Sequence”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。