日日操夜夜添-日日操影院-日日草夜夜操-日日干干-精品一区二区三区波多野结衣-精品一区二区三区高清免费不卡

公告:魔扣目錄網(wǎng)為廣大站長(zhǎng)提供免費(fèi)收錄網(wǎng)站服務(wù),提交前請(qǐng)做好本站友鏈:【 網(wǎng)站目錄:http://www.ylptlb.cn 】, 免友鏈快審服務(wù)(50元/站),

點(diǎn)擊這里在線咨詢客服
新站提交
  • 網(wǎng)站:51998
  • 待審:31
  • 小程序:12
  • 文章:1030137
  • 會(huì)員:747

《sharding-jdbc 分庫(kù)分表的 4種分片策略》 中我們介紹了 sharding-jdbc 4種分片策略的使用場(chǎng)景,可以滿足基礎(chǔ)的分片功能開(kāi)發(fā),這篇我們來(lái)看看分庫(kù)分表后,應(yīng)該如何為分片表生成全局唯一的主鍵 ID。

引入任何一種技術(shù)都是存在風(fēng)險(xiǎn)的,分庫(kù)分表當(dāng)然也不例外,除非庫(kù)、表數(shù)據(jù)量持續(xù)增加,大到一定程度,以至于現(xiàn)有高可用架構(gòu)已無(wú)法支撐,否則不建議大家做分庫(kù)分表,因?yàn)樽隽藬?shù)據(jù)分片后,你會(huì)發(fā)現(xiàn)自己踏上了一段踩坑之路,而分布式主鍵 ID 就是遇到的第一個(gè)坑。

不同數(shù)據(jù)節(jié)點(diǎn)間生成全局唯一主鍵是個(gè)棘手的問(wèn)題,一張邏輯表 t_order 拆分成多個(gè)真實(shí)表 t_order_n,然后被分散到不同分片庫(kù) db_0、db_1... ,各真實(shí)表的自增鍵由于無(wú)法互相感知從而會(huì)產(chǎn)生重復(fù)主鍵,此時(shí)數(shù)據(jù)庫(kù)本身的自增主鍵,就無(wú)法滿足分庫(kù)分表對(duì)主鍵全局唯一的要求。

 db_0--
    |-- t_order_0
    |-- t_order_1
    |-- t_order_2
 db_1--
    |-- t_order_0
    |-- t_order_1
    |-- t_order_2

盡管我們可以通過(guò)嚴(yán)格約束,各個(gè)分片表自增主鍵的 初始值 和 步長(zhǎng) 的方式來(lái)解決 ID 重復(fù)的問(wèn)題,但這樣會(huì)讓運(yùn)維成本陡增,而且可擴(kuò)展性極差,一旦要擴(kuò)容分片表數(shù)量,原表數(shù)據(jù)變動(dòng)比較大,所以這種方式不太可取。

 步長(zhǎng) step = 分表張數(shù)

 db_0--
    |-- t_order_0  ID: 0、6、12、18...
    |-- t_order_1  ID: 1、7、13、19...
    |-- t_order_2  ID: 2、8、14、20...
 db_1--
    |-- t_order_0  ID: 3、9、15、21...
    |-- t_order_1  ID: 4、10、16、22...
    |-- t_order_2  ID: 5、11、17、23...

目前已經(jīng)有了許多第三方解決方案可以完美解決這個(gè)問(wèn)題,比如基于 UUID、SNOWFLAKE算法 、segment號(hào)段,使用特定算法生成不重復(fù)鍵,或者直接引用主鍵生成服務(wù),像美團(tuán)(Leaf)和 滴滴(TinyId)等。

而sharding-jdbc 內(nèi)置了兩種分布式主鍵生成方案,UUID、SNOWFLAKE,不僅如此它還抽離出分布式主鍵生成器的接口,以便于開(kāi)發(fā)者實(shí)現(xiàn)自定義的主鍵生成器,后續(xù)我們會(huì)在自定義的生成器中接入 滴滴(TinyId)的主鍵生成服務(wù)。

前邊介紹過(guò)在 sharding-jdbc 中要想為某個(gè)字段自動(dòng)生成主鍵 ID,只需要在 Application.properties 文件中做如下配置:

# 主鍵字段
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
# 主鍵ID 生成方案
spring.shardingsphere.sharding.tables.t_order.key-generator.type=UUID
# 工作機(jī)器 id
spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=123

key-generator.column 表示主鍵字段,key-generator.type 為主鍵 ID 生成方案(內(nèi)置或自定義的),key-generator.props.worker.id 為機(jī)器ID,在主鍵生成方案設(shè)為 SNOWFLAKE 時(shí)機(jī)器ID 會(huì)參與位運(yùn)算。

在使用 sharding-jdbc 分布式主鍵時(shí)需要注意兩點(diǎn):

  • 一旦 insert 插入操作的實(shí)體對(duì)象中主鍵字段已經(jīng)賦值,那么即使配置了主鍵生成方案也會(huì)失效,最后SQL 執(zhí)行的數(shù)據(jù)會(huì)以賦的值為準(zhǔn)。
  • 不要給主鍵字段設(shè)置自增屬性,否則主鍵ID 會(huì)以默認(rèn)的 SNOWFLAKE 方式生成。比如:用 mybatis plus 的 @TableId 注解給字段 order_id 設(shè)置了自增主鍵,那么此時(shí)配置哪種方案,總是按雪花算法生成。

下面我們從源碼上分析下 sharding-jdbc 內(nèi)置主鍵生成方案 UUID、SNOWFLAKE 是怎么實(shí)現(xiàn)的。

UUID

打開(kāi) UUID 類型的主鍵生成實(shí)現(xiàn)類 UUIDShardingKeyGenerator 的源碼發(fā)現(xiàn),它的生成規(guī)則只有 UUID.randomUUID() 這么一行代碼,額~ 心中默默來(lái)了一句XX。

UUID 雖然可以做到全局唯一性,但還是不推薦使用它作為主鍵,因?yàn)槲覀兊膶?shí)際業(yè)務(wù)中不管是 user_id 還是 order_id 主鍵多為整型,而 UUID 生成的是個(gè) 32 位的字符串。

它的存儲(chǔ)以及查詢對(duì) MySQL 的性能消耗較大,而且 MySQL 官方也明確建議,主鍵要盡量越短越好,作為數(shù)據(jù)庫(kù)主鍵 UUID 的無(wú)序性還會(huì)導(dǎo)致數(shù)據(jù)位置頻繁變動(dòng),嚴(yán)重影響性能。

public final class UUIDShardingKeyGenerator implements ShardingKeyGenerator {
    private Properties properties = new Properties();

    public UUIDShardingKeyGenerator() {
    }

    public String getType() {
        return "UUID";
    }

    public synchronized Comparable<?> generateKey() {
        return UUID.randomUUID().toString().replaceAll("-", "");
    }

    public Properties getProperties() {
        return this.properties;
    }

    public void setProperties(Properties properties) {
        this.properties = properties;
    }
}

SNOWFLAKE

SNOWFLAKE(雪花算法)是默認(rèn)使用的主鍵生成方案,生成一個(gè) 64bit的長(zhǎng)整型(Long)數(shù)據(jù)。

sharding-jdbc 中雪花算法生成的主鍵主要由 4部分組成,1bit符號(hào)位、41bit時(shí)間戳位、10bit工作進(jìn)程位以及 12bit 序列號(hào)位。

分庫(kù)分表的 9種分布式主鍵ID 生成方案,挺全乎的

 

雪花算法ID組成

符號(hào)位(1bit位)

JAVA 中 Long 型的最高位是符號(hào)位,正數(shù)是0,負(fù)數(shù)是1,一般生成ID都為正數(shù),所以默認(rèn)為0

時(shí)間戳位(41bit)

41位的時(shí)間戳可以容納的毫秒數(shù)是 2 的 41次冪,而一年的總毫秒數(shù)為 1000L * 60 * 60 * 24 * 365,計(jì)算使用時(shí)間大概是69年,額~,我有生之間算是夠用了。

Math.pow(2, 41) / (365 * 24 * 60 * 60 * 1000L) = = 69年 

工作進(jìn)程位(10bit)

表示一個(gè)唯一的工作進(jìn)程id,默認(rèn)值為 0,可通過(guò) key-generator.props.worker.id 屬性設(shè)置。

spring.shardingsphere.sharding.tables.t_order.key-generator.props.worker.id=0000

序列號(hào)位(12bit)

同一毫秒內(nèi)生成不同的ID。

時(shí)鐘回?fù)?/strong>

了解了雪花算法的主鍵 ID 組成后不難發(fā)現(xiàn),這是一種嚴(yán)重依賴于服務(wù)器時(shí)間的算法,而依賴服務(wù)器時(shí)間的就會(huì)遇到一個(gè)棘手的問(wèn)題:時(shí)鐘回?fù)堋?/p>

為什么會(huì)出現(xiàn)時(shí)鐘回?fù)苣兀?/strong>

互聯(lián)網(wǎng)中有一種網(wǎng)絡(luò)時(shí)間協(xié)議 ntp 全稱 (Network Time Protocol) ,專門用來(lái)同步、校準(zhǔn)網(wǎng)絡(luò)中各個(gè)計(jì)算機(jī)的時(shí)間。

這就是為什么,我們的手機(jī)現(xiàn)在不用手動(dòng)校對(duì)時(shí)間,可每個(gè)人的手機(jī)時(shí)間還都是一樣的。

我們的硬件時(shí)鐘可能會(huì)因?yàn)楦鞣N原因變得不準(zhǔn)( 快了 或 慢了 ),此時(shí)就需要 ntp 服務(wù)來(lái)做時(shí)間校準(zhǔn),做校準(zhǔn)的時(shí)候就會(huì)發(fā)生服務(wù)器時(shí)鐘的 跳躍 或者 回?fù)?的問(wèn)題。

雪花算法如何解決時(shí)鐘回?fù)?/strong>

服務(wù)器時(shí)鐘回?fù)軙?huì)導(dǎo)致產(chǎn)生重復(fù)的 ID,SNOWFLAKE 方案中對(duì)原有雪花算法做了改進(jìn),增加了一個(gè)最大容忍的時(shí)鐘回?fù)芎撩霐?shù)。

如果時(shí)鐘回?fù)艿臅r(shí)間超過(guò)最大容忍的毫秒數(shù)閾值,則程序直接報(bào)錯(cuò);如果在可容忍的范圍內(nèi),默認(rèn)分布式主鍵生成器,會(huì)等待時(shí)鐘同步到最后一次主鍵生成的時(shí)間后再繼續(xù)工作。

最大容忍的時(shí)鐘回?fù)芎撩霐?shù),默認(rèn)值為 0,可通過(guò)屬性 max.tolerate.time.difference.milliseconds 設(shè)置。

# 最大容忍的時(shí)鐘回?fù)芎撩霐?shù)
spring.shardingsphere.sharding.tables.t_order.key-generator.max.tolerate.time.difference.milliseconds=5

下面是看下它的源碼實(shí)現(xiàn)類 SnowflakeShardingKeyGenerator,核心流程大概如下:

最后一次生成主鍵的時(shí)間 lastMilliseconds 與 當(dāng)前時(shí)間currentMilliseconds 做比較,如果 lastMilliseconds > currentMilliseconds則意味著時(shí)鐘回調(diào)了。

那么接著判斷兩個(gè)時(shí)間的差值(timeDifferenceMilliseconds)是否在設(shè)置的最大容忍時(shí)間閾值 max.tolerate.time.difference.milliseconds內(nèi),在閾值內(nèi)則線程休眠差值時(shí)間 Thread.sleep(timeDifferenceMilliseconds),否則大于差值直接報(bào)異常。

 
/**
 * @author xiaofu
 */
public final class SnowflakeShardingKeyGenerator implements ShardingKeyGenerator{
    @Getter
    @Setter
    private Properties properties = new Properties();
    
    public String getType() {
        return "SNOWFLAKE";
    }
    
    public synchronized Comparable<?> generateKey() {
     /**
      * 當(dāng)前系統(tǒng)時(shí)間毫秒數(shù) 
      */ 
        long currentMilliseconds = timeService.getCurrentMillis();
        /**
         * 判斷是否需要等待容忍時(shí)間差,如果需要,則等待時(shí)間差過(guò)去,然后再獲取當(dāng)前系統(tǒng)時(shí)間 
         */ 
        if (waitTolerateTimeDifferenceIfNeed(currentMilliseconds)) {
            currentMilliseconds = timeService.getCurrentMillis();
        }
        /**
         * 如果最后一次毫秒與 當(dāng)前系統(tǒng)時(shí)間毫秒相同,即還在同一毫秒內(nèi) 
         */
        if (lastMilliseconds == currentMilliseconds) {
         /**
          * &位與運(yùn)算符:兩個(gè)數(shù)都轉(zhuǎn)為二進(jìn)制,如果相對(duì)應(yīng)位都是1,則結(jié)果為1,否則為0
          * 當(dāng)序列為4095時(shí),4095+1后的新序列與掩碼進(jìn)行位與運(yùn)算結(jié)果是0
          * 當(dāng)序列為其他值時(shí),位與運(yùn)算結(jié)果都不會(huì)是0
          * 即本毫秒的序列已經(jīng)用到最大值4096,此時(shí)要取下一個(gè)毫秒時(shí)間值
          */
            if (0L == (sequence = (sequence + 1) & SEQUENCE_MASK)) {
                currentMilliseconds = waitUntilNextTime(currentMilliseconds);
            }
        } else {
         /**
          * 上一毫秒已經(jīng)過(guò)去,把序列值重置為1 
          */
            vibrateSequenceOffset();
            sequence = sequenceOffset;
        }
        lastMilliseconds = currentMilliseconds;
        
        /**
         * XX......XX XX000000 00000000 00000000 時(shí)間差 XX
         *    XXXXXX XXXX0000 00000000 機(jī)器ID XX
         *               XXXX XXXXXXXX 序列號(hào) XX
         *  三部分進(jìn)行|位或運(yùn)算:如果相對(duì)應(yīng)位都是0,則結(jié)果為0,否則為1
         */
        return ((currentMilliseconds - EPOCH) << TIMESTAMP_LEFT_SHIFT_BITS) | (getWorkerId() << WORKER_ID_LEFT_SHIFT_BITS) | sequence;
    }
    
    /**
     * 判斷是否需要等待容忍時(shí)間差
     */
    @SneakyThrows
    private boolean waitTolerateTimeDifferenceIfNeed(final long currentMilliseconds) {
     /**
      * 如果獲取ID時(shí)的最后一次時(shí)間毫秒數(shù)小于等于當(dāng)前系統(tǒng)時(shí)間毫秒數(shù),屬于正常情況,則不需要等待 
      */
        if (lastMilliseconds <= currentMilliseconds) {
            return false;
        }
        /**
         * ===>時(shí)鐘回?fù)艿那闆r(生成序列的時(shí)間大于當(dāng)前系統(tǒng)的時(shí)間),需要等待時(shí)間差 
         */
        /**
         * 獲取ID時(shí)的最后一次毫秒數(shù)減去當(dāng)前系統(tǒng)時(shí)間毫秒數(shù)的時(shí)間差 
         */
        long timeDifferenceMilliseconds = lastMilliseconds - currentMilliseconds;
        /**
         * 時(shí)間差小于最大容忍時(shí)間差,即當(dāng)前還在時(shí)鐘回?fù)艿臅r(shí)間差之內(nèi) 
         */
        Preconditions.checkState(timeDifferenceMilliseconds < getMaxTolerateTimeDifferenceMilliseconds(), 
                "Clock is moving backwards, last time is %d milliseconds, current time is %d milliseconds", lastMilliseconds, currentMilliseconds);
        /**
         * 線程休眠時(shí)間差 
         */
        Thread.sleep(timeDifferenceMilliseconds);
        return true;
    }
    
    // 配置的機(jī)器ID
    private long getWorkerId() {
        long result = Long.valueOf(properties.getProperty("worker.id", String.valueOf(WORKER_ID)));
        Preconditions.checkArgument(result >= 0L && result < WORKER_ID_MAX_VALUE);
        return result;
    }
    
    private int getMaxTolerateTimeDifferenceMilliseconds() {
        return Integer.valueOf(properties.getProperty("max.tolerate.time.difference.milliseconds", String.valueOf(MAX_TOLERATE_TIME_DIFFERENCE_MILLISECONDS)));
    }
    
    private long waitUntilNextTime(final long lastTime) {
        long result = timeService.getCurrentMillis();
        while (result <= lastTime) {
            result = timeService.getCurrentMillis();
        }
        return result;
    }
}

但從 SNOWFLAKE 方案生成的主鍵ID 來(lái)看,order_id 它是一個(gè)18位的長(zhǎng)整型數(shù)字,是不是發(fā)現(xiàn)它太長(zhǎng)了,想要 MySQL 那種從 0 遞增的自增主鍵該怎么實(shí)現(xiàn)呢?別急,后邊已經(jīng)會(huì)給出了解決辦法!

分庫(kù)分表的 9種分布式主鍵ID 生成方案,挺全乎的

 

SNOWFLAKE 主鍵ID

自定義

sharding-jdbc 利用 SPI 全稱( Service Provider Interface) 機(jī)制拓展主鍵生成規(guī)則,這是一種服務(wù)發(fā)現(xiàn)機(jī)制,通過(guò)掃描項(xiàng)目路徑 META-INF/services 下的文件,并自動(dòng)加載文件里所定義的類。

實(shí)現(xiàn)自定義主鍵生成器其實(shí)比較簡(jiǎn)單,只有兩步。

第一步,實(shí)現(xiàn) ShardingKeyGenerator 接口,并重寫其內(nèi)部方法,其中 getType() 方法為自定義的主鍵生產(chǎn)方案類型、generateKey() 方法則是具體生成主鍵的規(guī)則。

下面代碼中用 AtomicInteger 來(lái)模擬實(shí)現(xiàn)一個(gè)有序自增的 ID 生成。

/**
 * @Author: xiaofu
 * @Description: 自定義主鍵生成器
 */
@Component
public class MyShardingKeyGenerator implements ShardingKeyGenerator {


    private final AtomicInteger count = new AtomicInteger();

    /**
     * 自定義的生成方案類型
     */
    @Override
    public String getType() {
        return "XXX";
    }

    /**
     * 核心方法-生成主鍵ID
     */
    @Override
    public Comparable<?> generateKey() {
        return count.incrementAndGet();
    }

    @Override
    public Properties getProperties() {
        return null;
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

第二步,由于是利用 SPI 機(jī)制實(shí)現(xiàn)功能拓展,我們要在 META-INF/services 文件中配置自定義的主鍵生成器類路徑。

com.xiaofu.sharding.key.MyShardingKeyGenerator
分庫(kù)分表的 9種分布式主鍵ID 生成方案,挺全乎的

 

自定義主鍵 SPI 配置

上面這些弄完我們測(cè)試一下,配置定義好的主鍵生成類型 XXX,并插入幾條數(shù)據(jù)看看效果。

spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
spring.shardingsphere.sharding.tables.t_order.key-generator.type=XXX

通過(guò)控制臺(tái)的SQL 解析日志發(fā)現(xiàn),order_id 字段已按照有序自增的方式插入記錄,說(shuō)明配置的沒(méi)問(wèn)題。

分庫(kù)分表的 9種分布式主鍵ID 生成方案,挺全乎的

 

舉一反九

既然可以自定義生成方案,那么實(shí)現(xiàn)分布式主鍵的思路就很多了,又想到之前我寫的這篇 《9種 分布式ID生成方案》,發(fā)現(xiàn)可以完美兼容,這里挑選其中的 滴滴(Tinyid)來(lái)實(shí)踐一下,由于它是個(gè)單獨(dú)的分布式ID生成服務(wù),所以要先搭建環(huán)境了。

Tinyid 的服務(wù)提供Http 和 Tinyid-client 兩種接入方式,下邊使用 Tinyid-client 方式快速使用,更多的細(xì)節(jié)到這篇文章里看吧,實(shí)在是介紹過(guò)太多次了。

Tinyid 服務(wù)搭建

先拉源代碼 https://github.com/didi/tinyid.git。

由于是基于號(hào)段模式實(shí)現(xiàn)的分布式ID,所以依賴于數(shù)據(jù)庫(kù),要?jiǎng)?chuàng)建相應(yīng)的表 tiny_id_info 、tiny_id_token 并插入默認(rèn)數(shù)據(jù)。


CREATE TABLE `tiny_id_info` (
 `id` BIGINT (20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增主鍵',
 `biz_type` VARCHAR (63) NOT NULL DEFAULT '' COMMENT '業(yè)務(wù)類型,唯一',
 `begin_id` BIGINT (20) NOT NULL DEFAULT '0' COMMENT '開(kāi)始id,僅記錄初始值,無(wú)其他含義。初始化時(shí)begin_id和max_id應(yīng)相同',
 `max_id` BIGINT (20) NOT NULL DEFAULT '0' COMMENT '當(dāng)前最大id',
 `step` INT (11) DEFAULT '0' COMMENT '步長(zhǎng)',
 `delta` INT (11) NOT NULL DEFAULT '1' COMMENT '每次id增量',
 `remainder` INT (11) NOT NULL DEFAULT '0' COMMENT '余數(shù)',
 `create_time` TIMESTAMP NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '創(chuàng)建時(shí)間',
 `update_time` TIMESTAMP NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新時(shí)間',
 `version` BIGINT (20) NOT NULL DEFAULT '0' COMMENT '版本號(hào)',
 PRIMARY KEY (`id`),
 UNIQUE KEY `uniq_biz_type` (`biz_type`)
) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 COMMENT 'id信息表';

CREATE TABLE `tiny_id_token` (
 `id` INT (11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增id',
 `token` VARCHAR (255) NOT NULL DEFAULT '' COMMENT 'token',
 `biz_type` VARCHAR (63) NOT NULL DEFAULT '' COMMENT '此token可訪問(wèn)的業(yè)務(wù)類型標(biāo)識(shí)',
 `remark` VARCHAR (255) NOT NULL DEFAULT '' COMMENT '備注',
 `create_time` TIMESTAMP NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '創(chuàng)建時(shí)間',
 `update_time` TIMESTAMP NOT NULL DEFAULT '2010-01-01 00:00:00' COMMENT '更新時(shí)間',
 PRIMARY KEY (`id`)
) ENGINE = INNODB AUTO_INCREMENT = 1 DEFAULT CHARSET = utf8 COMMENT 'token信息表';

INSERT INTO `tiny_id_token` (`id`, `token`, `biz_type`, `remark`, `create_time`, `update_time`) VALUES ('1', '0f673adf80504e2eaa552f5d791b644c', 'order', '1', '2017-12-14 16:36:46', '2017-12-14 16:36:48');

INSERT INTO `tiny_id_info` (`id`, `biz_type`, `begin_id`, `max_id`, `step`, `delta`, `remainder`, `create_time`, `update_time`, `version`) VALUES ('1', 'order', '1', '1', '100000', '1', '0', '2018-07-21 23:52:58', '2018-07-22 23:19:27', '1');

并在 Tinyid 服務(wù)中配置上邊表所在數(shù)據(jù)源信息

datasource.tinyid.primary.url=jdbc:mysql://47.93.6.e:3306/ds-0?autoReconnect=true&useUnicode=true&characterEncoding=UTF-8
datasource.tinyid.primary.username=root
datasource.tinyid.primary.password=root

最后項(xiàng)目 maven install ,右鍵 TinyIdServerApplication 啟動(dòng)服務(wù), Tinyid 分布式ID生成服務(wù)就搭建完畢了。

自定義 Tinyid 主鍵類型

Tinyid 服務(wù)搭建完下邊在項(xiàng)目中引入它,新建個(gè) tinyid_client.properties 文件其中添加 tinyid.server 和 tinyid.token 屬性,token 為之前 SQL 預(yù)先插入的用戶數(shù)據(jù)。

# tinyid 分布式ID
# 服務(wù)地址
tinyid.server=127.0.0.1:9999
# 業(yè)務(wù)token
tinyid.token=0f673adf80504e2eaa552f5d791b644c

代碼中獲取 ID更簡(jiǎn)單,只需一行代碼,業(yè)務(wù)類型 order 是之前 SQ L 預(yù)先插入的數(shù)據(jù)。

Long id = TinyId.nextId("order");

我們開(kāi)始自定義 Tinyid 主鍵生成類型的實(shí)現(xiàn)類 TinyIdShardingKeyGenerator 。

/**
 * @Author: xiaofu
 * @Description: 自定義主鍵生成器
 */
@Component
public class TinyIdShardingKeyGenerator implements ShardingKeyGenerator {
    
    /**
     * 自定義的生成方案類型
     */
    @Override
    public String getType() {
        return "tinyid";
    }

    /**
     * 核心方法-生成主鍵ID
     */
    @Override
    public Comparable<?> generateKey() {
        
        Long id = TinyId.nextId("order");
        
        return id;
    }

    @Override
    public Properties getProperties() {
        return null;
    }

    @Override
    public void setProperties(Properties properties) {

    }
}

并在配置文件中啟用 Tinyid 主鍵生成類型,到此配置完畢,趕緊測(cè)試一下。

# 主鍵字段
spring.shardingsphere.sharding.tables.t_order.key-generator.column=order_id
# 主鍵ID 生成方案
spring.shardingsphere.sharding.tables.t_order.key-generator.type=tinyid

測(cè)試 Tinyid 主鍵

向數(shù)據(jù)庫(kù)插入訂單記錄測(cè)試發(fā)現(xiàn),主鍵ID字段 order_id 已經(jīng)為趨勢(shì)遞增的了, Tinyid 服務(wù)成功接入,完美!

分庫(kù)分表的 9種分布式主鍵ID 生成方案,挺全乎的

 

在這里插入圖片描述

總結(jié)

后續(xù)的八種生成方式大家參考 《9種 分布式ID生成方案》 按需接入吧,整體比較簡(jiǎn)單這里就不依次實(shí)現(xiàn)了。

 

案例 GitHub 地址:https://github.com/chengxy-nds/Springboot-Notebook/tree/master/springboot-sharding-jdbc

分享到:
標(biāo)簽:分庫(kù)分表
用戶無(wú)頭像

網(wǎng)友整理

注冊(cè)時(shí)間:

網(wǎng)站:5 個(gè)   小程序:0 個(gè)  文章:12 篇

  • 51998

    網(wǎng)站

  • 12

    小程序

  • 1030137

    文章

  • 747

    會(huì)員

趕快注冊(cè)賬號(hào),推廣您的網(wǎng)站吧!
最新入駐小程序

數(shù)獨(dú)大挑戰(zhàn)2018-06-03

數(shù)獨(dú)一種數(shù)學(xué)游戲,玩家需要根據(jù)9

答題星2018-06-03

您可以通過(guò)答題星輕松地創(chuàng)建試卷

全階人生考試2018-06-03

各種考試題,題庫(kù),初中,高中,大學(xué)四六

運(yùn)動(dòng)步數(shù)有氧達(dá)人2018-06-03

記錄運(yùn)動(dòng)步數(shù),積累氧氣值。還可偷

每日養(yǎng)生app2018-06-03

每日養(yǎng)生,天天健康

體育訓(xùn)練成績(jī)?cè)u(píng)定2018-06-03

通用課目體育訓(xùn)練成績(jī)?cè)u(píng)定