概述
項目中為了緩解數據庫服務器壓力和提高并發量進行分庫分表,在新增數據時,如果此時按照傳統方式使用數據庫主鍵自增,那么在并發下ID可能會沖突; 使用UUID的話又因其無序會產生頁分裂導致磁盤IO過大使得系統性能降低;? 經過了解雪花算法根據其特點可以解決分布式系統中生成高性能、趨勢遞增、全局唯一ID, 因此項目中使用雪花算法策略生成ID
雪花算法特點
- 唯一性:?通過結合時間戳、機器ID和序列號,雪花算法可以生成幾乎唯一的ID
- 高性能:?雪花算法在內存中生成ID,無需訪問數據庫或其他外部服務,因此具有很高的性能
- 趨勢遞增:?生成的ID是趨勢遞增的,這有助于數據庫索引優化,提高查詢效率
- 去中心化:?每個節點可以獨立生成ID,無需協調,適合分布式系統
- 可定制性:?算法中的不同部分(時間戳、機器ID、序列號)可以根據實際需求進行調整
- 擴展
- 中心化生成主鍵方案
- 基于SEQUENCE區間方案
- 各數據庫按特定步長自增
- 基于redis生成自增序列
- 去中心化生成主鍵方案
- UUID生成無序的唯一ID
- 雪花算法生成ID
- 中心化生成主鍵方案
項目最佳實踐
- 引入第三方依賴
<dependency><groupId>cn.hutool</groupId><artifactId>hutool-core</artifactId>
</dependency>
- 雪花Id生成工具類
import cn.hutool.core.lang.Snowflake;
import java.util.Random;public class SnowFlakeUtil {// 終端機器ID: 【0-31】private static long workerId = 1; // 數據中心ID: 【0-31】private static long dataCenterId = 1;private volatile static Snowflake snowflake; //雪花對象//靜態塊實現對象初始化static{Random rand=new Random();// 分布式環境下確保為每個實例配置了唯一的workerId和dataCenterId,以避免ID沖突,因此采取隨機方法設置workerId = rand.nextInt(31)+1;//[1,31]內的隨機整數dataCenterId = rand.nextInt(31)+1;//[1,31]內的隨機整數snowflake = getInstance();}// Long型IDpublic static long nextId() {return snowflake.nextId();}// String類型IDpublic static String nextIdStr(){return snowflake.nextIdStr();}// 通過雙重檢測保證Snowflake對象在高并發下對象唯一private static Snowflake getInstance() {if (null == snowflake) {synchronized (SnowFlakeUtil.class) {if (null == snowflake) {snowflake = new Snowflake(workerId, dataCenterId);}}}return snowflake;}// 測試public static void main(String[] args) {System.out.println("IdLong: " + SnowFlakeUtil.nextId()); // IdLong: 1798609085217599488 雪花算法默認LongSystem.out.println("IdStr: " + SnowFlakeUtil.nextIdStr()); // IdStr: 1798609085217599489 某些場景下需要字符串類型}
}