搞定了六种分布式ID,分库分表哪个适合做主键?

2024年 4月 18日 194.8k 0

今天咱们继续一起来探究下,分布式ID在分库分表中起到的作用以及如何使用,ShardingSphere-jdbc中已经为我们提供了多种分布式主键ID生成策略。接下来将分别介绍这些策略的优缺点,看看它们在实际应用中的场景和效果。

图片图片

小富技术站:https://xiaofucode.com

为什么用分布式主键ID

在传统的单库单表结构时,通常可以使用自增主键来保证数据的唯一性。但在分库分表的情况下,每个表的默认自增步长为1,这导致了各个库、表之间可能存在重叠的主键范围,从而使得主键字段失去了其唯一性的意义。

为了解决这一问题,我们需要引入专门的分布式 ID 生成器来生成全局唯一的ID,并将其作为每条记录的主键,以确保全局唯一性。通过这种方式,我们能够有效地避免数据冲突和重复插入的问题,从而保障系统的正常运行。

除了满足唯一性的基本要求外,作为主键 ID,我们还需要关注主键字段的数据类型、长度对性能的影响。因为主键字段的数据类型、长度直接影响着数据库的查询效率和整体系统性能表现,这一点也是我们在选方案时需要考虑的因素。

内置算法

在ShardingSphere 5.X版本后进一步丰富了其框架内部的主键生成策略方案。此前仅提供了UUID和Snowflake两种策略,现在又陆续提供了NanoID、CosId、CosId-Snowflake三种策略。下面我们将逐个的过一下。

注意:SQL中不要主动拼接主键字段(包括持久化工具自动拼接的)否则一律走默认的Snowflake策略!!!

ShardingSphere中为分片表设置主键生成策略后,执行插入操作时,会自动在SQL中拼接配置的主键字段和生成的分布式ID值。所以,在创建分片表时主键字段无需再设置 自增 AUTO_INCREMENT。同时,在插入数据时应避免为主键字段赋值,否则会覆盖主键策略生成的ID。

CREATE TABLE `t_order` (
  `id` bigint NOT NULL,
  `order_id` bigint NOT NULL,
  `user_id` bigint NOT NULL,
  `order_number` varchar(255) COLLATE utf8mb4_general_ci NOT NULL,
  `customer_id` bigint NOT NULL,
  `order_date` datetime DEFAULT NULL,
  `interval_value` varchar(125) COLLATE utf8mb4_general_ci DEFAULT NULL,
  `total_amount` decimal(10,2) NOT NULL,
  PRIMARY KEY (`order_id`) USING BTREE
) ;

UUID

想要获得一个具有唯一性的ID,大概率会先想到UUID,因为它不仅具有全球唯一的特性使用还简单。但并不推荐将其作为主键ID。

• UUID的无序性。在插入新行数据后,InnoDB无法像插入有序数据那样直接将新行追加到表尾,而是需要为新行寻找合适的位置来分配空间。由于ID无序,页分裂操作变得不可避免,导致大量数据的移动。频繁的页分裂会导致数据碎片化(即数据在物理存储上分散分布)。这种随机的ID分配过程需要大量的额外操作,导致频繁的对数据进行无序的访问,导致磁盘寻道时间增加。数据的无序性进一步加剧了数据碎片化,降低了数据访问效率。

• UUID字符串类型。字符串比数字类型占用更多的存储空间,对存储和查询性能造成较大的消耗;字符串类型的长度可变,可变长度的数据行会破坏索引的连续性,导致索引查找性能下降。

算法类型:UUID

spring:
  shardingsphere:
    rules:
      sharding:
        key-generators:  # 分布式序列算法配置
          # UUID生成算法
          uu-id-gen:
            type: UUID
        tables:
          t_order:  # 逻辑表名称
            actual-data-nodes: db$->{0..1}.t_order_${0..2} # 数据节点:数据库.分片表
            database-strategy:  # 分库策略
              standard:
                sharding-column: order_id
                sharding-algorithm-name: t_order_database_mod
            table-strategy: # 分表策略
              standard:
                sharding-column: order_id
                sharding-algorithm-name: t_order_table_mod
            key-generate-strategy: # 分布式主键生成策略
              column: id
              keyGeneratorName: uu-id-gen

NanoID

或许很多人都不熟悉 NanoID,它是一款用类似 UUID 生成唯一标识符的轻量级库。不过,与 UUID 不同的是 NanoID 生成的字符串ID长度较短,仅为21位。但仍然不推荐将它作为主键ID,理由和UUID一样。

算法类型:NANOID

spring:
  shardingsphere:
    rules:
      sharding:
        key-generators:  # 分布式序列算法配置
          # nanoid生成算法
          nanoid-gen:
            type: NANOID
        tables:
          t_order:  # 逻辑表名称
            actual-data-nodes: db$->{0..1}.t_order_${0..2} # 数据节点:数据库.分片表
            key-generate-strategy: # 分布式主键生成策略
              column: id
              keyGeneratorName: nanoid-gen

定制雪花算法

雪花算法是比较主流的分布式ID生成方案,在 ShardingSphere 中的Snowflake算法生成的是 Long 类型的 ID,通常作为默认的主键生成策略使用。

内置的雪花算法生成的ID主要由时间戳、工作机器IDworkId、序列号sequence三部分组成。

@Override
  public synchronized Long generateKey() {
      ..........
      return ((currentMilliseconds - EPOCH) {0..1}.t_order_${0..2} # 数据节点:数据库.分片表
            key-generate-strategy: # 分布式主键生成策略
              column: id
              keyGeneratorName: cosId-gen

CosId-Snowflake

CosId-Snowflake 是 CosId 框架内提供的 Snowflake 算法,它的实现原理和上边的定制版雪花算法类似,ID主要也是由时间戳、工作机器ID、序列号sequence三部分组成。同样处理了时钟回拨等问题。

public synchronized long generate() {
long currentTimestamp = this.getCurrentTime();
if (currentTimestamp this.lastTimestamp && this.sequence >= this.sequenceResetThreshold) {
this.sequence = 0L;
}

this.sequence = this.sequence + 1L & this.maxSequence;
if (this.sequence == 0L) {
currentTimestamp = this.nextTime();
}

this.lastTimestamp = currentTimestamp;
long diffTimestamp = currentTimestamp - this.epoch;
if (diffTimestamp > this.maxTimestamp) {
throw new TimestampOverflowException(this.epoch, diffTimestamp, this.maxTimestamp);
} else {
return diffTimestamp

相关文章

Oracle如何使用授予和撤销权限的语法和示例
Awesome Project: 探索 MatrixOrigin 云原生分布式数据库
下载丨66页PDF,云和恩墨技术通讯(2024年7月刊)
社区版oceanbase安装
Oracle 导出CSV工具-sqluldr2
ETL数据集成丨快速将MySQL数据迁移至Doris数据库

发布评论