成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

分布式ID生成的常見方案~都在這里啦!

云計算 分布式
我們日常開發中,經常需要使用到分布式ID。我們系統一般都是分布式部署的,一些分布式鎖、冪等、數據庫的唯一鍵,都需要分布式ID。

前言

大家好,我是田螺。

我們日常開發中,經常需要使用到分布式ID。我們系統一般都是分布式部署的,一些分布式鎖、冪等、數據庫的唯一鍵,都需要分布式ID。

今天田螺哥盤點一些常見的分布式唯一ID生成方案。

1. 數據庫自增ID

原理:利用數據庫自增字段(如MySQL的AUTO_INCREMENT)生成唯一ID

圖片圖片

優點:簡單易用、ID有序、索引效率高缺點:單點故障、擴展性差(分庫分表困難)
適用場景:單機或簡單主從架構系統

代碼示例

CREATE TABLE orders (
    id INT AUTO_INCREMENT PRIMARY KEY,
    order_data VARCHAR(255)
);

2. UUID

  • 原理:基于MAC地址、時間戳、隨機數生成128位字符串
  • 優點:全局唯一、無需中心化服務
  • 缺點:無序導致索引效率低、存儲空間大(36字符)
  • 適用場景:日志跟蹤、非核心業務(如臨時會話)

我們的項目中,有些伙伴為了簡單方便,有時候會直接用它,如果業務性比較強的,就在它后綴拼接寫個性化標記(業務標記)進來~

代碼示例

import java.util.UUID;
String uuid = UUID.randomUUID().toString();

3. 雪花算法(Snowflake)

  • 原理:64位結構 = 時間戳(41位) + 機器ID(10位) + 序列號(12位)

    圖片圖片

  • 優點:高性能(單機每秒4萬+)、趨勢遞增29
  • 缺點:依賴時鐘同步(時鐘回撥會導致重復)
  • 適用場景:分布式高并發系統(如電商訂單)

其實,我們現在的系統,很多場景就是用雪花算法生成的,如流水號等等~

代碼示例

public class Snowflake {
    private long machineId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public synchronized long nextId() {
        long timestamp = System.currentTimeMillis();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("時鐘回撥!");
        }
        if (timestamp == lastTimestamp) {
            sequence = (sequence + 1) & 4095; // 12位序列號
            if (sequence == 0) timestamp = tilNextMillis(lastTimestamp);
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;
        return (timestamp << 22) | (machineId << 12) | sequence;
    }
}

4. 數據庫號段模式

  • 原理:批量獲取ID段(如一次取1000個),減少數據庫訪問
  • 優點:降低數據庫壓力、可用性高(緩存號段)、速度快
  • 缺點:在服務器重啟或故障轉移等情況下,可能會導致ID的生成出現不連續的情況。
  • 適用場景:中等并發業務(如用戶ID生成)

我們的一些客戶號,當前是用號段模式生成的,然后拼一些業務標記

表結構:

CREATE TABLE id_segment (
    biz_tag VARCHAR(50) PRIMARY KEY,
    max_id BIGINT NOT NULL,
    step INT NOT NULL,
    version INT NOT NULL
);

5. Redis分布式ID

  • 原理:利用INCR原子操作生成遞增ID

    圖片圖片

  • 優點:性能優于數據庫、天然有序、高性能、可擴展性強
  • 缺點:依賴Redis可用性
  • 適用場景:按日生成的流水號(如訂單號=日期+自增)

代碼示例:

Jedis jedis = new Jedis("redis-host");
Long orderId = jedis.incr("order:20240526");

6.百度的uid-generator

優點:避免頻繁生成、吞吐量提升至600萬/秒
適用場景:超大規模分布式系統

基于Twitter的Snowflake算法進行改進,增加了更多的配置和靈活性。

與原始的snowflake算法不同在于,uid-generator支持自定義時間戳、工作機器ID和 序列號 等各部分的位數,而且uid-generator中采用用戶自定義workId的生成策略。

代碼示例:

import com.baidu.fsg.uid.UidGenerator;  
import com.baidu.fsg.uid.impl.CachedUidGenerator;  
  
public class UidGeneratorDemo {  
  
    public static void main(String[] args) {  
        // 創建一個UidGenerator實例  
        UidGenerator uidGenerator = new CachedUidGenerator();  
  
        // 初始化,這里只是一個簡單的示例,實際使用時你可能需要根據你的業務場景進行更復雜的配置  
        // 例如,設置workerId、epoch等  
        // 注意:在多實例部署時,每個實例的workerId必須唯一  
        long workerId = 1L; // 示例ID,實際使用時需要保證每個實例的唯一性  
        long datacenterId = 1L; // 數據中心ID,示例  
        uidGenerator.init(workerId, datacenterId, null);  
  
        // 生成一個UID  
        long uid = uidGenerator.getUID();  
        System.out.println("Generated UID: " + uid);  
    }  
}


7. 基于Zookeeper的順序節點

利用Zookeeper的順序節點特性來生成全局唯一ID。

圖片圖片

優點:

  • 利用Zookeeper的集群特性保證高可用。
  • ID全局唯一。

缺點:

  • 需要依賴Zookeeper集群。
  • 可能會受到Zookeeper性能的限制。
  • 并發競爭較大不適合用Zookeeper

8. 數據庫集群模式

單庫的數據庫自增ID會存在單點問題,所以可以用數據庫集群模式,去解決這個問題。數據庫集群模式:通過多個數據庫實例設置不同的起始值和步長來生成全局唯一的ID。

圖片圖片


數據庫集群模式優點

  • 可以有效生成集群中的唯一ID。解決了單點的問題。
  • 降低ID生成數據庫操作的負載。

數據庫集群模式缺點

  • 需要獨立部署多個數據庫實例,成本高。
  • 后期不方便擴展

9. 美團(Leaf)

Leaf是美團點評開源的分布式ID生成系統,包含基于數據庫和基于Zookeeper的兩種實現方式。

以基于數據庫的自增ID生成策略為例(數據庫表結構):

CREATE TABLE leaf_alloc (  
    biz_tag VARCHAR(128) NOT NULL COMMENT '業務key',  
    max_id BIGINT(20) NOT NULL COMMENT '當前已分配的最大id',  
    step INT(11) NOT NULL COMMENT '每次id的增長步長',  
    PRIMARY KEY (biz_tag)  
) ENGINE=INNODB DEFAULT CHARSET=utf8mb4;

Java 實現:

import java.sql.*;  
  
public class LeafIdGenerator {  
  
    private static final String JDBC_URL = "jdbc:mysql://localhost:3306/your_database?useSSL=false&serverTimeznotallow=UTC";  
    private static final String USERNAME = "your_username";  
    private static final String PASSWORD = "your_password";  
  
    private static final String UPDATE_SQL = "UPDATE leaf_alloc SET max_id = max_id + ? WHERE biz_tag = ?";  
    private static final String SELECT_SQL = "SELECT max_id FROM leaf_alloc WHERE biz_tag = ? FOR UPDATE";  
  
    public synchronized long getId(String bizTag) throws SQLException {  
        Connection conn = null;  
        PreparedStatement updateStmt = null;  
        PreparedStatement selectStmt = null;  
        ResultSet rs = null;  
  
        try {  
            conn = DriverManager.getConnection(JDBC_URL, USERNAME, PASSWORD);  
            selectStmt = conn.prepareStatement(SELECT_SQL);  
            selectStmt.setString(1, bizTag);  
            rs = selectStmt.executeQuery();  
  
            if (rs.next()) {  
                long maxId = rs.getLong("max_id");  
                int step = 1000; // 假設步長為1000,你可以從數據庫中讀取這個值  
  
                // 假設這里只是簡單演示,不檢查是否超過max_id + step是否溢出  
                updateStmt = conn.prepareStatement(UPDATE_SQL);  
                updateStmt.setInt(1, step);  
                updateStmt.setString(2, bizTag);  
                updateStmt.executeUpdate();  
  
                // 返回ID區間中的一個ID,這里簡單返回maxId(實際應用中可能需要更復雜的策略)  
                return maxId;  
            } else {  
                // 如果沒有找到對應的bizTag,則需要初始化  
                // ... 初始化代碼省略 ...  
                throw new RuntimeException("BizTag not found: " + bizTag);  
            }  
        } finally {  
            // 關閉資源,省略了異常處理  
            if (rs != null) rs.close();  
            if (selectStmt != null) selectStmt.close();  
            if (updateStmt != null) updateStmt.close();  
            if (conn != null) conn.close();  
        }  
    }  
  
    public static void main(String[] args) {  
        LeafIdGenerator generator = new LeafIdGenerator();  
        try {  
            long id = generator.getId("test-biz-tag");  
            System.out.println("Generated ID: " + id);  
        } catch (SQLException e) {  
            e.printStackTrace();  
        }  
    }  
}

優點

  • 結合了數據庫和Zookeeper的優點,提供了高可用和高性能的ID生成服務。缺點:
  • 就是時鐘回撥問題、復雜性高。

10. 滴滴(Tinyid)

Tinyid是滴滴開源的輕量級分布式ID生成系統,它是基于號段模式原理實現的與Leaf如出一轍,每個服務獲取一個號段(1000,2000]、(2000,3000]、(3000,4000]

圖片圖片

以下是一個簡化的Tinyid,服務端的偽代碼:

// 假設我們有一個ID生成器,這里用AtomicLong模擬  
import java.util.concurrent.atomic.AtomicLong;  
  
public class TinyidService {  
    private AtomicLong idGenerator = new AtomicLong(0);  
  
    // 模擬的ID生成方法  
    public synchronized long generateId() {  
        return idGenerator.incrementAndGet();  
    }  
  
    // 這里應該是RESTful API的實現,但為簡化起見,我們省略了HTTP部分  
    // 客戶端應該通過HTTP請求調用此方法  
    public long getIdOverHttp() {  
        return generateId();  
    }  
}

客戶端(Java示例)

import okhttp3.*;  
  
public class TinyidClient {  
    private static final String TINYID_SERVICE_URL = "http://localhost:8080/tinyid/generate";  
  
    public static void main(String[] args) {  
        OkHttpClient client = new OkHttpClient();  
  
        Request request = new Request.Builder()  
                .url(TINYID_SERVICE_URL)  
                .build();  
  
        client.newCall(request).enqueue(new Callback() {  
            @Override  
            public void onFailure(Call call, IOException e) {  
                e.printStackTrace();  
            }  
  
            @Override  
            public void onResponse(Call call, Response response) throws IOException {  
                if (!response.isSuccessful()) {  
                    throw new IOException("Unexpected code " + response);  
                } else {  
                    // 假設服務端返回的是純文本格式的ID  
                    String responseBody = response.body().string();  
                    long id = Long.parseLong(responseBody);  
                    System.out.println("Generated ID: " + id);  
                }  
            }  
        });  
    }  
}
  • 優缺點:簡單、輕量級,但性能可能不如其他方案。
責任編輯:武曉燕 來源: 撿田螺的小男孩
相關推薦

2019-04-24 08:31:43

分布式限流kafka

2025-05-16 09:34:10

2018-03-19 14:43:28

2017-10-24 14:57:58

AI人工智能機器學習

2021-07-01 09:00:00

安全數字化轉型滲透

2018-04-26 16:15:02

數據庫MySQLMySQL 8.0

2024-07-02 11:16:21

2019-06-18 09:10:01

工具策略系統

2019-11-14 08:44:11

分布式系統策略

2023-09-11 08:51:23

LinkedList雙向鏈表線程

2021-10-06 16:21:32

類型對象Typescript

2021-06-17 13:40:47

區塊鏈比特幣公有鏈

2023-12-11 21:59:01

時序分析深度學習自回歸模型

2021-12-09 08:16:40

JVM參數系統

2019-11-04 09:07:48

DevOps互聯網IT

2009-06-24 14:10:22

2017-08-28 16:40:07

Region切分觸發策略

2017-12-08 10:42:49

HBase切分細節

2022-03-02 10:36:37

Linux性能優化

2017-09-19 14:55:27

Android字體修改
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 国产成人综合在线 | 国产精品爱久久久久久久 | 伊人色综合久久天天五月婷 | 91精品久久久久久久久中文字幕 | 91最新入口 | 久久久久网站 | 国产高清精品在线 | 久久久网 | 日本福利一区 | 国产欧美久久精品 | 中文字幕亚洲精品 | 免费黄色的视频 | 九九av| 国产精品日韩 | 日韩一区二区在线播放 | 色毛片 | 国产精品久久久久久久久 | www.国产一区 | 伊人精品久久久久77777 | 性欧美hd| 国产一区在线免费观看 | 欧美区在线 | 亚州精品天堂中文字幕 | 成人乱人乱一区二区三区软件 | 午夜一级做a爰片久久毛片 精品综合 | 一区二区三区四区在线视频 | 国产亚洲成av人在线观看导航 | 欧美成人a| 久久国产精品-久久精品 | 欧美成人精品 | 涩涩视频在线观看免费 | 成人av色 | 日韩欧美在线一区 | 国产精品视频在线观看 | 成人精品一区二区三区 | 91麻豆精品国产91久久久久久久久 | 国产精品一区二区三区四区五区 | 亚洲国产精品久久久久婷婷老年 | 一级在线视频 | 亚洲国产欧美精品 | 一区二区免费 |