最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

MySQL分庫分表后主鍵ID生成的八種方案

 更新時間:2025年08月08日 08:59:04   作者:墨夶  
當你的MySQL數(shù)據(jù)庫因數(shù)據(jù)量或并發(fā)壓力進行分庫分表后,主鍵ID重復(fù)會成為系統(tǒng)崩潰的導火索,本文將從底層原理出發(fā),結(jié)合真實業(yè)務(wù)代碼,深度解析8種主流主鍵ID生成方案,助你構(gòu)建穩(wěn)定可靠的分庫分表系統(tǒng),需要的朋友可以參考下

分庫分表后的主鍵ID沖突陷阱

當你的MySQL數(shù)據(jù)庫因數(shù)據(jù)量或并發(fā)壓力進行分庫分表后,主鍵ID重復(fù)會成為系統(tǒng)崩潰的導火索。假設(shè)你將訂單表拆分為10個分表,每個分表都從1開始自增,最終會出現(xiàn)以下災(zāi)難性問題:

  • ID沖突:不同分表中的訂單ID可能完全相同
  • 業(yè)務(wù)混亂:無法通過ID直接定位數(shù)據(jù)所在分表
  • 分布式事務(wù)失敗:主鍵沖突導致寫入操作異常

本文將從底層原理出發(fā),結(jié)合真實業(yè)務(wù)代碼,深度解析8種主流主鍵ID生成方案,助你構(gòu)建穩(wěn)定可靠的分庫分表系統(tǒng)。

一、方案一:數(shù)據(jù)庫自增ID + 分段設(shè)置

核心思想

通過為每個分表配置不同的起始值步長,確保ID全局唯一。

實現(xiàn)代碼

-- 分表1(t_order_0)配置
ALTER TABLE t_order_0 AUTO_INCREMENT = 1; -- 起始值1,步長10

-- 分表2(t_order_1)配置
ALTER TABLE t_order_1 AUTO_INCREMENT = 11; -- 起始值11,步長10

-- 分表3(t_order_2)配置
ALTER TABLE t_order_2 AUTO_INCREMENT = 21; -- 起始值21,步長10

代碼注解

  • 步長設(shè)置:若總分表數(shù)為N,則每個分表步長設(shè)為N
  • 起始值計算:分表索引i的起始值為i * N + 1
  • 適用場景:分表數(shù)量固定的小規(guī)模系統(tǒng)

Java調(diào)用示例

// 根據(jù)訂單ID計算分表索引
int getTableIndex(Long orderId) {
    return (int)(orderId % 10); // 假設(shè)分10個表
}

// 插入訂單
void insertOrder(Order order) {
    int tableIndex = getTableIndex(order.getId());
    String tableName = "t_order_" + tableIndex;
    
    // 動態(tài)拼接SQL
    String sql = "INSERT INTO " + tableName + "(id, order_no) VALUES (?, ?)";
    jdbcTemplate.update(sql, order.getId(), order.getOrderNo());
}

優(yōu)缺點分析

優(yōu)點缺點
實現(xiàn)簡單,無需額外組件分表數(shù)量固定,擴容困難
性能優(yōu)秀,直接利用數(shù)據(jù)庫特性高并發(fā)下單表自增ID可能耗盡
存儲效率高,ID緊湊需手動維護分表配置

二、方案二:UUID全局唯一標識符

核心思想

利用UUID的128位隨機性保證全局唯一性。

實現(xiàn)代碼

-- 創(chuàng)建訂單表(主鍵字段為UUID)
CREATE TABLE t_order (
    id CHAR(36) PRIMARY KEY, -- UUID長度36位
    order_no VARCHAR(50)
);

Java生成UUID

import java.util.UUID;

public class Order {
    private String id = UUID.randomUUID().toString(); // 生成UUID
    private String orderNo;

    // Getter & Setter
}

代碼注解

  • UUID格式xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx
  • 存儲優(yōu)化:可壓縮為16字節(jié)二進制存儲(Base128編碼)

性能優(yōu)化示例

// 壓縮UUID為16字節(jié)
public byte[] compressUuid(String uuid) {
    return UUID.fromString(uuid).toString().getBytes(StandardCharsets.UTF_8);
}

優(yōu)缺點分析

優(yōu)點缺點
完全隨機,無依賴數(shù)據(jù)庫存儲空間大(36字節(jié))
適用于分布式系統(tǒng)B+樹索引性能差(隨機寫入)
無需協(xié)調(diào)生成ID無法直接定位分表

三、方案三:Snowflake算法(Twitter開源)

核心思想

通過時間戳+機器ID+序列號生成64位有序ID。

Java實現(xiàn)代碼

public class SnowflakeIdGenerator {
    private final long twepoch = 1288834974657L; // 起始時間戳(2010-11-04)
    private final long workerIdBits = 5L; // 機器ID位數(shù)
    private final long datacenterIdBits = 5L; // 數(shù)據(jù)中心ID位數(shù)
    private final long sequenceBits = 12L; // 序列號位數(shù)
    
    private final long maxWorkerId = ~(-1L << workerIdBits);
    private final long maxDatacenterId = ~(-1L << datacenterIdBits);
    private final long sequenceMask = ~(-1L << sequenceBits);
    
    private long workerId;
    private long datacenterId;
    private long sequence = 0L;
    private long lastTimestamp = -1L;

    public SnowflakeIdGenerator(long workerId, long datacenterId) {
        if (workerId > maxWorkerId || workerId < 0) {
            throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
        }
        if (datacenterId > maxDatacenterId || datacenterId < 0) {
            throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
        }
        this.workerId = workerId;
        this.datacenterId = datacenterId;
    }

    public synchronized long nextId() {
        long timestamp = timeGen();
        
        if (timestamp < lastTimestamp) {
            throw new RuntimeException(String.format("時鐘回撥: %d ms", lastTimestamp - timestamp));
        }

        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0;
        }

        lastTimestamp = timestamp;
        return (timestamp - twepoch) << (workerIdBits + datacenterIdBits + sequenceBits)
                | (datacenterId << (workerIdBits + sequenceBits))
                | (workerId << sequenceBits)
                | sequence;
    }

    protected long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    protected long timeGen() {
        return System.currentTimeMillis();
    }
}

代碼注解

  • 位運算邏輯
    • 時間戳(41位) → 代表從起始時間到現(xiàn)在的毫秒數(shù)
    • 數(shù)據(jù)中心ID(5位) → 支持32個數(shù)據(jù)中心
    • 機器ID(5位) → 支持32個節(jié)點
    • 序列號(12位) → 毫秒內(nèi)最多支持4096個ID

調(diào)用示例

SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(1, 1);
long orderId = idGenerator.nextId();
System.out.println("生成的ID: " + orderId);

優(yōu)缺點分析

優(yōu)點缺點
全局唯一且有序依賴系統(tǒng)時間(時鐘回撥問題)
支持分布式場景需要預(yù)先分配機器ID
存儲效率高(8字節(jié))最大時間戳限制為69年

四、方案四:Redis原子自增

核心思想

利用Redis的INCR命令生成全局唯一ID。

Redis配置

# 啟動Redis
redis-server

# 設(shè)置初始值
SET order_id 1000

Java調(diào)用示例

import redis.clients.jedis.Jedis;

public class RedisIdGenerator {
    private Jedis jedis = new Jedis("localhost");

    public long generateId() {
        return jedis.incr("order_id"); // 原子自增
    }
}

代碼注解

  • 高可用保障:建議使用Redis集群模式
  • 分片策略:可通過不同Key區(qū)分業(yè)務(wù)類型(如order_iduser_id

集群模式優(yōu)化

// Redis Cluster客戶端配置
JedisCluster jedisCluster = new JedisCluster(new HostAndPort("192.168.1.101", 6379),
                                             new HostAndPort("192.168.1.102", 6379));

優(yōu)缺點分析

優(yōu)點缺點
高性能(每秒百萬級QPS)依賴Redis服務(wù)穩(wěn)定性
支持分布式場景單點故障風險(需集群)
簡單易用需處理網(wǎng)絡(luò)延遲

五、方案五:第三方ID生成服務(wù)

核心思想

使用獨立服務(wù)(如滴滴TinyID)生成ID。

TinyID集成示例

// 1. 添加Maven依賴
<dependency>
    <groupId>com.didi</groupId>
    <artifactId>tinyid-client</artifactId>
    <version>1.0.0</version>
</dependency>

// 2. 配置TinyID
TinyIdClient client = new TinyIdClient("http://tinyid-service.com");

// 3. 生成ID
String businessType = "order";
Long id = client.getId(businessType);

代碼注解

  • TinyID原理:基于數(shù)據(jù)庫的Sequence表生成ID
  • 多租戶支持:通過businessType區(qū)分不同業(yè)務(wù)

TinyID服務(wù)端配置

CREATE TABLE tinyid (
    id BIGINT PRIMARY KEY,
    business_type VARCHAR(50),
    max_id BIGINT,
    step INT,
    version INT
);

優(yōu)缺點分析

優(yōu)點缺點
支持多業(yè)務(wù)類型需維護獨立服務(wù)
高可用性(支持集群)依賴網(wǎng)絡(luò)通信
靈活配置步長學習成本較高

六、方案六:COMB ID(組合ID)

核心思想

時間戳隨機數(shù)組合,生成有序UUID。

Java實現(xiàn)代碼

import java.time.Instant;
import java.util.Random;

public class CombIdGenerator {
    private final Random random = new Random();

    public String generateId() {
        byte[] uuid = new byte[16];
        
        // 前6字節(jié)為時間戳
        long timestamp = Instant.now().toEpochMilli();
        for (int i = 0; i < 6; i++) {
            uuid[i] = (byte)(timestamp >> (8 * (5 - i)));
        }
        
        // 后10字節(jié)為隨機數(shù)
        random.nextBytes(uuid);
        
        return bytesToHex(uuid);
    }

    private String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }
}

代碼注解

  • 時間戳部分:確保ID有序性
  • 隨機部分:避免重復(fù)

優(yōu)缺點分析

優(yōu)點缺點
兼具有序性和隨機性實現(xiàn)復(fù)雜度高
降低B+樹索引碎片依賴時間同步

七、方案七:數(shù)據(jù)庫中間件內(nèi)置策略

ShardingSphere示例

// 1. 配置ShardingSphere
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123

代碼注解

  • 內(nèi)置算法:支持UUID和Snowflake
  • 自定義擴展:可通過接口實現(xiàn)自定義生成器

自定義生成器示例

public class CustomKeyGenerator implements KeyGenerator {
    @Override
    public Comparable<?> generateKey() {
        return new SnowflakeIdGenerator(1, 1).nextId();
    }
}

優(yōu)缺點分析

優(yōu)點缺點
無縫集成ShardingSphere依賴中間件版本
支持多種算法配置復(fù)雜度高

八、方案八:基因法 + Hash分片

核心思想

在ID中嵌入分片基因,直接定位分表。

Java實現(xiàn)代碼

public class ShardIdGenerator {
    private static final int SHARD_COUNT = 8; // 8個分表
    private static final int GEN_BITS = 3; // 3位基因(2^3=8)

    public long generateShardId(long baseId, int shardIndex) {
        // 基因掩碼:0b00000111
        long mask = (1 << GEN_BITS) - 1;
        
        // 清除低3位基因
        long idWithoutGene = baseId & ~mask;
        
        // 設(shè)置新的基因
        return idWithoutGene | (shardIndex & mask);
    }
}

代碼注解

  • 基因提取:通過位運算定位分表索引
  • 適用場景:Hash分片的分庫分表系統(tǒng)

分表查詢示例

long shardId = 1234567890123456789L;
int shardIndex = (int)(shardId & ((1 << 3) - 1)); // 提取低3位
String tableName = "t_order_" + shardIndex;

優(yōu)缺點分析

優(yōu)點缺點
直接定位分表ID修改后需重新計算
無需額外組件分片規(guī)則強依賴基因位

如何選擇最適合你的方案?

方案適用場景推薦指數(shù)
數(shù)據(jù)庫自增+步長小規(guī)模分表???
UUID分布式系統(tǒng)????
Snowflake高并發(fā)系統(tǒng)?????
Redis高性能要求????
TinyID多業(yè)務(wù)場景????
COMB ID有序性優(yōu)先???
ShardingSphere中間件集成????
基因法Hash分片????

最后提醒:選擇主鍵生成方案時,需綜合考慮業(yè)務(wù)規(guī)模、性能需求運維成本。記住:沒有銀彈方案,只有最合適的解決方案!

代碼包結(jié)構(gòu)

MainKeyGenerator/
├── config/
│   └── shard.properties       # 分片配置
├── service/
│   ├── RedisIdService.java    # Redis生成器
│   ├── SnowflakeService.java  # Snowflake實現(xiàn)
│   └── TinyIdService.java     # TinyID客戶端
├── model/
│   └── Order.java             # 訂單模型
└── util/
    └── ShardUtil.java         # 分片工具類

部署建議

  • 生產(chǎn)環(huán)境建議采用SnowflakeTinyID
  • 高并發(fā)場景優(yōu)先使用Redis集群
  • 小規(guī)模系統(tǒng)可使用數(shù)據(jù)庫自增步長

“主鍵ID是分庫分表系統(tǒng)的命脈,選對方案,你的系統(tǒng)才能穩(wěn)如泰山!”

以上就是MySQL分庫分表后主鍵ID生成的八種方案的詳細內(nèi)容,更多關(guān)于MySQL主鍵ID生成方案的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • MySQL超詳細實現(xiàn)用戶管理實例

    MySQL超詳細實現(xiàn)用戶管理實例

    MySQL 是一個多用戶數(shù)據(jù)庫,具有功能強大的訪問控制系統(tǒng),可以為不同用戶指定不同權(quán)限。在前面的章節(jié)中我們使用的是 root 用戶,該用戶是超級管理員,擁有所有權(quán)限,包括創(chuàng)建用戶、刪除用戶和修改用戶密碼等管理權(quán)限
    2022-06-06
  • Windows server 2008 r2上安裝MySQL5.7.10步驟

    Windows server 2008 r2上安裝MySQL5.7.10步驟

    這篇文章主要介紹了Windows server 2008 r2上安裝MySQL5.7.10的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-01-01
  • Mysql數(shù)據(jù)庫表中為什么有索引卻沒有提高查詢速度

    Mysql數(shù)據(jù)庫表中為什么有索引卻沒有提高查詢速度

    你有沒有想起過為什么明明再數(shù)據(jù)庫中有索引,但是查詢速度卻并沒有希望的那樣快?本篇文章將帶給你答案,跟小編一起看看吧
    2022-02-02
  • MySQL中設(shè)置服務(wù)器級別的默認排序規(guī)則的方法

    MySQL中設(shè)置服務(wù)器級別的默認排序規(guī)則的方法

    collation_server?是一個系統(tǒng)變量,它定義了服務(wù)器級別的默認排序規(guī)則,本文主要介紹了MySQL中設(shè)置服務(wù)器級別的默認排序規(guī)則的方法,具有一定的參考價值,感興趣的可以了解一下
    2024-08-08
  • MySQL復(fù)制架構(gòu)的搭建及配置過程

    MySQL復(fù)制架構(gòu)的搭建及配置過程

    這篇文章主要介紹了MySQL復(fù)制架構(gòu)的相關(guān)知識,本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-02-02
  • mysql?8.0.26?安裝配置圖文教程

    mysql?8.0.26?安裝配置圖文教程

    這篇文章主要為大家詳細介紹了mysql?8.0.26?安裝配置圖文教程,文中安裝步驟介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Windows下MySQL定時備份腳本的實現(xiàn)

    Windows下MySQL定時備份腳本的實現(xiàn)

    這篇文章主要介紹了Windows下MySQL定時備份腳本的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • Mysql中varchar類型一些需要注意的地方

    Mysql中varchar類型一些需要注意的地方

    這篇文章主要介紹了Mysql中varchar類型一些需要注意的地方,幫助大家更好的理解和學習MySQL,感興趣的朋友可以了解下
    2021-01-01
  • centos7.4系統(tǒng)中yum源安裝mysql 5.6

    centos7.4系統(tǒng)中yum源安裝mysql 5.6

    本文給大家介紹的是如何在centos7.4系統(tǒng)中通過yum源安裝MySQL 5.6數(shù)據(jù)庫,CentOS7默認數(shù)據(jù)庫是mariadb, 但是 好多用的都是mysql ,但是CentOS7的yum源中默認好像是沒有mysql的,今天我們就來看看具體如何操作
    2018-09-09
  • Linux中查看MySQL服務(wù)是否開啟方式

    Linux中查看MySQL服務(wù)是否開啟方式

    這篇文章主要介紹了Linux中查看MySQL服務(wù)是否開啟方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09

最新評論

南阳市| 凉城县| 靖边县| 宝清县| 永州市| 元谋县| 通海县| 岱山县| 稷山县| 台山市| 浮山县| 淮安市| 安多县| 衢州市| 资阳市| 宁河县| 绩溪县| 十堰市| 华池县| 宜兰市| 昌图县| 肃宁县| 承德市| 孝感市| 江津市| 丽江市| 岑溪市| 江门市| 哈密市| 靖远县| 玉树县| 红河县| 周口市| 奇台县| 太湖县| 如东县| 蒲江县| 若羌县| 平山县| 崇阳县| 洛南县|