摘要:關(guān)于我為什么寫(xiě)這篇文章是因?yàn)榻裉煸谧鲇唵文K的時(shí)候看到之前的上描述的年月日用戶位企業(yè)位四位自增長(zhǎng)數(shù)。背景對(duì)于其定訂單的生成。個(gè)人的看法是主要是唯一,其他關(guān)于業(yè)務(wù)方面的不是太太重要。自增實(shí)現(xiàn)了用于將的值遞增,并返回結(jié)果。
關(guān)于我為什么寫(xiě)這篇文章是因?yàn)榻裉煸谧鲇唵文K的時(shí)候,看到之前的PRD上描述的年月日+用戶id2位+企業(yè)id位
+四位自增長(zhǎng)數(shù)。然后竟被我反駁的突然改成了精確時(shí)間+4位自增長(zhǎng)數(shù),于是我更失望了。
我們考慮一下,據(jù)我所常見(jiàn)的訂單基本都14-20位。(年月日時(shí)分秒和隨機(jī)數(shù))基本上就有14位了。雖然一般項(xiàng)目做不到淘寶雙11這種
支付峰值達(dá)到每秒10萬(wàn)筆訂單.但是我覺(jué)得至少事先可以考慮到,想必當(dāng)初淘寶或許也沒(méi)意識(shí)到以后發(fā)展
得這么好。
對(duì)于其定訂單的生成。我覺(jué)得要至少要符合以下這三種,全局唯一 ,
在復(fù)雜的分布式系統(tǒng)中,很多場(chǎng)景需要的都是全局唯一ID的場(chǎng)景,一般為了防止沖突可以考慮的有36
位的UUID,twitter的snowflake等。
但是可以思考這些問(wèn)題?
是不是應(yīng)該有一些其他意義的思考,比如說(shuō)訂單系統(tǒng)有買家的id(取固定幾位)
是否有商品的標(biāo)識(shí),方便熟悉業(yè)務(wù)的排查問(wèn)題或者查詢也通過(guò)不去系統(tǒng)查找可以有個(gè)初步的認(rèn)識(shí),但是業(yè)務(wù)量大的話感覺(jué)就可以排除這個(gè)人為的去辨識(shí)了。
個(gè)人的看法是主要是唯一,其他關(guān)于業(yè)務(wù)方面的不是太太重要。
查閱了相關(guān)資料,主要有以下這幾種
1.UUID
組成:當(dāng)前日期+時(shí)間+時(shí)鐘序列+機(jī)器識(shí)別號(hào)(Mac地址或其他)沒(méi)有mac網(wǎng)卡的話會(huì)有別的東西識(shí)別。
在分布式系統(tǒng)中,所有元素(WEB服務(wù)器)都不需要通過(guò)中央控制端來(lái)判斷數(shù)據(jù)唯一性。幾十年之內(nèi)可以達(dá)到全球唯一性。
snowflake的結(jié)構(gòu)如下(每部分用-分開(kāi)):
2.Mysql通過(guò)AUTO_INCREMENT實(shí)現(xiàn)、Oracle通過(guò)Sequence序列實(shí)現(xiàn)。
在數(shù)據(jù)庫(kù)集群環(huán)境下,不同數(shù)據(jù)庫(kù)節(jié)點(diǎn)可設(shè)置不同起步值、相同步長(zhǎng)來(lái)實(shí)現(xiàn)集群下生產(chǎn)全局唯一、遞增ID
3.Snowflake算法 雪花算法
41位時(shí)間戳+10位機(jī)器ID+12位序列號(hào)(自增) 轉(zhuǎn)化長(zhǎng)度為18位的長(zhǎng)整型。
Twitter為滿足美秒上萬(wàn)條消息的創(chuàng)建,且ID需要趨勢(shì)遞增,方便客戶端排序。
Snowflake雖然有同步鎖,但是比uuid效率高。
4.Redis自增ID
實(shí)現(xiàn)了incr(key)用于將key的值遞增1,并返回結(jié)果。如果key不存在,創(chuàng)建默認(rèn)并賦值為0。 具有原子性,保證在并發(fā)的時(shí)候。
但是我在這主要想說(shuō)的是雪花算法生成id
關(guān)于序列
0 - 0000000000 0000000000 0000000000 0000000000 0 - 00000 - 00000 - 000000000000
第一位為未使用,接下來(lái)的41位為毫秒級(jí)時(shí)間(41位的長(zhǎng)度可以使用69年),然后是5位datacenterId和5位workerId(10位的長(zhǎng)度最多支持部署1024個(gè)節(jié)點(diǎn)) ,最后12位是毫秒內(nèi)的計(jì)數(shù)(12位的計(jì)數(shù)順序號(hào)支持每個(gè)節(jié)點(diǎn)每毫秒產(chǎn)生4096個(gè)ID序號(hào))
一共加起來(lái)剛好64位,為一個(gè)Long型。(轉(zhuǎn)換成字符串長(zhǎng)度為18)
snowflake生成的ID整體上按照時(shí)間自增排序,并且整個(gè)分布式系統(tǒng)內(nèi)不會(huì)產(chǎn)生ID碰撞(由datacenter和workerId作區(qū)分),并且效率較高。據(jù)說(shuō):snowflake每秒能夠產(chǎn)生26萬(wàn)個(gè)ID。
以下是代碼
部分借鑒與網(wǎng)絡(luò)
100萬(wàn)個(gè)ID 耗時(shí)2秒
/** * Created by youze on 18-7-5 */ public class IdWorker { /** * 起始的時(shí)間戳 */ private final static long START_STMP = 1530795377086L; /** * 每一部分占用的位數(shù) */ /** * 序列號(hào)占用的位數(shù) */ private final static long SEQUENCE_BIT = 12; /** * 機(jī)器標(biāo)識(shí)占用的位數(shù) */ private final static long MACHINE_BIT = 5; /** * 數(shù)據(jù)中心占用的位數(shù) */ 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; /** * 數(shù)據(jù)中心 */ private long datacenterId; /** * 機(jī)器標(biāo)識(shí) */ private long machineId; /** * 序列號(hào) */ private long sequence = 0L; /** * 上一次時(shí)間戳 */ private long lastStmp = -1L; public IdWorker(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; } /** * 產(chǎn)生下一個(gè)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) { //相同毫秒內(nèi),序列號(hào)自增 sequence = (sequence + 1) & MAX_SEQUENCE; //同一毫秒的序列數(shù)已經(jīng)達(dá)到最大 if (sequence == 0L) { currStmp = getNextMill(); } } else { //不同毫秒內(nèi),序列號(hào)置為0 sequence = 0L; } lastStmp = currStmp; return ( //時(shí)間戳部分 currStmp - START_STMP) << TIMESTMP_LEFT //數(shù)據(jù)中心部分 | datacenterId << DATACENTER_LEFT //機(jī)器標(biāo)識(shí)部分 | machineId << MACHINE_LEFT //序列號(hào)部分 | 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) { IdWorker snowFlake = new IdWorker(2, 3); long start = System.currentTimeMillis(); for (int i = 0; i < 1000000; i++) { System.out.println(snowFlake.nextId()); } System.out.println(System.currentTimeMillis() - start); } }
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/71472.html
摘要:每個(gè)事物的范圍限定在單個(gè)聚合內(nèi)。當(dāng)然,記住僅僅因?yàn)槭莾蓚€(gè)表的關(guān)系設(shè)計(jì)不易任何方式表明他們是兩個(gè)聚合。一個(gè)捕獲這個(gè)事件,并在每個(gè)指定的聚合上執(zhí)行命令。盡管如此,不得不訴諸于此解決方案,這表明您的聚合的總體邊界并不正確。 什么是聚合: 聚合是一個(gè)更大的封裝單位,而不僅僅是一個(gè)類。每個(gè)事物的范圍限定在單個(gè)聚合內(nèi)。聚合組件的使用期被界限在整個(gè)聚合的生命周期中。 具體的,一個(gè)聚合將會(huì)處理命令,請(qǐng)...
摘要:由于初版需求及開(kāi)發(fā)工作都沒(méi)有參與,在接手項(xiàng)目后過(guò)了遍前端結(jié)構(gòu)發(fā)現(xiàn)所有交互及組件都是現(xiàn)擼,并未使用市面上已有的優(yōu)秀前端框架從我個(gè)人角度理解上出發(fā),后續(xù)需求變更中當(dāng)需要實(shí)現(xiàn)某些常用組件樣式或交互時(shí),基本上都需要現(xiàn)擼或者尋找合適的組件。 2016悄無(wú)聲息的過(guò)去了,再過(guò)不久便是農(nóng)歷新年 這幾天相對(duì)清閑梳理了一下去年所做的工作,希望在新的一年能發(fā)展的更好 今年一共研發(fā)或升級(jí)了五款產(chǎn)品:合伙人、奪...
摘要:解決冪等問(wèn)題的三部曲,也是作者的思考框架。這是解決冪等問(wèn)題的第二部曲列出并減少副作用的分析維度。所以在并發(fā)執(zhí)行的維度,將并發(fā)重復(fù)執(zhí)行變成串行重復(fù)執(zhí)行是最好的冪等解決方案。 綱要 文章目的:本文旨在提煉一套分布式冪等問(wèn)題的思考框架,而非解決某個(gè)具體的分布式冪等問(wèn)題。在這個(gè)框架體系內(nèi),會(huì)有一些方案舉例說(shuō)明。文章目標(biāo):希望讀者能通過(guò)這套思考框架設(shè)計(jì)出符合自己業(yè)務(wù)的完備的冪等解決方案。文章內(nèi)容...
摘要:結(jié)論二從不同的角度去看抽象一致性得出的結(jié)論是不一樣的只有最符合現(xiàn)有業(yè)務(wù)的沒(méi)有最正確的說(shuō)明三對(duì)于實(shí)現(xiàn)一方法是查詢用戶的消費(fèi)信息而這里的詳細(xì)計(jì)算訂單金額直接寫(xiě)在這個(gè)方法里面抽象層次十分混亂所以實(shí)現(xiàn)一是不推薦的。 場(chǎng)景 用戶實(shí)體User 通過(guò)用戶Id查找用戶的訂單信息接口List orders = orderService.queryOrders(long userId) 通過(guò)用戶Id查找...
摘要:離職新路線年的總結(jié)在這里年總結(jié),其實(shí)在發(fā)布這個(gè)文章之前,就已經(jīng)跟阿里那邊再談新的,會(huì)以的級(jí)別入職阿里閑魚(yú)部門。總所周知,我司在月份調(diào)整了一次架構(gòu),具體如下美團(tuán)調(diào)整了組織架構(gòu)。 17年的總結(jié)來(lái)的更晚一點(diǎn),其實(shí)是一直在猶豫要不要寫(xiě),主要感覺(jué)去年一年折騰的有點(diǎn)兇殘,連續(xù)換工作以及地點(diǎn),一路走來(lái)有糾結(jié),有痛苦,有快樂(lè),有興奮,有迷茫,有得有失,所以想了很久,還是來(lái)記錄下這一年的關(guān)鍵點(diǎn)。 離職 ...
閱讀 3053·2021-09-08 10:43
閱讀 1039·2019-08-30 15:53
閱讀 989·2019-08-30 13:51
閱讀 849·2019-08-29 14:03
閱讀 810·2019-08-26 18:35
閱讀 1243·2019-08-26 13:38
閱讀 1592·2019-08-26 10:34
閱讀 3506·2019-08-26 10:21