最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Go實(shí)現(xiàn)分布式唯一ID的生成之雪花算法

 更新時(shí)間:2022年05月06日 09:17:34   作者:Blockchain210  
本文主要介紹了Go實(shí)現(xiàn)分布式唯一ID的生成之雪花算法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

分布式唯一ID的生成

背景:

在分布式架構(gòu)下,唯一序列號(hào)生成是我們?cè)谠O(shè)計(jì)一個(gè)尤其是數(shù)據(jù)庫(kù)使用分庫(kù)分表的時(shí)候會(huì)常見的一個(gè)問題

特性:

全局唯一,這是基本要求,不能出現(xiàn)重復(fù)數(shù)字類型,趨勢(shì)遞增,后面的ID必須比前面的大長(zhǎng)度短,能夠提高查詢效率,這也是從MySQL數(shù)據(jù)庫(kù)規(guī)范出發(fā)的,尤其是ID作為主鍵時(shí)**信息安全,**如果ID連續(xù)生成,勢(shì)必會(huì)泄露業(yè)務(wù)信息,所以需要無規(guī)則不規(guī)則高可用低延時(shí),ID生成快,能夠扛住高并發(fā),延時(shí)足夠低不至于成為業(yè)務(wù)瓶頸.

雪花算法:

? snowflake是推特開源的分布式ID生成算法

結(jié)果: long 型的ID號(hào)(64位的ID號(hào))

核心思想(生成的ID號(hào)是64位那么就對(duì)64位進(jìn)行劃分賦予特別的含義):

在這里插入圖片描述

41bit-時(shí)間戳決定了該算法生成ID號(hào)的可用年限.

10bit-工作機(jī)器編號(hào)決定了該分布式系統(tǒng)的擴(kuò)容性即機(jī)器數(shù)量.

12bit-序列號(hào)決定了每毫秒單機(jī)系統(tǒng)可以生成的序列號(hào)

拓展:什么是時(shí)間戳?

北京時(shí)間1970年01月01日08時(shí)00分00秒到此時(shí)時(shí)刻的總秒數(shù)

優(yōu)勢(shì):

//實(shí)現(xiàn)方法:
package main


import (
	"errors"
	"fmt"
	"sync"
	"time"
)

/*
	雪花算法(snowFlake)的具體實(shí)現(xiàn)方案:
 */

type SnowFlake struct{
	mu sync.Mutex
	//雪花算法開啟時(shí)的起始時(shí)間戳
	twepoch int64

	//每一部分占用的位數(shù)
	workerIdBits     int64 //每個(gè)數(shù)據(jù)中心的工作機(jī)器的編號(hào)位數(shù)
	datacenterIdBits int64 //數(shù)據(jù)中心的編號(hào)位數(shù)
	sequenceBits     int64 //每個(gè)工作機(jī)器每毫秒遞增的位數(shù)

	//每一部分最大的數(shù)值
	maxWorkerId int64
	maxDatacenterId int64
	maxSequence int64

	//每一部分向左移動(dòng)的位數(shù)
	workerIdShift int64
	datacenterIdShift int64
	timestampShift int64

	//當(dāng)前數(shù)據(jù)中心ID號(hào)
	datacenterId int64
	//當(dāng)前機(jī)器的ID號(hào)
	workerId int64
	//序列號(hào)
	sequence int64
	//上一次生成ID號(hào)前41位的毫秒時(shí)間戳
	lastTimestamp int64
}

/*
	獲取毫秒的時(shí)間戳
 */
func (s *SnowFlake)timeGen()int64{
	return time.Now().UnixMilli()
}
/*
	獲取比lastTimestamp大的當(dāng)前毫秒時(shí)間戳
 */
func (s *SnowFlake)tilNextMills()int64{
	timeStampMill:=s.timeGen()
	for timeStampMill<=s.lastTimestamp{
		timeStampMill=s.timeGen()
	}
	return timeStampMill
}
func (s *SnowFlake)NextId()(int64,error){
	s.mu.Lock()
	defer s.mu.Unlock()
	nowTimestamp:=s.timeGen()//獲取當(dāng)前的毫秒級(jí)別的時(shí)間戳
	if nowTimestamp<s.lastTimestamp{
		//系統(tǒng)時(shí)鐘倒退,倒退了s.lastTimestamp-nowTimestamp
		return -1,errors.New(fmt.Sprintf("clock moved backwards, Refusing to generate id for %d milliseconds",s.lastTimestamp-nowTimestamp))
	}
	if nowTimestamp==s.lastTimestamp{
		s.sequence=(s.sequence+1)&s.maxSequence
		if s.sequence==0{
			 //tilNextMills中有一個(gè)循環(huán)等候當(dāng)前毫秒時(shí)間戳到達(dá)lastTimestamp的下一個(gè)毫秒時(shí)間戳
			nowTimestamp=s.tilNextMills()
		}
	}else{
		s.sequence=0
	}
	s.lastTimestamp=nowTimestamp
	return (nowTimestamp-s.twepoch)<<s.timestampShift| //時(shí)間戳差值部分
		s.datacenterId<<s.datacenterIdShift| //數(shù)據(jù)中心部分
		s.workerId<<s.workerIdShift| //工作機(jī)器編號(hào)部分
		s.sequence, //序列號(hào)部分
		nil
}

func NewSnowFlake(workerId int64,datacenterId int64)(*SnowFlake,error){
	mySnow:=new(SnowFlake)
	mySnow.twepoch=time.Now().Unix() //返回當(dāng)前時(shí)間的時(shí)間戳(時(shí)間戳是指北京時(shí)間1970年01月01日8時(shí)0分0秒到此時(shí)時(shí)刻的總秒數(shù))
	if workerId<0||datacenterId<0{
		return nil,errors.New("workerId or datacenterId must not lower than 0 ")
	}
	/*
		標(biāo)準(zhǔn)的雪花算法
	 */
	mySnow.workerIdBits =5
	mySnow.datacenterIdBits=5
	mySnow.sequenceBits=12

	mySnow.maxWorkerId=-1^(-1<<mySnow.workerIdBits)         //64位末尾workerIdBits位均設(shè)為1,其余設(shè)為0
	mySnow.maxDatacenterId=-1^(-1<<mySnow.datacenterIdBits) //64位末尾datacenterIdBits位均設(shè)為1,其余設(shè)為0
	mySnow.maxSequence=-1^(-1<<mySnow.sequenceBits)  //64位末尾sequenceBits位均設(shè)為1,其余設(shè)為0

	if workerId>=mySnow.maxWorkerId||datacenterId>=mySnow.maxDatacenterId{
		return nil,errors.New("workerId or datacenterId must not higher than max value ")
	}
	mySnow.workerIdShift=mySnow.sequenceBits
	mySnow.datacenterIdShift=mySnow.sequenceBits+mySnow.workerIdBits
	mySnow.timestampShift=mySnow.sequenceBits+mySnow.workerIdBits+mySnow.datacenterIdBits

	mySnow.lastTimestamp=-1
	mySnow.workerId=workerId
	mySnow.datacenterId=datacenterId

	return mySnow,nil
}



func main(){
	//模擬實(shí)驗(yàn)是生成并發(fā)400W個(gè)ID,所需要的時(shí)間
	mySnow,_:=NewSnowFlake(0,0)//生成雪花算法
	group:=sync.WaitGroup{}
	startTime:=time.Now()
	generateId:=func (s SnowFlake,requestNumber int){
		for i:=0;i<requestNumber;i++{
			s.NextId()
			group.Done()
		}
	}
	group.Add(4000000)
	//生成并發(fā)的數(shù)為4000000
	currentThreadNum:=400
	for i:=0;i<currentThreadNum;i++{
		generateId(*mySnow,10000)
	}
	group.Wait()
	fmt.Printf("time: %v\n",time.Now().Sub(startTime))
}

在這里插入圖片描述

以上分析生成400WID號(hào)只需要803.1006ms(所以單機(jī)上可以每秒生成的ID數(shù)在400W以上)

優(yōu)點(diǎn):

毫秒數(shù)在高位,自增序列在低位,整個(gè)ID都是趨勢(shì)遞增不依賴數(shù)據(jù)庫(kù)等第三方系統(tǒng),以服務(wù)的方式部署,穩(wěn)定性更高,生成的ID性能也是非常高的可以根據(jù)自身業(yè)務(wù)特性分配bit位,非常靈活

缺陷:

1. 依賴機(jī)器時(shí)鐘,如果**機(jī)器時(shí)鐘回?fù)?*,會(huì)導(dǎo)致重復(fù)ID生成.
2. 在單機(jī)上是遞增的,但是由于設(shè)計(jì)到分布式環(huán)境下,每臺(tái)機(jī)器上的時(shí)鐘不可能完全同步,有時(shí)候會(huì)出現(xiàn)不是全局遞增的情況.

如何解決單機(jī)系統(tǒng)中時(shí)鐘回?fù)軉栴}:

? 可以分為兩種情況:

1. 如果**時(shí)間回?fù)軙r(shí)間較短,比如配置5ms以內(nèi)**,那么可以直接等候一定的時(shí)間,讓機(jī)器時(shí)間追上來
2. 如果**時(shí)間回?fù)軙r(shí)間較長(zhǎng)**,我們不能接收這么長(zhǎng)的阻塞等候,那么就有兩個(gè)策略,直接拒絕,拋出異常;或者通過RD時(shí)鐘回滾

布式環(huán)境下,每臺(tái)機(jī)器上的時(shí)鐘不可能完全同步,有時(shí)候會(huì)出現(xiàn)不是全局遞增的情況.

如何解決單機(jī)系統(tǒng)中時(shí)鐘回?fù)軉栴}:

? 可以分為兩種情況:

1. 如果**時(shí)間回?fù)軙r(shí)間較短,比如配置5ms以內(nèi)**,那么可以直接等候一定的時(shí)間,讓機(jī)器時(shí)間追上來
2. 如果**時(shí)間回?fù)軙r(shí)間較長(zhǎng)**,我們不能接收這么長(zhǎng)的阻塞等候,那么就有兩個(gè)策略,直接拒絕,拋出異常;或者通過RD時(shí)鐘回滾

參考博客高并發(fā)情況下,雪花ID一秒400W個(gè),以及分布式ID算法(詳析)

到此這篇關(guān)于Go實(shí)現(xiàn)分布式唯一ID的生成之雪花算法的文章就介紹到這了,更多相關(guān)Go分布式唯一ID 內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • go語(yǔ)言中的map如何解決散列性能下降

    go語(yǔ)言中的map如何解決散列性能下降

    近期對(duì)go語(yǔ)言的map進(jìn)行深入了解和探究,其中關(guān)于map解決大量沖突的擴(kuò)容操作設(shè)計(jì)的十分巧妙,所以筆者特地整理了這篇文章來探討一下go語(yǔ)言中map如何解決散列性能下降,文中有相關(guān)的代碼示例供大家參考,需要的朋友可以參考下
    2024-03-03
  • 詳解Go語(yǔ)言中make和new的區(qū)別

    詳解Go語(yǔ)言中make和new的區(qū)別

    Go語(yǔ)言中,有兩個(gè)比較雷同的內(nèi)置函數(shù),分別是new和make方法,那他們有什么區(qū)別呢?本文將通過一些示例為大家詳細(xì)介紹一下,感興趣的可以了解一下
    2023-02-02
  • Go?實(shí)戰(zhàn)單隊(duì)列到優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn)圖文示例

    Go?實(shí)戰(zhàn)單隊(duì)列到優(yōu)先級(jí)隊(duì)列實(shí)現(xiàn)圖文示例

    這篇文章主要為大家介紹了Go?實(shí)戰(zhàn)單隊(duì)列到優(yōu)先級(jí)隊(duì)列圖文示例實(shí)現(xiàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • Golang中自定義json序列化時(shí)間格式的示例代碼

    Golang中自定義json序列化時(shí)間格式的示例代碼

    Go語(yǔ)言作為一個(gè)由Google開發(fā),號(hào)稱互聯(lián)網(wǎng)的C語(yǔ)言的語(yǔ)言,自然也對(duì)JSON格式支持很好,下面這篇文章主要介紹了關(guān)于Golang中自定義json序列化時(shí)間格式的相關(guān)內(nèi)容,下面話不多說了,來一起看看詳細(xì)的介紹吧
    2024-08-08
  • Go方法簡(jiǎn)單性和高效性的充分體現(xiàn)詳解

    Go方法簡(jiǎn)單性和高效性的充分體現(xiàn)詳解

    本文深入探討了Go語(yǔ)言中方法的各個(gè)方面,包括基礎(chǔ)概念、定義與聲明、特性、實(shí)戰(zhàn)應(yīng)用以及性能考量,文章充滿技術(shù)深度,通過實(shí)例和代碼演示,力圖幫助讀者全面理解Go方法的設(shè)計(jì)哲學(xué)和最佳實(shí)踐
    2023-10-10
  • Go語(yǔ)言時(shí)間管理利器之深入解析time模塊的實(shí)戰(zhàn)技巧

    Go語(yǔ)言時(shí)間管理利器之深入解析time模塊的實(shí)戰(zhàn)技巧

    本文深入解析了Go語(yǔ)言標(biāo)準(zhǔn)庫(kù)中的time模塊,揭示了其高效用法和實(shí)用技巧,通過學(xué)習(xí)time模塊的三大核心類型(Time、Duration、Timer/Ticker)以及高頻使用場(chǎng)景,開發(fā)者可以更好地處理時(shí)間相關(guān)的任務(wù),感興趣的朋友一起看看吧
    2025-03-03
  • Golang常用的幾種密碼加密方式分享

    Golang常用的幾種密碼加密方式分享

    這篇文章給大家介紹了Golang常用的幾種密碼加密方式,加密有兩種方式,一種是直接加密,一種是鹽值加密,直接加密指的是將原始密碼直接進(jìn)行加密,鹽值加密則是在進(jìn)行密碼加密之前,文中有詳細(xì)的代碼示例,需要的朋友可以參考下
    2023-08-08
  • 理解Go流程控制與快樂路徑原則

    理解Go流程控制與快樂路徑原則

    這篇文章主要為大家介紹了Go流程控制與快樂路徑原則的原理解析,
    有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • golang通過context控制并發(fā)的應(yīng)用場(chǎng)景實(shí)現(xiàn)

    golang通過context控制并發(fā)的應(yīng)用場(chǎng)景實(shí)現(xiàn)

    這篇文章主要介紹了golang通過context控制并發(fā)的應(yīng)用場(chǎng)景實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • Golang的循環(huán)語(yǔ)句和循環(huán)控制語(yǔ)句詳解

    Golang的循環(huán)語(yǔ)句和循環(huán)控制語(yǔ)句詳解

    循環(huán)語(yǔ)句為了簡(jiǎn)化程序中有規(guī)律的重復(fù)性操作,需要用到循環(huán)語(yǔ)句,和其他大多數(shù)編程語(yǔ)言一樣,GO的循環(huán)語(yǔ)句有for循環(huán),不同的是沒有while循環(huán),而循環(huán)控制語(yǔ)句可以改變循環(huán)語(yǔ)句的執(zhí)行過程,下面給大家介紹下go循環(huán)語(yǔ)句和循環(huán)控制語(yǔ)句的相關(guān)知識(shí),一起看看吧
    2021-11-11

最新評(píng)論

象山县| 伊金霍洛旗| 郑州市| 诸城市| 瑞丽市| 定安县| 蕉岭县| 延安市| 莱芜市| 昌平区| 三亚市| 青河县| 龙州县| 兰坪| 兴和县| 义马市| 新余市| 会宁县| 昆山市| 英吉沙县| 上栗县| 武隆县| 鹤岗市| 建水县| 象山县| 沙雅县| 都安| 玛多县| 临潭县| 台湾省| 北票市| 永安市| 马山县| 车致| 黎城县| 永寿县| 阳泉市| 三明市| 临泉县| 台州市| 景德镇市|