偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

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

云計(jì)算 分布式
我們?nèi)粘i_發(fā)中,經(jīng)常需要使用到分布式ID。我們系統(tǒng)一般都是分布式部署的,一些分布式鎖、冪等、數(shù)據(jù)庫的唯一鍵,都需要分布式ID。

前言

大家好,我是田螺。

我們?nèi)粘i_發(fā)中,經(jīng)常需要使用到分布式ID。我們系統(tǒng)一般都是分布式部署的,一些分布式鎖、冪等、數(shù)據(jù)庫的唯一鍵,都需要分布式ID。

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

1. 數(shù)據(jù)庫自增ID

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

圖片圖片

優(yōu)點(diǎn):簡單易用、ID有序、索引效率高缺點(diǎn):單點(diǎn)故障、擴(kuò)展性差(分庫分表困難)
適用場景:單機(jī)或簡單主從架構(gòu)系統(tǒng)

代碼示例

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

2. UUID

  • 原理:基于MAC地址、時(shí)間戳、隨機(jī)數(shù)生成128位字符串
  • 優(yōu)點(diǎn):全局唯一、無需中心化服務(wù)
  • 缺點(diǎn):無序?qū)е滤饕实?、存儲空間大(36字符)
  • 適用場景:日志跟蹤、非核心業(yè)務(wù)(如臨時(shí)會話)

我們的項(xiàng)目中,有些伙伴為了簡單方便,有時(shí)候會直接用它,如果業(yè)務(wù)性比較強(qiáng)的,就在它后綴拼接寫個(gè)性化標(biāo)記(業(yè)務(wù)標(biāo)記)進(jìn)來~

代碼示例

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

3. 雪花算法(Snowflake)

  • 原理:64位結(jié)構(gòu) = 時(shí)間戳(41位) + 機(jī)器ID(10位) + 序列號(12位)

    圖片圖片

  • 優(yōu)點(diǎn):高性能(單機(jī)每秒4萬+)、趨勢遞增29
  • 缺點(diǎn):依賴時(shí)鐘同步(時(shí)鐘回?fù)軙?dǎo)致重復(fù))
  • 適用場景:分布式高并發(fā)系統(tǒng)(如電商訂單)

其實(shí),我們現(xiàn)在的系統(tǒng),很多場景就是用雪花算法生成的,如流水號等等~

代碼示例

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("時(shí)鐘回?fù)埽?);
        }
        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. 數(shù)據(jù)庫號段模式

  • 原理:批量獲取ID段(如一次取1000個(gè)),減少數(shù)據(jù)庫訪問
  • 優(yōu)點(diǎn):降低數(shù)據(jù)庫壓力、可用性高(緩存號段)、速度快
  • 缺點(diǎn):在服務(wù)器重啟或故障轉(zhuǎn)移等情況下,可能會導(dǎo)致ID的生成出現(xiàn)不連續(xù)的情況。
  • 適用場景:中等并發(fā)業(yè)務(wù)(如用戶ID生成)

我們的一些客戶號,當(dāng)前是用號段模式生成的,然后拼一些業(yè)務(wù)標(biāo)記

表結(jié)構(gòu):

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

    圖片圖片

  • 優(yōu)點(diǎn):性能優(yōu)于數(shù)據(jù)庫、天然有序、高性能、可擴(kuò)展性強(qiáng)
  • 缺點(diǎn):依賴Redis可用性
  • 適用場景:按日生成的流水號(如訂單號=日期+自增)

代碼示例:

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

6.百度的uid-generator

優(yōu)點(diǎn):避免頻繁生成、吞吐量提升至600萬/秒
適用場景:超大規(guī)模分布式系統(tǒng)

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

與原始的snowflake算法不同在于,uid-generator支持自定義時(shí)間戳、工作機(jī)器ID和 序列號 等各部分的位數(shù),而且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) {  
        // 創(chuàng)建一個(gè)UidGenerator實(shí)例  
        UidGenerator uidGenerator = new CachedUidGenerator();  
  
        // 初始化,這里只是一個(gè)簡單的示例,實(shí)際使用時(shí)你可能需要根據(jù)你的業(yè)務(wù)場景進(jìn)行更復(fù)雜的配置  
        // 例如,設(shè)置workerId、epoch等  
        // 注意:在多實(shí)例部署時(shí),每個(gè)實(shí)例的workerId必須唯一  
        long workerId = 1L; // 示例ID,實(shí)際使用時(shí)需要保證每個(gè)實(shí)例的唯一性  
        long datacenterId = 1L; // 數(shù)據(jù)中心ID,示例  
        uidGenerator.init(workerId, datacenterId, null);  
  
        // 生成一個(gè)UID  
        long uid = uidGenerator.getUID();  
        System.out.println("Generated UID: " + uid);  
    }  
}


7. 基于Zookeeper的順序節(jié)點(diǎn)

利用Zookeeper的順序節(jié)點(diǎn)特性來生成全局唯一ID。

圖片圖片

優(yōu)點(diǎn):

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

缺點(diǎn):

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

8. 數(shù)據(jù)庫集群模式

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

圖片圖片


數(shù)據(jù)庫集群模式優(yōu)點(diǎn)

  • 可以有效生成集群中的唯一ID。解決了單點(diǎn)的問題。
  • 降低ID生成數(shù)據(jù)庫操作的負(fù)載。

數(shù)據(jù)庫集群模式缺點(diǎn)

  • 需要獨(dú)立部署多個(gè)數(shù)據(jù)庫實(shí)例,成本高。
  • 后期不方便擴(kuò)展

9. 美團(tuán)(Leaf)

Leaf是美團(tuán)點(diǎn)評開源的分布式ID生成系統(tǒng),包含基于數(shù)據(jù)庫和基于Zookeeper的兩種實(shí)現(xiàn)方式。

以基于數(shù)據(jù)庫的自增ID生成策略為例(數(shù)據(jù)庫表結(jié)構(gòu)):

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

Java 實(shí)現(xiàn):

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; // 假設(shè)步長為1000,你可以從數(shù)據(jù)庫中讀取這個(gè)值  
  
                // 假設(shè)這里只是簡單演示,不檢查是否超過max_id + step是否溢出  
                updateStmt = conn.prepareStatement(UPDATE_SQL);  
                updateStmt.setInt(1, step);  
                updateStmt.setString(2, bizTag);  
                updateStmt.executeUpdate();  
  
                // 返回ID區(qū)間中的一個(gè)ID,這里簡單返回maxId(實(shí)際應(yīng)用中可能需要更復(fù)雜的策略)  
                return maxId;  
            } else {  
                // 如果沒有找到對應(yīng)的bizTag,則需要初始化  
                // ... 初始化代碼省略 ...  
                throw new RuntimeException("BizTag not found: " + bizTag);  
            }  
        } finally {  
            // 關(guān)閉資源,省略了異常處理  
            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();  
        }  
    }  
}

優(yōu)點(diǎn)

  • 結(jié)合了數(shù)據(jù)庫和Zookeeper的優(yōu)點(diǎn),提供了高可用和高性能的ID生成服務(wù)。缺點(diǎn):
  • 就是時(shí)鐘回?fù)軉栴}、復(fù)雜性高。

10. 滴滴(Tinyid)

Tinyid是滴滴開源的輕量級分布式ID生成系統(tǒng),它是基于號段模式原理實(shí)現(xiàn)的與Leaf如出一轍,每個(gè)服務(wù)獲取一個(gè)號段(1000,2000]、(2000,3000]、(3000,4000]

圖片圖片

以下是一個(gè)簡化的Tinyid,服務(wù)端的偽代碼:

// 假設(shè)我們有一個(gè)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();  
    }  
  
    // 這里應(yīng)該是RESTful API的實(shí)現(xiàn),但為簡化起見,我們省略了HTTP部分  
    // 客戶端應(yīng)該通過HTTP請求調(diào)用此方法  
    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 {  
                    // 假設(shè)服務(wù)端返回的是純文本格式的ID  
                    String responseBody = response.body().string();  
                    long id = Long.parseLong(responseBody);  
                    System.out.println("Generated ID: " + id);  
                }  
            }  
        });  
    }  
}
  • 優(yōu)缺點(diǎn):簡單、輕量級,但性能可能不如其他方案。
責(zé)任編輯:武曉燕 來源: 撿田螺的小男孩
相關(guān)推薦

2019-04-24 08:31:43

分布式限流kafka

2025-05-16 09:34:10

2024-07-02 11:16:21

2019-06-18 09:10:01

工具策略系統(tǒng)

2019-11-14 08:44:11

分布式系統(tǒng)策略

2017-10-24 14:57:58

AI人工智能機(jī)器學(xué)習(xí)

2018-04-26 16:15:02

數(shù)據(jù)庫MySQLMySQL 8.0

2018-03-19 14:43:28

2021-07-01 09:00:00

安全數(shù)字化轉(zhuǎn)型滲透

2021-12-09 08:16:40

JVM參數(shù)系統(tǒng)

2019-11-04 09:07:48

DevOps互聯(lián)網(wǎng)IT

2023-09-11 08:51:23

LinkedList雙向鏈表線程

2021-06-17 13:40:47

區(qū)塊鏈比特幣公有鏈

2021-10-06 16:21:32

類型對象Typescript

2023-12-11 21:59:01

時(shí)序分析深度學(xué)習(xí)自回歸模型

2022-06-16 07:31:15

MySQL服務(wù)器服務(wù)

2017-12-23 14:55:14

Java語言編程

2020-03-18 18:20:19

區(qū)塊鏈數(shù)字貨幣比特幣

2019-12-04 07:57:22

6G5G網(wǎng)絡(luò)

2017-08-28 16:40:07

Region切分觸發(fā)策略
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號