網(wǎng)站建設(shè)如何就接入支付寶推廣平臺(tái)app
文章目錄
- 問(wèn)題及需求
- 常用ID解決方案
- 數(shù)據(jù)庫(kù)自增ID
- UUID
- Redis發(fā)號(hào)器
- Snowflake雪花算法
- 分布式 ID 生成算法Snowflake原理
- 關(guān)于bit與byte
- 雪花算法的位數(shù)
- Snowflake必須注意的地方
- 全局唯?、不能重復(fù)
- 保證各個(gè)系統(tǒng)時(shí)間一致
- Snowflake雪花算法實(shí)現(xiàn)
- 雪花算法測(cè)試結(jié)果
問(wèn)題及需求
單庫(kù)下?般使用Mysql自增ID,但是分庫(kù)分表后,會(huì)造成不同分片上的數(shù)據(jù)表主鍵會(huì)重復(fù)
需求:性能強(qiáng)勁、全局唯一、防止惡意用戶規(guī)矩id的規(guī)則來(lái)獲取數(shù)據(jù)
常用ID解決方案
數(shù)據(jù)庫(kù)自增ID
利用自增id, 設(shè)置不同的?增步長(zhǎng):auto_increment_offset
、auto-increment-increment
DB1: 單數(shù)
//從1開(kāi)始、每次加2
DB2: 偶數(shù)
//從2開(kāi)始,每次加2
缺點(diǎn):
- 依靠數(shù)據(jù)庫(kù)系統(tǒng)的功能實(shí)現(xiàn),但是未來(lái)擴(kuò)容麻煩
- 主從切換時(shí)的不?致可能會(huì)導(dǎo)致重復(fù)發(fā)號(hào)
- 性能瓶頸存在單臺(tái)sql上
UUID
性能非常高,沒(méi)有網(wǎng)絡(luò)消耗
缺點(diǎn):
- 無(wú)序的字符串,不具備趨勢(shì)自增特性
- UUID太長(zhǎng),不易于存儲(chǔ),浪費(fèi)存儲(chǔ)空間,很多場(chǎng)景不適用
Redis發(fā)號(hào)器
利用Redis的INCR和INCRBY來(lái)實(shí)現(xiàn),原子操作,線程安全,性能比Mysql強(qiáng)勁
缺點(diǎn):
- 需要占用網(wǎng)絡(luò)資源,增加系統(tǒng)復(fù)雜度
Snowflake雪花算法
- twitter 開(kāi)源的分布式 ID生成算法,代碼實(shí)現(xiàn)簡(jiǎn)單、不占用寬帶、數(shù)據(jù)遷移不受影響
- 生成的 id 中包含有時(shí)間戳,所以生成的 id按照時(shí)間遞增
- 部署了多臺(tái)服務(wù)器,需要保證系統(tǒng)時(shí)間?樣,機(jī)器編號(hào)不?樣
缺點(diǎn):
- 依賴系統(tǒng)時(shí)鐘(多臺(tái)服務(wù)器時(shí)間?定要?樣)
分布式 ID 生成算法Snowflake原理
關(guān)于bit與byte
bit(位):電腦中存儲(chǔ)的最小單位,可以存儲(chǔ)?進(jìn)制中的0或1
byte(字節(jié)):?個(gè)byte由8個(gè)bit組成
常規(guī)64位系統(tǒng)??java數(shù)據(jù)類(lèi)型存儲(chǔ)字節(jié)大小
int:4 個(gè)字節(jié)
short:2 個(gè)字節(jié)
long:8 個(gè)字節(jié)
byte:1 個(gè)字節(jié)
float:4 個(gè)字節(jié)
double:8 個(gè)字節(jié)
char:2 個(gè)字節(jié)
科普:數(shù)據(jù)類(lèi)型在不同位數(shù)機(jī)器的平臺(tái)下長(zhǎng)度不同
16位平臺(tái) int 2個(gè)字節(jié)16位
32位平臺(tái) int 4個(gè)字節(jié)32位
64位平臺(tái) int 4個(gè)字節(jié)32位
雪花算法的位數(shù)
雪花算法生成的數(shù)字,long類(lèi),所以是:8個(gè)byte,64bit
表示的值 -9223372036854775808(-2的63次方)~9223372036854775807(2的63次?-1)
生成的唯?值?于數(shù)據(jù)庫(kù)主鍵,不能是負(fù)數(shù),所以值為0~9223372036854775807(2的63次方-1)
- 第一個(gè)bit位代表符號(hào)位,正數(shù)是0,負(fù)數(shù)是1,ID為正數(shù),所以固定為0
- 毫秒級(jí)時(shí)間戳部分占41bit,不是存儲(chǔ)當(dāng)前時(shí)間的時(shí)間截,服務(wù)上線的時(shí)間毫秒級(jí)的時(shí)間戳(為當(dāng)前時(shí)間-服務(wù)第一次上線時(shí)間)
- 工作機(jī)器 id占10bit,可支持210 =1024個(gè)節(jié)點(diǎn)
- 序列號(hào)部分占12bit,可允許同一毫秒生成212 =4096個(gè)Id,則理論上一秒就可生成4096*1000 = 400萬(wàn)個(gè)ld
- 組合起來(lái)剛好是64位,Long類(lèi)型
Snowflake必須注意的地方
全局唯?、不能重復(fù)
分布式部署就需要分配不同的workId, 如果workId相同,
可能會(huì)導(dǎo)致?成的id相同
保證各個(gè)系統(tǒng)時(shí)間一致
分布式情況下,需要保證各個(gè)系統(tǒng)時(shí)間?致,如果服務(wù)器的時(shí)鐘回?fù)?#xff0c;就會(huì)導(dǎo)致?成的 id 重復(fù)
什么時(shí)候會(huì)系統(tǒng)回?fù)?#xff1f;
- 人工去生產(chǎn)環(huán)境做了系統(tǒng)時(shí)間調(diào)整
- 業(yè)務(wù)需求,代碼里面做了系統(tǒng)時(shí)間同步
Snowflake雪花算法實(shí)現(xiàn)
配置文件
增加:
#配置workId
spring.shardingsphere.sharding.tables.product_order.key-generator.props.worker.id=1
方式一:訂單id使用MybatisPlus的配置,ProductOrder類(lèi)配置
@TableId(value = "id", type = IdType.ASSIGN_ID)
默認(rèn)實(shí)現(xiàn)類(lèi)為DefaultIdentifierGenerator雪花算法
方式二:使用Sharding-Jdbc配置文件,注釋DO類(lèi)里面的id分配策略
#id?成策略
spring.shardingsphere.sharding.tables.product_order.key-generator.column=id
spring.shardingsphere.sharding.tables.product_order.key-generator.type=SNOWFLAKE
方式三 進(jìn)階:動(dòng)態(tài)指定sharding jdbc 的雪花算法中的屬性work.id屬性
使用sharding-jdbc中的使用IP后幾位來(lái)做workId,但在某些情況下會(huì)出現(xiàn)生成重復(fù)ID的情況
解決辦法: 在啟動(dòng)時(shí)給每個(gè)服務(wù)分配不同的workId, 引?redis/zk都行,缺點(diǎn)就是多了依賴
雪花算法測(cè)試結(jié)果
可以看出id全局不重復(fù),并呈現(xiàn)出遞增增長(zhǎng)