摘要:原理的雪花算法,使用語言實現。生成的整體上按照時間自增排序,并且整個分布式系統內不會產生碰撞由和作區分,并且效率較高。據說每秒能夠產生萬個。
分布式系統中,有一些需要使用全局唯一ID的場景,這種時候為了防止ID沖突可以使用36位的UUID,但是UUID有一些缺點,首先他相對比較長,另外UUID一般是無序的。
有些時候我們希望能使用一種簡單一些的ID,并且希望ID能夠按照時間有序生成。
而twitter的SnowFlake解決了這種需求,最初Twitter把存儲系統從MySQL遷移到Cassandra,因為Cassandra沒有順序ID生成機制,所以開發了這樣一套全局唯一ID生成服務。
原理Twitter的雪花算法SnowFlake,使用Java語言實現。
SnowFlake算法產生的ID是一個64位的整型,結構如下(每一部分用“-”符號分隔):
</>復制代碼
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
1位標識部分,在java中由于long的最高位是符號位,正數是0,負數是1,一般生成的ID為正數,所以為0;
41位時間戳部分,這個是毫秒級的時間,一般實現上不會存儲當前的時間戳,而是時間戳的差值(當前時間-固定的開始時間),這樣可以使產生的ID從更小值開始;41位的時間戳可以使用69年,(1L << 41) / (1000L 60 60 24 365) = 69年;
10位節點部分,Twitter實現中使用前5位作為數據中心標識,后5位作為機器標識,可以部署1024個節點;
12位序列號部分,支持同一毫秒內同一個節點可以生成4096個ID;
SnowFlake算法生成的ID大致上是按照時間遞增的,用在分布式系統中時,需要注意數據中心標識和機器標識必須唯一,這樣就能保證每個節點生成的ID都是唯一的。或許我們不一定都需要像上面那樣使用5位作為數據中心標識,5位作為機器標識,可以根據我們業務的需要,靈活分配節點部分,如:若不需要數據中心,完全可以使用全部10位作為機器標識;若數據中心不多,也可以只使用3位作為數據中心,7位作為機器標識。
snowflake生成的ID整體上按照時間自增排序,并且整個分布式系統內不會產生ID碰撞(由datacenter和workerId作區分),并且效率較高。據說:snowflake每秒能夠產生26萬個ID。
源碼本機實測:100萬個ID 耗時5秒
</>復制代碼
/**
* 描述: Twitter的分布式自增ID雪花算法snowflake (Java版)
* https://github.com/souyunku/SnowFlake
*
* @author yanpenglei
* @create 2018-03-13 12:37
**/
public class SnowFlake {
/**
* 起始的時間戳
*/
private final static long START_STMP = 1480166465631L;
/**
* 每一部分占用的位數
*/
private final static long SEQUENCE_BIT = 12; //序列號占用的位數
private final static long MACHINE_BIT = 5; //機器標識占用的位數
private final static long DATACENTER_BIT = 5;//數據中心占用的位數
/**
* 每一部分的最大值
*/
private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
/**
* 每一部分向左的位移
*/
private final static long MACHINE_LEFT = SEQUENCE_BIT;
private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
private long datacenterId; //數據中心
private long machineId; //機器標識
private long sequence = 0L; //序列號
private long lastStmp = -1L;//上一次時間戳
public SnowFlake(long datacenterId, long machineId) {
if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
throw new IllegalArgumentException("datacenterId can"t be greater than MAX_DATACENTER_NUM or less than 0");
}
if (machineId > MAX_MACHINE_NUM || machineId < 0) {
throw new IllegalArgumentException("machineId can"t be greater than MAX_MACHINE_NUM or less than 0");
}
this.datacenterId = datacenterId;
this.machineId = machineId;
}
/**
* 產生下一個ID
*
* @return
*/
public synchronized long nextId() {
long currStmp = getNewstmp();
if (currStmp < lastStmp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate id");
}
if (currStmp == lastStmp) {
//相同毫秒內,序列號自增
sequence = (sequence + 1) & MAX_SEQUENCE;
//同一毫秒的序列數已經達到最大
if (sequence == 0L) {
currStmp = getNextMill();
}
} else {
//不同毫秒內,序列號置為0
sequence = 0L;
}
lastStmp = currStmp;
return (currStmp - START_STMP) << TIMESTMP_LEFT //時間戳部分
| datacenterId << DATACENTER_LEFT //數據中心部分
| machineId << MACHINE_LEFT //機器標識部分
| sequence; //序列號部分
}
private long getNextMill() {
long mill = getNewstmp();
while (mill <= lastStmp) {
mill = getNewstmp();
}
return mill;
}
private long getNewstmp() {
return System.currentTimeMillis();
}
public static void main(String[] args) {
SnowFlake snowFlake = new SnowFlake(2, 3);
long start = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
System.out.println(snowFlake.nextId());
}
System.out.println(System.currentTimeMillis() - start);
}
}
循環生成的ID,運行結果如下:
開源地址</>復制代碼
170916032679263329
170916032679263330
170916032679263331
170916032679263332
170916032679263333
170916032679263334
170916032679263335
170916032679263336
170916032679263337
170916032679263338
170916032679263339
170916032679263340
170916032679263341
170916032679263342
Github:https://github.com/souyunku/SnowFlake
推薦閱讀 Spring Cloud 系列教程Spring Cloud(一)服務的注冊與發現 Eureka
Spring Cloud(二)Consul 服務治理實現
Spring Cloud(三)服務提供者 Eureka + 服務消費者(rest + Ribbon)
Spring Cloud(四)服務提供者 Eureka + 服務消費者 Feign
Spring Cloud(五)斷路器監控(Hystrix Dashboard)
Spring Cloud(六)服務網關 zuul 快速入門
Spring Cloud(七)服務網關 Zuul Filter 使用
Spring Cloud(八)高可用的分布式配置中心 Spring Cloud Config
Spring Cloud(九)高可用的分布式配置中心 Spring Cloud Config 集成 Eureka 服務
Spring Cloud(十)高可用的分布式配置中心 Spring Cloud Config 中使用 Refresh
Spring Cloud(十一)高可用的分布式配置中心 Spring Cloud Bus 消息總線集成(RabbitMQ)
Spring Boot 系列教程源碼 + 教程
Github:https://github.com/souyunku/spring-boot-examples
Docker 容器Docker Compose 1.18.0 之服務編排詳解
Docker CE 安裝 初窺 Dockerfile 部署 Nginx
Docker Container 容器操作
Docker Hub 倉庫使用,及搭建 Docker Registry
Docker Registry Server 搭建,配置免費 HTTPS 證書,及擁有權限認證、TLS 的私有倉庫
Docker Registry 企業級私有鏡像倉庫Harbor管理WEB UI, 可能是最詳細的部署
Docker 部署 SpringBoot 項目整合 Redis 鏡像做訪問計數 Demo
Docker Maven Plugin 生成 Docker 鏡像 push 到 DockerHub上
環境搭建搭建 Apache RocketMQ 單機環境
手把手教你 MongoDB 的安裝與詳細使用(一)
手把手教你 MongoDB 的安裝與詳細使用(二)
搭建 MongoDB分片(sharding) / 分區 / 集群環境
搭建 SolrCloud 集群服務
搭建 Solr 單機服務
搭建 RabbitMQ 集群服務
搭建 RabbitMQ 單機服務
Mycat 讀寫分離 數據庫分庫分表 中間件 安裝部署,及簡單使用
離線部署 CDH 5.12.1 及使用 CDH 部署 Hadoop 大數據平臺集群服務
Contact作者:鵬磊
出處:http://www.ymq.io
版權歸作者所有,轉載請注明出處
Wechat:關注公眾號,搜云庫,專注于開發技術的研究與知識分享
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/68769.html
摘要:今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...
摘要:今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 今天整理了一下近大半年以來的一些文章,和我的預期一樣,很多文章我都忘記自己曾經寫過了,這個記錄的過程讓我也有了新的理解。希望大家,收藏,點贊,加轉發。 面試必備 面試必備:深入Spring MVC DispatchServlet 源碼...
摘要:關于我為什么寫這篇文章是因為今天在做訂單模塊的時候看到之前的上描述的年月日用戶位企業位四位自增長數。背景對于其定訂單的生成。個人的看法是主要是唯一,其他關于業務方面的不是太太重要。自增實現了用于將的值遞增,并返回結果。 關于我為什么寫這篇文章是因為今天在做訂單模塊的時候,看到之前的PRD上描述的年月日+用戶id2位+企業id位+四位自增長數。然后竟被我反駁的突然改成了精確時間+4位自增...
摘要:有些時候我們希望能使用一種簡單一些的,并且希望能夠按照時間有序生成。轉換成字符串后長度最多生成的整體上按照時間自增排序,并且整個分布式系統內不會產生碰撞由和作區分,并且效率較高。經測試每秒能夠產生萬個。 概述 分布式系統中,有一些需要使用全局唯一ID的場景,這種時候為了防止ID沖突可以使用36位的UUID,但是UUID有一些缺點,首先他相對比較長,另外UUID一般是無序的。 有些時候我...
摘要:序本文主要來聊聊分布式的生成方案。分布式的生成,以為代表的,系列算法采用的就是劃分命名空間并行生成的思路。 序 本文主要來聊聊分布式id的生成方案。 目標 業務系統需要什么樣的ID生成器中提出了幾點目標: 唯一性 時間相關 粗略有序 可反解 可制造 主要思路 對于每個標識,都需要有一個命名空間(namespace),來保證其相對唯一性。分布式的ID生成,以Twitter Snowf...
閱讀 2192·2021-09-22 10:56
閱讀 1492·2021-09-07 10:11
閱讀 1813·2019-08-30 15:54
閱讀 2300·2019-08-30 15:44
閱讀 2319·2019-08-29 12:40
閱讀 3040·2019-08-28 18:25
閱讀 1751·2019-08-26 10:24
閱讀 3195·2019-08-23 18:39