柚子快報(bào)邀請(qǐng)碼778899分享:分布式ID的使用
柚子快報(bào)邀請(qǐng)碼778899分享:分布式ID的使用
1.背景
分布式id(Distributed ID)可以用來(lái)唯一標(biāo)識(shí)分布式系統(tǒng)中的各個(gè)實(shí)體、任務(wù)或請(qǐng)求。它可以用于多種用途,包括以下幾個(gè)方面:
1. 數(shù)據(jù)庫(kù)主鍵:在分布式數(shù)據(jù)庫(kù)中,每個(gè)數(shù)據(jù)記錄需要一個(gè)唯一的主鍵標(biāo)識(shí)。分布式id可以用作主鍵,確保數(shù)據(jù)記錄的唯一性。
2. 分布式鎖:在分布式系統(tǒng)中,多個(gè)節(jié)點(diǎn)之間需要共享鎖來(lái)實(shí)現(xiàn)同步和互斥。分布式id可以作為鎖的名稱(chēng),確保每個(gè)節(jié)點(diǎn)使用的鎖是唯一的。
3. 分布式消息隊(duì)列:在消息隊(duì)列系統(tǒng)中,分布式id可以用來(lái)標(biāo)識(shí)消息的發(fā)送和接收狀態(tài),以便進(jìn)行消息的可靠傳輸和處理。
4. 分布式事務(wù):在分布式事務(wù)中,分布式id可以用來(lái)標(biāo)識(shí)事務(wù)的唯一性,確保事務(wù)的一致性和隔離性。
5. 分布式任務(wù)調(diào)度:在分布式任務(wù)調(diào)度系統(tǒng)中,分布式id可以用來(lái)標(biāo)識(shí)任務(wù)的唯一性,確保任務(wù)的正確執(zhí)行和結(jié)果的正確處理。
總之,分布式id可以在分布式系統(tǒng)中實(shí)現(xiàn)唯一標(biāo)識(shí)、數(shù)據(jù)一致性、任務(wù)調(diào)度等功能,提高系統(tǒng)的可靠性和性能。
這里我們采用美團(tuán)的leaf算法來(lái)實(shí)現(xiàn)分布式的唯一ID
2.號(hào)段模式
官方很懶,到現(xiàn)在還沒(méi)有上傳maven倉(cāng)庫(kù),需要手動(dòng)git下來(lái)。
git clone git@github.com:Meituan-Dianping/Leaf.git
git checkout feature/spring-boot-starter
cd Leaf
mvn clean install -Dmaven.test.skip=true
2.1依賴(lài)引入
2.2sql執(zhí)行
CREATE DATABASE leaf
CREATE TABLE `leaf_alloc` (
`biz_tag` varchar(128) NOT NULL DEFAULT '',
`max_id` bigint(20) NOT NULL DEFAULT '1',
`step` int(11) NOT NULL,
`description` varchar(256) DEFAULT NULL,
`update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`biz_tag`)
) ENGINE=InnoDB;
insert into leaf_alloc(biz_tag, max_id, step, description) values('leaf-segment-test', 1, 2000, 'Test leaf Segment Mode Get Id')
2.3?使用
1.在resources文件下創(chuàng)建一個(gè)leaf.properties
leaf.name=com.sankuai.leaf.opensource.test
leaf.segment.enable=true
leaf.segment.url=jdbc:mysql://localhost:3306/leaf
leaf.segment.username=root
leaf.segment.password=123456
2.主函數(shù)引入@EnableLeafServer注解
package com.mikey.distributed;
import com.sankuai.inf.leaf.plugin.annotation.EnableLeafServer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author mikey
* @create 2024-03-03 21:21
*/
@SpringBootApplication
@EnableLeafServer
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class,args);
}
}
3.實(shí)際應(yīng)用
@RestController
public class IdController {
@Autowired
private SegmentService segmentService;
@GetMapping("/segment")
public Result getId1() {
return segmentService.getId("leaf-segment-test");
}
}
2.4總結(jié)
Leaf 最早期需求是各個(gè)業(yè)務(wù)線的訂單ID生成需求。在美團(tuán)早期,有的業(yè)務(wù)直接通過(guò)DB自增的方式生成ID,有的業(yè)務(wù)通過(guò)redis緩存來(lái)生成ID,也有的業(yè)務(wù)直接用UUID這種方式來(lái)生成ID。以上的方式各自有各自的問(wèn)題,因此我們決定實(shí)現(xiàn)一套分布式ID生成服務(wù)來(lái)滿足需求。(來(lái)自官網(wǎng))
我們會(huì)發(fā)現(xiàn)在獲取id的時(shí)候,需要一個(gè)key,這個(gè)key實(shí)際就是數(shù)據(jù)庫(kù)的biz_tag這個(gè)字段,代表著業(yè)務(wù)的標(biāo)簽。max_id就是這次請(qǐng)求拿到的id,step就是步長(zhǎng)。
假設(shè)此時(shí)數(shù)據(jù)庫(kù)是? max_id = 1 , step = 20。
那么這次請(qǐng)求拿到的id就是1,然后他會(huì)緩存這1-20的id,下一次請(qǐng)求而不會(huì)請(qǐng)求數(shù)據(jù)庫(kù),而是從緩存里面拿,這里就是他性能高的原因。你會(huì)發(fā)現(xiàn)當(dāng)你請(qǐng)求多幾次的時(shí)候,而id還沒(méi)到20,數(shù)據(jù)庫(kù)的max_id更新到了21,這是因?yàn)樗麜?huì)提前去申請(qǐng)id空間,防止id不夠,而提前做了數(shù)據(jù)庫(kù)更新。
3.雪花算法
雪花算法(Snowflake Algorithm)是一種用于生成分布式系統(tǒng)中唯一 ID 的算法。
64 位二進(jìn)制格式:Snowflake 算法生成的唯一 ID 是一個(gè) 64 位的整數(shù),其結(jié)構(gòu)一般是:1位符號(hào)位(不使用)、41位的時(shí)間戳、10位的機(jī)器標(biāo)識(shí)(或工作機(jī)器 ID)、12位的序列號(hào)。 時(shí)間戳部分:占據(jù)了整個(gè) 64 位中的高位 41 位,可以精確到毫秒級(jí)別的時(shí)間,可以保證在相同的時(shí)間戳內(nèi)生成的 ID 唯一。 機(jī)器標(biāo)識(shí)部分:占據(jù)了中間的 10 位,用于區(qū)分不同的機(jī)器。這部分的信息可以手動(dòng)配置或者從機(jī)器的某些特征中提取,例如數(shù)據(jù)中心 ID 和機(jī)器 ID 的組合。 序列號(hào)部分:占據(jù)了低位的 12 位,用于解決在同一毫秒內(nèi)產(chǎn)生大量請(qǐng)求時(shí)的并發(fā)沖突問(wèn)題。在同一毫秒內(nèi),序列號(hào)會(huì)從 0 開(kāi)始遞增,最多可以生成 4096(2^12)個(gè)不同的 ID。 生成 ID 的規(guī)則:Snowflake 算法根據(jù)當(dāng)前時(shí)間戳、機(jī)器標(biāo)識(shí)和序列號(hào)生成唯一的 ID。當(dāng)某個(gè)節(jié)點(diǎn)生成 ID 時(shí),它會(huì)根據(jù)當(dāng)前時(shí)間戳計(jì)算出時(shí)間戳部分,將機(jī)器標(biāo)識(shí)和序列號(hào)部分組合成 ID。
實(shí)際上不同的公司都會(huì)根據(jù)自己的場(chǎng)景從而去改造雪花算法,可以從時(shí)間戳部分或者機(jī)器表示部分或者序列號(hào)部分去優(yōu)化,可以參考一下百度UidGenerator。
3.1依賴(lài)引入
這里需要引入zk的相關(guān)依賴(lài),可以理解成zk在這里做了數(shù)據(jù)庫(kù)這樣的角色,存儲(chǔ)了機(jī)器的標(biāo)識(shí)符(ip)。這里不展開(kāi)zk的安裝,自行查看相關(guān)資料。
3.2使用
1.在resources文件下創(chuàng)建一個(gè)leaf.properties
leaf.name=com.sankuai.leaf.opensource.test
leaf.snowflake.enable=false
leaf.snowflake.address=ip
leaf.snowflake.port=port
2.使用
@Autowired
private SnowflakeService snowflakeService;
@GetMapping("/snowflake")
public Result getId2() {
return snowflakeService.getId("111");
}
我們可以發(fā)現(xiàn)雪花算法這里也要獲取一個(gè)key,實(shí)際上這里的key是沒(méi)有意義的??纯磄ithub上的解釋。
柚子快報(bào)邀請(qǐng)碼778899分享:分布式ID的使用
精彩鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。