Go 開發(fā)的一款分布式唯一 ID 生成系統(tǒng)
今天跟大家介紹一個(gè)開源項(xiàng)目:id-maker,主要功能是用來在分布式環(huán)境下生成唯一 ID。上周停更了一周,也是用來開發(fā)和測(cè)試這個(gè)項(xiàng)目的相關(guān)代碼。
美團(tuán)有一個(gè)開源項(xiàng)目叫 Leaf,使用 Java 開發(fā)。本項(xiàng)目就是在此思路的基礎(chǔ)上,使用 Go 開發(fā)實(shí)現(xiàn)的。
項(xiàng)目整體代碼量并不多,不管是想要在實(shí)際生產(chǎn)環(huán)境中使用,還是想找個(gè)項(xiàng)目練手,我覺得都是一個(gè)不錯(cuò)的選擇。
項(xiàng)目背景
在大部分系統(tǒng)中,全局唯一 ID 都是一個(gè)強(qiáng)需求。比如快遞,外賣,電影等,都需要生成唯一 ID 來保證單號(hào)唯一。
那業(yè)務(wù)系統(tǒng)對(duì) ID 號(hào)的要求有哪些呢?
- 全局唯一性:不能出現(xiàn)重復(fù)的 ID 號(hào),既然是唯一標(biāo)識(shí),這是最基本的要求。
 - 趨勢(shì)遞增:在 MySQL InnoDB 引擎中使用的是聚集索引,由于多數(shù) RDBMS 使用 B-tree 的數(shù)據(jù)結(jié)構(gòu)來存儲(chǔ)索引數(shù)據(jù),在主鍵的選擇上面我們應(yīng)該盡量使用有序的主鍵保證寫入性能。
 - 單調(diào)遞增:保證下一個(gè) ID 一定大于上一個(gè) ID,例如事務(wù)版本號(hào)、IM 增量消息、排序等特殊需求。
 - 信息安全:如果 ID 是連續(xù)的,惡意用戶的扒取工作就非常容易做了,直接按照順序下載指定 URL 即可;如果是訂單號(hào)就更危險(xiǎn)了,競(jìng)對(duì)可以直接知道我們一天的單量。所以在一些應(yīng)用場(chǎng)景下,會(huì)需要 ID 無規(guī)則、不規(guī)則。
 
在此背景下,有一個(gè)高可用的唯一 ID 生成系統(tǒng)就很重要了。
項(xiàng)目使用
生成 ID 分兩種方式:
- 根據(jù)數(shù)據(jù)庫生成 ID。
 - 根據(jù)雪花算法生成 ID。
 
使用上提供兩種方式來調(diào)用接口:
- HTTP 方式
 - gRPC 方式
 
HTTP 方式
1、健康檢查:
- curl http://127.0.0.1:8080/ping
 
2、獲取 ID:
獲取 tag 是 test 的 ID:
- curl http://127.0.0.1:8080/v1/id/test
 
3、獲取雪花 ID:
- curl http://127.0.0.1:8080/v1/snowid
 
gRPC 方式
1、獲取 ID:
- grpcurl -plaintext -d '{"tag":"test"}' -import-path $HOME/src/id-maker/internal/controller/rpc/proto -proto segment.proto localhost:50051 proto.Gid/GetId
 
2、獲取雪花 ID:
- grpcurl -plaintext -import-path $HOME/src/id-maker/internal/controller/rpc/proto -proto segment.proto localhost:50051 proto.Gid/GetSnowId
 
本地開發(fā)
- # Run MySQL
 - $ make compose-up
 - # Run app with migrations
 - $ make run
 
項(xiàng)目架構(gòu)
項(xiàng)目使用 go-clean-template 架構(gòu)模板開發(fā),目錄結(jié)構(gòu)如下:
下面對(duì)各目錄做一個(gè)簡要說明:
- cmd:程序入口
 - config:配置文件
 - docs:生成的項(xiàng)目文檔
 - integration-test:整合測(cè)試
 - internal:業(yè)務(wù)代碼
 - pkg:一些調(diào)用的包
 
借用官方的兩張圖:
整體的層次關(guān)系是這樣的,最里面是 models,定義我們的表結(jié)構(gòu),然后中間是業(yè)務(wù)邏輯層,業(yè)務(wù)邏輯層會(huì)提供接口,給最外層的 API 來調(diào)用,最外層就是一些工具和調(diào)用入口。
這樣做的最大好處就是解耦,不管最外層如何變化,只要在業(yè)務(wù)邏輯層實(shí)現(xiàn)對(duì)應(yīng)接口即可,核心代碼可能根本不需要改變。
所以,它們之間的調(diào)用關(guān)系看起來是這樣的:
- HTTP > usecase
 - usecase > repository (Postgres)
 - usecase < repository (Postgres)
 - HTTP < usecase
 
以上就是本項(xiàng)目的全部內(nèi)容,如果大家感興趣的話,歡迎給我留言交流,要是能給個(gè) star 那就太好了。
項(xiàng)目地址:
- https://github.com/yongxinz/id-maker
 
本文轉(zhuǎn)載自微信公眾號(hào)「AlwaysBeta」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請(qǐng)聯(lián)系A(chǔ)lwaysBeta公眾號(hào)。



















 
 
 












 
 
 
 