黄视频网站在线免费观看-黄视频网站在线看-黄视频网站在线观看-黄视频网站免费看-黄视频网站免费观看-黄视频网站免费

千鋒教育-做有情懷、有良心、有品質(zhì)的職業(yè)教育機(jī)構(gòu)

手機(jī)站
千鋒教育

千鋒學(xué)習(xí)站 | 隨時隨地免費(fèi)學(xué)

千鋒教育

掃一掃進(jìn)入千鋒手機(jī)站

領(lǐng)取全套視頻
千鋒教育

關(guān)注千鋒學(xué)習(xí)站小程序
隨時隨地免費(fèi)學(xué)習(xí)課程

當(dāng)前位置:首頁  >  技術(shù)干貨  > 分布式系統(tǒng)里用戶ID生成有什么好的方法和規(guī)則能滿足“少數(shù)、盡量短、不能直接看出規(guī)則”這幾個條件?

分布式系統(tǒng)里用戶ID生成有什么好的方法和規(guī)則能滿足“少數(shù)、盡量短、不能直接看出規(guī)則”這幾個條件?

來源:千鋒教育
發(fā)布人:xqq
時間: 2023-10-12 21:06:57 1697116017

1、基于UUID

在Java的世界里,想要得到一個具有少數(shù)性的ID,首先被想到可能就是UUID,畢竟它有著全球少數(shù)的特性。那么UUID可以做分布式ID嗎?答案是可以的,但是并不是十分推薦。

public static void main(String[] args) {        String uuid = UUID.randomUUID().toString().replaceAll("-","");       System.out.println(uuid); }

UUID的生成簡單到只有一行代碼,輸出結(jié)果?c2b8c2b9e46c47e3b30dca3b0d447718,但UUID卻并不適用于實(shí)際的業(yè)務(wù)需求。像用作訂單號UUID這樣的字符串沒有絲毫的意義,看不出和訂單相關(guān)的有用信息;而對于數(shù)據(jù)庫來說用作業(yè)務(wù)主鍵ID,它不僅是太長還是字符串,存儲性能差查詢也很耗時,所以不推薦用作分布式ID。

優(yōu)點(diǎn):生成足夠簡單,本地生成無網(wǎng)絡(luò)消耗,具有少數(shù)性。

缺點(diǎn):

無序的字符串,不具備趨勢自增特性;沒有具體的業(yè)務(wù)含義;長度過長16 字節(jié)128位,36位長度的字符串,存儲以及查詢對MySQL的性能消耗較大,MySQL官方明確建議主鍵要盡量越短越好,作為數(shù)據(jù)庫主鍵?UUID?的無序性會導(dǎo)致數(shù)據(jù)位置頻繁變動,嚴(yán)重影響性能。

2、基于數(shù)據(jù)庫自增ID

基于數(shù)據(jù)庫的auto_increment自增ID完全可以充當(dāng)分布式ID,具體實(shí)現(xiàn):需要一個單獨(dú)的MySQL實(shí)例用來生成ID,建表結(jié)構(gòu)如下:

當(dāng)我們需要一個ID的時候,向表中插入一條記錄返回主鍵ID,但這種方式有一個比較致命的缺點(diǎn),訪問量激增時MySQL本身就是系統(tǒng)的瓶頸,用它來實(shí)現(xiàn)分布式服務(wù)風(fēng)險比較大。

優(yōu)點(diǎn):實(shí)現(xiàn)簡單,ID單調(diào)自增,數(shù)值類型查詢速度快

缺點(diǎn):DB單點(diǎn)存在宕機(jī)風(fēng)險,無法扛住高并發(fā)場景

3、基于數(shù)據(jù)庫集群模式

前邊說了單點(diǎn)數(shù)據(jù)庫方式不可取,那對上邊的方式做一些高可用優(yōu)化,換成主從模式集群。害怕一個主節(jié)點(diǎn)掛掉沒法用,那就做雙主模式集群,也就是兩個Mysql實(shí)例都能單獨(dú)的生產(chǎn)自增ID。那這樣還會有個問題,兩個MySQL實(shí)例的自增ID都從1開始,會生成重復(fù)的ID怎么辦?

解決方案:設(shè)置起始值和自增步長。

MySQL_1 配置:

MySQL_2 配置:

這樣兩個MySQL實(shí)例的自增ID分別就是:

1、3、5、7、92、4、6、8、10

那如果集群后的性能還是扛不住高并發(fā)咋辦?就要進(jìn)行MySQL擴(kuò)容增加節(jié)點(diǎn),這是一個比較麻煩的事。

從上圖可以看出,水平擴(kuò)展的數(shù)據(jù)庫集群,有利于解決數(shù)據(jù)庫單點(diǎn)壓力的問題,同時為了ID生成特性,將自增步長按照機(jī)器數(shù)量來設(shè)置。增加第三臺MySQL實(shí)例需要人工修改一、二兩臺MySQL實(shí)例的起始值和步長,把第三臺機(jī)器的ID起始生成位置設(shè)定在比現(xiàn)有最大自增ID的位置遠(yuǎn)一些,但必須在一、二兩臺MySQL實(shí)例ID還沒有增長到第三臺MySQL實(shí)例的起始ID值的時候,否則自增ID就要出現(xiàn)重復(fù)了,必要時可能還需要停機(jī)修改。

優(yōu)點(diǎn):解決DB單點(diǎn)問題。

缺點(diǎn):不利于后續(xù)擴(kuò)容,而且實(shí)際上單個數(shù)據(jù)庫自身壓力還是大,依舊無法滿足高并發(fā)場景。

4、基于數(shù)據(jù)庫的號段模式

號段模式是當(dāng)下分布式ID生成器的主流實(shí)現(xiàn)方式之一,號段模式可以理解為從數(shù)據(jù)庫批量的獲取自增ID,每次從數(shù)據(jù)庫取出一個號段范圍,例如 (1,1000] 代表1000個ID,具體的業(yè)務(wù)服務(wù)將本號段,生成1~1000的自增ID并加載到內(nèi)存。表結(jié)構(gòu)如下:

CREATE TABLE id_generator (  id int(10) NOT NULL,  max_id bigint(20) NOT NULL COMMENT '當(dāng)前最大id',  step int(20) NOT NULL COMMENT '號段的布長',  biz_type    int(20) NOT NULL COMMENT '業(yè)務(wù)類型',  version int(20) NOT NULL COMMENT '版本號',  PRIMARY KEY (id)) 
biz_type?:代表不同業(yè)務(wù)類型max_id?:當(dāng)前最大的可用idstep?:代表號段的長度version?:是一個樂觀鎖,每次都更新version,保證并發(fā)時數(shù)據(jù)的正確性

等這批號段ID用完,再次向數(shù)據(jù)庫申請新號段,對max_id字段做一次update操作,update max_id= max_id + step,update成功則說明新號段獲取成功,新的號段范圍是(max_id ,max_id +step]。

update id_generator set max_id = #{max_id+step}, version = version + 1 where version = # {version} and biz_type = XXX

由于多業(yè)務(wù)端可能同時操作,所以采用版本號version樂觀鎖方式更新,這種分布式ID生成方式不強(qiáng)依賴于數(shù)據(jù)庫,不會頻繁的訪問數(shù)據(jù)庫,對數(shù)據(jù)庫的壓力小很多。

5、基于Redis模式

Redis也同樣可以實(shí)現(xiàn),原理就是利用redis的?incr命令實(shí)現(xiàn)ID的原子性自增:

用redis實(shí)現(xiàn)需要注意一點(diǎn),要考慮到redis持久化的問題。redis有兩種持久化方式RDB和AOF:

RDB會定時打一個快照進(jìn)行持久化,假如連續(xù)自增但redis沒及時持久化,而這會Redis掛掉了,重啟Redis后會出現(xiàn)ID重復(fù)的情況。AOF會對每條寫命令進(jìn)行持久化,即使Redis掛掉了也不會出現(xiàn)ID重復(fù)的情況,但由于incr命令的特殊性,會導(dǎo)致Redis重啟恢復(fù)的數(shù)據(jù)時間過長。

6、基于雪花算法(Snowflake)模式

雪花算法(Snowflake)是twitter公司內(nèi)部分布式項(xiàng)目采用的ID生成算法,開源后廣受國內(nèi)大廠的好評,在該算法影響下各大公司相繼開發(fā)出各具特色的分布式生成器。

Snowflake生成的是Long類型的ID,一個Long類型占8個字節(jié),每個字節(jié)占8比特,也就是說一個Long類型占64個比特。Snowflake ID組成結(jié)構(gòu):正數(shù)位(占1比特)+?時間戳(占41比特)+?機(jī)器ID(占5比特)+?數(shù)據(jù)中心(占5比特)+?自增值(占12比特),總共64比特組成的一個Long類型。

名列前茅個bit位(1bit):Java中l(wèi)ong的較高位是符號位代表正負(fù),正數(shù)是0,負(fù)數(shù)是1,一般生成ID都為正數(shù),所以默認(rèn)為0。時間戳部分(41bit):毫秒級的時間,不建議存當(dāng)前時間戳,而是用(當(dāng)前時間戳 – 固定開始時間戳)的差值,可以使產(chǎn)生的ID從更小的值開始;41位的時間戳可以使用69年,(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年工作機(jī)器id(10bit):也被叫做workId,這個可以靈活配置,機(jī)房或者機(jī)器號組合都可以。序列號部分(12bit):自增值支持同一毫秒內(nèi)同一個節(jié)點(diǎn)可以生成4096個ID

根據(jù)這個算法的邏輯,只需要將這個算法用Java語言實(shí)現(xiàn)出來,封裝為一個工具方法,那么各個業(yè)務(wù)應(yīng)用可以直接使用該工具方法來獲取分布式ID,只需保證每個業(yè)務(wù)應(yīng)用有自己的工作機(jī)器id即可,而不需要單獨(dú)去搭建一個獲取分布式ID的應(yīng)用。Java版本的****Snowflake算法實(shí)現(xiàn):

public class SnowFlakeShortUrl {    private final static long START_TIMESTAMP = 1480166465631L;    private final static long SEQUENCE_BIT = 12;   //序列號占用的位數(shù)    private final static long MACHINE_BIT = 5;     //機(jī)器標(biāo)識占用的位數(shù)    private final static long DATA_CENTER_BIT = 5; //數(shù)據(jù)中心占用的位數(shù)    private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);    private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);    private final static long MAX_DATA_CENTER_NUM = -1L ^ (-1L << DATA_CENTER_BIT);    private final static long MACHINE_LEFT = SEQUENCE_BIT;    private final static long DATA_CENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;    private final static long TIMESTAMP_LEFT = DATA_CENTER_LEFT + DATA_CENTER_BIT;    private long dataCenterId;  //數(shù)據(jù)中心    private long machineId;     //機(jī)器標(biāo)識    private long sequence = 0L; //序列號    private long lastTimeStamp = -1L;  //上一次時間戳    private long getNextMill() {        long mill = getNewTimeStamp();        while (mill <= lastTimeStamp) {            mill = getNewTimeStamp();        }        return mill;}    private long getNewTimeStamp() {        return System.currentTimeMillis();    }    public SnowFlakeShortUrl(long dataCenterId, long machineId) {        if (dataCenterId > MAX_DATA_CENTER_NUM || dataCenterId < 0) {            throw new IllegalArgumentException("DtaCenterId can't be greater than MAX_DATA_CENTER_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;    }  public synchronized long nextId() {        long currTimeStamp = getNewTimeStamp();        if (currTimeStamp < lastTimeStamp) {            throw new RuntimeException("Clock moved backwards.  Refusing to generate id");        }        if (currTimeStamp == lastTimeStamp) {            //相同毫秒內(nèi),序列號自增            sequence = (sequence + 1) & MAX_SEQUENCE;            //同一毫秒的序列數(shù)已經(jīng)達(dá)到最大            if (sequence == 0L) {                currTimeStamp = getNextMill();            }        } else {            //不同毫秒內(nèi),序列號置為0            sequence = 0L;        }        lastTimeStamp = currTimeStamp;        return (currTimeStamp - START_TIMESTAMP) << TIMESTAMP_LEFT //時間戳部分                | dataCenterId << DATA_CENTER_LEFT       //數(shù)據(jù)中心部分                | machineId << MACHINE_LEFT             //機(jī)器標(biāo)識部分                | sequence;                             //序列號部分    }    public static void main(String[] args) {        SnowFlakeShortUrl snowFlake = new SnowFlakeShortUrl(2, 3);        for (int i = 0; i < (1 << 4); i++) {            System.out.println(snowFlake.nextId());        }    }}

7、百度(uid-generator)

uid-generator是由百度技術(shù)部開發(fā),項(xiàng)目GitHub地址為https://github.com/baidu/uid-generator。uid-generator是基于Snowflake算法實(shí)現(xiàn)的,與原始的snowflake算法不同在于,uid-generator支持自定義時間戳、工作機(jī)器ID和?序列號?等各部分的位數(shù),而且uid-generator中采用用戶自定義workId的生成策略。

uid-generator需要與數(shù)據(jù)庫配合使用,需要新增一個WORKER_NODE表。當(dāng)應(yīng)用啟動時會向數(shù)據(jù)庫表中去插入一條數(shù)據(jù),插入成功后返回的自增ID就是該機(jī)器的workId數(shù)據(jù)由host,port組成。對于****uid-generator?ID組成結(jié)構(gòu):workId,占用了22個bit位,時間占用了28個bit位,序列化占用了13個bit位,需要注意的是,和原始的snowflake不太一樣,時間的單位是秒,而不是毫秒,workId也不一樣,而且同一應(yīng)用每次重啟就會消費(fèi)一個workId。

延伸閱讀1:分布式ID的特點(diǎn)

少數(shù)性:生成的ID全局少數(shù),在特定范圍內(nèi)沖突概率極小。有序性:生成的ID按某種規(guī)則有序,便于數(shù)據(jù)庫插入及排序。可用性:可保證高并發(fā)下的可用性,確保任何時候都能正確的生成ID。自主性:分布式環(huán)境下不依賴中心認(rèn)證即可自行生成ID。安全性:不暴露系統(tǒng)和業(yè)務(wù)的信息,如:訂單數(shù),用戶數(shù)等。
聲明:本站稿件版權(quán)均屬千鋒教育所有,未經(jīng)許可不得擅自轉(zhuǎn)載。
10年以上業(yè)內(nèi)強(qiáng)師集結(jié),手把手帶你蛻變精英
請您保持通訊暢通,專屬學(xué)習(xí)老師24小時內(nèi)將與您1V1溝通
免費(fèi)領(lǐng)取
今日已有369人領(lǐng)取成功
劉同學(xué) 138****2860 剛剛成功領(lǐng)取
王同學(xué) 131****2015 剛剛成功領(lǐng)取
張同學(xué) 133****4652 剛剛成功領(lǐng)取
李同學(xué) 135****8607 剛剛成功領(lǐng)取
楊同學(xué) 132****5667 剛剛成功領(lǐng)取
岳同學(xué) 134****6652 剛剛成功領(lǐng)取
梁同學(xué) 157****2950 剛剛成功領(lǐng)取
劉同學(xué) 189****1015 剛剛成功領(lǐng)取
張同學(xué) 155****4678 剛剛成功領(lǐng)取
鄒同學(xué) 139****2907 剛剛成功領(lǐng)取
董同學(xué) 138****2867 剛剛成功領(lǐng)取
周同學(xué) 136****3602 剛剛成功領(lǐng)取
相關(guān)推薦HOT
為什么Oracle收購MySQL后仍保證其開源免費(fèi)?

一、為什么Oracle收購MySQL后仍保證其開源免費(fèi)MySQL在收購前一直使用GPL許可分發(fā),而GPL許可是不可撤銷的,這意味著至少被收購之前的最后一個Re...詳情>>

2023-10-12 22:52:49
為什么MySQL對SQL標(biāo)準(zhǔn)中很多基本用法都不支持?

一、為什么MySQL對SQL標(biāo)準(zhǔn)中很多基本用法都不支持因?yàn)楫?dāng)年,在微軟.net技術(shù)棧下開發(fā)應(yīng)用,用的就是sql server數(shù)據(jù)庫。在特性方面,不僅緊跟sql...詳情>>

2023-10-12 22:49:20
數(shù)據(jù)庫與Microsoft Excel有什么區(qū)別?

一、數(shù)據(jù)庫與Microsoft Excel的區(qū)別1、結(jié)構(gòu)不同excel即是電子數(shù)據(jù)表,顯示由一系列行與列構(gòu)成的網(wǎng)格。。其中的單元格可以用于存放數(shù)值、計算式...詳情>>

2023-10-12 22:47:09
web頁面安全是什么?

一、web頁面安全是什么Web頁面安全指的是保護(hù)Web應(yīng)用程序和用戶數(shù)據(jù)免受惡意攻擊和不當(dāng)使用的一系列措施。它旨在確保Web頁面的機(jī)密性、完整性和...詳情>>

2023-10-12 22:35:44
為什么分布式數(shù)據(jù)庫這么喜歡用kv store?

一、為什么分布式數(shù)據(jù)庫這么喜歡用kv store雖然不論是單機(jī)數(shù)據(jù)庫(MySQL、PostgreSQL等等),還是題主說到的分布式數(shù)據(jù)庫(CockroachDB、TiDB)...詳情>>

2023-10-12 22:21:18
快速通道
99久久精品国产片| 亚洲精品中文一区不卡| 欧美1卡一卡二卡三新区| 日韩在线观看视频黄| 一级女性全黄久久生活片| 九九久久99综合一区二区| 国产视频一区二区在线播放| 毛片成人永久免费视频| 欧美大片a一级毛片视频| 美女被草网站| 精品久久久久久免费影院| 免费一级生活片| 精品视频在线看| 日本特黄特黄aaaaa大片| 精品国产一区二区三区国产馆| 国产韩国精品一区二区三区| 国产欧美精品| 精品视频在线观看一区二区| 黄色短视频网站| 国产成人女人在线视频观看 | 国产不卡福利| 精品国产一区二区三区精东影业 | 国产91精品系列在线观看| 麻豆网站在线看| 91麻豆精品国产高清在线| 韩国三级视频网站| 成人影院一区二区三区| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 中文字幕97| 日韩一级黄色| 可以在线看黄的网站| 免费国产在线视频| 一级毛片视频免费| 国产不卡在线观看视频| 精品视频免费看| 精品国产亚洲一区二区三区| 成人免费观看视频| 欧美激情伊人| 欧美大片毛片aaa免费看| 欧美18性精品| 国产网站免费在线观看| 国产成人精品综合在线| 99久久精品国产片| 国产不卡在线观看视频| 香蕉视频久久| 精品在线视频播放| 日本特黄特色aaa大片免费| 999精品视频在线| 成人高清护士在线播放| 999久久久免费精品国产牛牛| 国产视频网站在线观看| 欧美α片无限看在线观看免费| 你懂的在线观看视频| 999精品在线| 国产伦久视频免费观看视频| 毛片高清| 国产成人精品在线| 国产视频久久久久| 欧美一级视| 久久国产影视免费精品| 国产不卡精品一区二区三区| 精品国产三级a| 麻豆网站在线看| 国产成人女人在线视频观看 | 91麻豆tv| 国产不卡在线播放| 国产福利免费观看| 国产一区二区精品久| 九九精品在线播放| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 黄色免费三级| 日日夜夜婷婷| 国产欧美精品| 免费国产在线观看不卡| 精品视频一区二区三区| 黄色免费三级| 天天做日日爱| 久草免费资源| 黄视频网站免费观看| 99久久视频| 成人影院一区二区三区| 毛片高清| 91麻豆精品国产自产在线 | 国产成人啪精品| 日韩免费片| 欧美1区2区3区| 国产a毛片| 91麻豆国产| 国产一区免费观看| 国产亚洲免费观看| 黄色免费三级| 91麻豆国产福利精品| 午夜激情视频在线播放| 国产麻豆精品高清在线播放| 色综合久久手机在线| 欧美一级视频高清片| 高清一级做a爱过程不卡视频| 国产原创视频在线| 亚洲第一页乱| 国产美女在线观看| 国产成人欧美一区二区三区的| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 国产亚洲精品成人a在线| 国产网站免费| 精品国产一区二区三区久久久蜜臀 | 午夜在线影院| 午夜在线亚洲| 午夜激情视频在线播放| 国产成人女人在线视频观看| 久久国产一久久高清| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 成人免费网站久久久| 午夜欧美成人久久久久久| 国产不卡在线看| 国产91素人搭讪系列天堂| 青青久久国产成人免费网站| 999精品视频在线| 午夜在线影院| 欧美大片aaaa一级毛片| 久久精品店| 国产91丝袜高跟系列| 精品视频在线观看一区二区| 精品视频在线看 | 精品国产一区二区三区免费| 欧美夜夜骑 青草视频在线观看完整版 久久精品99无色码中文字幕 欧美日韩一区二区在线观看视频 欧美中文字幕在线视频 www.99精品 香蕉视频久久 | 成人影院一区二区三区| 天天做人人爱夜夜爽2020毛片| 中文字幕一区二区三区精彩视频| 久久99这里只有精品国产| 精品视频在线看| 尤物视频网站在线观看| 色综合久久天天综合观看| 四虎影视久久久| 久久成人性色生活片| 欧美国产日韩精品| 精品在线观看一区| 精品视频在线观看免费| 亚洲 欧美 成人日韩| 韩国三级视频网站| 韩国三级一区| 国产一区二区精品| 欧美激情一区二区三区在线| 国产伦精品一区二区三区无广告| 亚洲精品中文字幕久久久久久| 色综合久久久久综合体桃花网| 九九免费精品视频| 99色播| 麻豆网站在线看| 黄色免费三级| 国产极品精频在线观看| 亚洲精品影院一区二区| 麻豆系列 在线视频| 日日夜夜婷婷| 国产精品1024在线永久免费| 九九精品影院| 国产综合91天堂亚洲国产| 国产一区二区精品| 四虎影视久久久| 99色视频| 99热精品在线| 一a一级片| 一级女性大黄生活片免费| 一级女性大黄生活片免费| 国产伦精品一区二区三区无广告 | 欧美激情伊人| 免费的黄视频| 999久久狠狠免费精品| 日本伦理黄色大片在线观看网站| 天天做人人爱夜夜爽2020毛片| 黄色短视屏| 午夜在线观看视频免费 成人| 成人影院久久久久久影院| 国产a视频| 日韩在线观看网站| 色综合久久手机在线| 久久精品免视看国产成人2021| 韩国三级视频网站| 欧美大片aaaa一级毛片| 色综合久久天天综合绕观看| 亚州视频一区二区| 国产美女在线一区二区三区| 色综合久久手机在线| 欧美一区二区三区性| 欧美1区2区3区| 中文字幕97| 青青久热| 久久精品欧美一区二区| 日本伦理网站| 久久99这里只有精品国产| 一级毛片视频在线观看| 一级片片| 国产原创视频在线| 国产麻豆精品| 久久99这里只有精品国产| 青青久久精品国产免费看| 亚欧视频在线| 高清一级毛片一本到免费观看| 欧美激情一区二区三区视频高清 | 国产一区二区精品尤物| 日韩女人做爰大片|