背景

在软件系统演进过程中,随着业务规模的增长 (TPS/存储容量),我们需要通过集群化部署来分摊计算、存储压力。

应用服务的无状态设计使其具备了伸缩性。在使用 Kubernetes 部署时我们只需要一行命令即可完成服务伸缩

(kubectl scale --replicas=5 deployment/order-service)。

但对于有状态的数据库就不那么容易了,此时数据库变成系统的性能瓶颈是显而易见的。

分库分表

从微服务的角度来理解垂直拆分其实就是微服务拆分。以限界上下文来定义服务边界将大服务/单体应用拆分成多个自治的粒度更小的服务,因为自治性规范要求,数据库也需要进行业务拆分。

但垂直拆分后的单个微服务依然会面临 TPS/存储容量 的挑战,所以这里我们重点讨论水平拆分的方式。

数据库分库分表方案是逻辑统一,物理分区自治的方案。其核心设计在于中间层映射方案的设计 (上图 Mapping),即分片算法的设计。

几乎所有编程语言都内置实现了散列表(java:HashMap/csharp:Dictionary/python:dict/go:map ...)。分片算法跟散列表高度相似(hashCode),都得通过 key/shardingValue 映射到对应的槽位(slot)。

那么 shardingValue 从哪里来呢?CosId!!!

CosId:分布式 ID 生成器

CosId 旨在提供通用、灵活、高性能的分布式 ID 生成器。CosId 目前提供了以下三种算法:

  • SnowflakeId : 单机 TPS 性能:409W/s , 主要解决 时钟回拨问题机器号分配问题 并且提供更加友好、灵活的使用体验。
  • SegmentId: 每次获取一段 (Step) ID,来降低号段分发器的网络IO请求频次提升性能,提供多种存储后端:关系型数据库、RedisZookeeper 供用户选择。
  • SegmentChainId(推荐):SegmentChainId (lock-free) 是对 SegmentId 的增强。性能可达到近似 AtomicLongTPS 性能:12743W+/s

shardingValue 问题解决了,但这就够了吗?ShardingSphere!!!

摘自 CosId 官网:https://github.com/Ahoo-Wang/CosId

ShardingSphere

Apache ShardingSphere 是一款开源分布式数据库生态项目,由 JDBC、Proxy 和 Sidecar(规划中) 3 款产品组成。其核心采用可插拔架构,通过组件扩展功能。对上以数据库协议及 SQL 方式提供诸多增强功能,包括数据分片、访问路由、数据安全等;对下原生支持 MySQL、PostgreSQL、SQL Server、Oracle 等多种数据存储引擎。Apache ShardingSphere 项目理念,是提供数据库增强计算服务平台,进而围绕其上构建生态。充分利用现有数据库的计算与存储能力,通过插件化方式增强其核心能力,为企业解决在数字化转型中面临的诸多使用难点,为加速数字化应用赋能。

摘自 Apache ShardingSphere 官网:https://shardingsphere.apache.org/index_zh.html

接下来进入本文的主要内容:如何基于 ShardingSphere 可插拔架构(SPI)来集成 CosId,以及应用配置指南。

安装

Spring-Boot 应用 为例

  • ShardingSphere v5.1.0+

因为 ShardingSphere v5.1.0 PR,已经合并了 cosid-shardingsphere 模块,所以只需要引用 ShardingSphere 依赖即可。

<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.1</version>
</dependency>
  • ShardingSphere v5.0.0
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.0.0</version>
</dependency>
<dependency>
<groupId>me.ahoo.cosid</groupId>
<artifactId>cosid-shardingsphere</artifactId>
<version>1.8.15</version>
</dependency>

分布式 ID

KeyGenerateAlgorithm

UML Class Diagram

上图展示了目前所有 ShardingSphere 内置的 KeyGenerateAlgorithm 实现,这里我们只讲 CosIdKeyGenerateAlgorithm ,其他实现请阅读https://shardingsphere.apache.org/document/current/cn/features/sharding/concept/key-generator/

CosIdKeyGenerateAlgorithm

配置

type: COSID

名称 数据类型 说明 默认值
id-name String IdGenerator 的名称(在 IdGeneratorProvider 中已注册) __share__
as-string String 是否生成字符串类型的ID fasle
spring:
shardingsphere:
rules:
sharding:
key-generators:
cosid:
type: COSID
props:
id-name: __share__

分片算法

ShardingAlgorithm

UML Class Diagram

CosIdModShardingAlgorithm

CosId取模分片算法

算法说明

单值分片键(PreciseShardingValue)算法复杂度:O(1)

范围值分片键(RangeShardingValue)算法复杂度:O(N),其中N为范围值个数。

性能基准测试

精确值/单值(PreciseShardingValue) 范围值/多值(RangeShardingValue)

配置

type: COSID_MOD

名称 数据类型 说明 默认值
logic-name-prefix String 逻辑表/数据源名前缀
mod int 除数
spring:
shardingsphere:
rules:
sharding:
sharding-algorithms:
alg-name:
type: COSID_MOD
props:
mod: 4
logic-name-prefix: t_table_

CosIdIntervalShardingAlgorithm

基于间隔的时间范围分片算法。

算法说明

精确值/单值分片键(PreciseShardingValue)算法复杂度:O(1)

范围值分片键(RangeShardingValue)算法复杂度:O(N),其中N为范围值单位时间个数。

性能基准测试

精确值/单值(PreciseShardingValue) 范围值/多值(RangeShardingValue)

配置

type: COSID_INTERVAL

名称 数据类型 说明 默认值
logic-name-prefix String 逻辑表/数据源名前缀
datetime-lower String 时间分片下界值,时间戳格式:yyyy-MM-dd HH:mm:ss
datetime-upper String 时间分片上界值,时间戳格式:yyyy-MM-dd HH:mm:ss
sharding-suffix-pattern String 分片真实表/数据源后缀格式
datetime-interval-unit ChronoUnit 分片键时间间隔单位
datetime-interval-amount int 分片键时间间隔
ts-unit String 时间戳单位:SECOND/MILLISECOND MILLISECOND
zone-id String 分片键时区 ZoneId.systemDefault().getId()
spring:
shardingsphere:
rules:
sharding:
sharding-algorithms:
alg-name:
type: COSID_INTERVAL
props:
logic-name-prefix: logic-name-prefix
datetime-lower: 2021-12-08 22:00:00
datetime-upper: 2022-12-01 00:00:00
sharding-suffix-pattern: yyyyMM
datetime-interval-unit: MONTHS
datetime-interval-amount: 1

CosIdSnowflakeIntervalShardingAlgorithm

算法说明

我们知道 SnowflakeId 的位分区方式,SnowflakeId 可以解析出时间戳,即 SnowflakeId 可以作为时间,所以 SnowflakeId 可以作为 INTERVAL 的分片算法的分片值。

(当没有CreateTime可用作分片时[这是一个非常极端的情况],或者对性能有非常极端的要求时, 分布式ID主键 作为查询范围可能是持久层性能更好的选择。 )

配置

type: COSID_INTERVAL_SNOWFLAKE

名称 数据类型 说明 默认值
logic-name-prefix String 逻辑表/数据源名前缀
datetime-lower String 时间分片下界值,时间戳格式:yyyy-MM-dd HH:mm:ss
datetime-upper String 时间分片上界值,时间戳格式:yyyy-MM-dd HH:mm:ss
sharding-suffix-pattern String 分片真实表/数据源后缀格式
datetime-interval-unit ChronoUnit 分片键时间间隔单位
datetime-interval-amount int 分片键时间间隔
id-name String IdGenerator 的名称(在 IdGeneratorProvider 中已注册) __share__
spring:
shardingsphere:
rules:
sharding:
sharding-algorithms:
alg-name:
type: COSID_INTERVAL_SNOWFLAKE
props:
logic-name-prefix: logic-name-prefix
datetime-lower: 2021-12-08 22:00:00
datetime-upper: 2022-12-01 00:00:00
sharding-suffix-pattern: yyyyMM
datetime-interval-unit: MONTHS
datetime-interval-amount: 1
id-name: cosid-name

总结

本文主要讨论了分库分表产生的背景以及如何基于 ShardingSphere 可插拔架构集成 CosId 的应用实战。

ShardingSphere 采用可插拔架构,使得开发者非常方便的自定义满足自身应用场景的功能扩展,如果你也对参与 ShardingSphere 社区贡献感兴趣请参考 https://shardingsphere.apache.org/community/cn/contribute/contributor/

阅读源码的小技巧之类图

相信很多小伙伴在阅读源码过程中总是难以自拔的遍历式以方法为单位一行行查看源码的实现细节,以至于迷失在细节中(如果你还能坚持下来,那真是佩服你的毅力之坚韧!)。这样的阅读方式是非常糟糕的、低效的。

阅读源码跟阅读书籍一样有非常多的相似之处:先建立一个概览图(索引),然后再逐层往下精进。(自上而下的方式更有利于阅读过程中不迷失在具体细节中)

推荐大家使用IDEA的插件 Diagrams 用于生成源码级别的概览图:UML类图。

引用说明

ShardingSphere 集成 CosId 实战的更多相关文章

  1. Jenkins持续集成企业实战系列之Jenkins插件下载及邮件配置-----05

    注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.    最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...

  2. Jenkins持续集成企业实战系列之Jenkins手动构建-----04

    注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.    最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...

  3. Jenkins持续集成企业实战系列之Jenkins配置演示-----03

    注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.    最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...

  4. Jenkins持续集成企业实战系列之Jenkins持续集成简介及安装-----02

    1.      Jenkins持续集成简介 注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.    最初接触Jenkins也是由于公司需求, ...

  5. Jenkins持续集成企业实战系列之两种网站部署的流程-----01

    注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.    最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...

  6. Jenkins持续集成企业实战

    阅读目录: Jenkins持续集成企业实战1.1 目前主流网站部署的流程1.2 Jenkins持续集成简介1.3 Jenkins持续集成组件1.4 Jenkins平台安装部署1.5 Jenkins相关 ...

  7. Spring Boot 集成 RabbitMQ 实战

    Spring Boot 集成 RabbitMQ 实战 特别说明: 本文主要参考了程序员 DD 的博客文章<Spring Boot中使用RabbitMQ>,在此向原作者表示感谢. Mac 上 ...

  8. go-micro集成RabbitMQ实战和原理

    在go-micro中异步消息的收发是通过Broker这个组件来完成的,底层实现有RabbitMQ.Kafka.Redis等等很多种方式,这篇文章主要介绍go-micro使用RabbitMQ收发数据的方 ...

  9. Java SpringBoot集成RabbitMq实战和总结

    目录 交换器.队列.绑定的声明 关于消息序列化 同一个队列多消费类型 注解将消息和消息头注入消费者方法 关于消费者确认 关于发送者确认模式 消费消息.死信队列和RetryTemplate RPC模式的 ...

随机推荐

  1. synchronized 的作用?

    在 Java 中,synchronized 关键字是用来控制线程同步的,就是在多线程的环境 下,控制 synchronized 代码段不被多个线程同时执行. synchronized 既可以加在一段代 ...

  2. centos 7环境下安装部署zookeeper

    近一直在看zookeeper的知识,有所收获,打算写些一些关于zookeeper的博客,也当做是自己的复习和笔记. 在上一篇 博客中简单地介绍了centos 7 下如何安装jdk,这一篇将介绍如何在c ...

  3. ctfhub web信息泄露备份文件下载(网站源码,back文件)

    网站源码 进入环境,首先我们用bp抓一下包 在HTTP请求方式GET/后添加两个负载,一个用于爆破文件名,一个用于爆破后缀名 得知网页源码的备份形式为www.zip,下载网页源码 打开记事本文件 发现 ...

  4. 攻防世界baby_web

    baby_web 题目提示想想初始页,但我们一访问就会跳转到1.php我们使用bp抓包分析,我们发送到repeater模块修改请求访问1.php内容看看 发现flag隐藏了我们去hex中看看 这样我们 ...

  5. 编译器如何处理C++不同类中同名函数(参数类型个数都相同)

    转载请注明出处,版权归作者所有 lyzaily@126.com yanzhong.lee 作者按: 从这篇文章中,我们主要会认识到一下几点: 一.不类中的特征标相同的同名函数,它们是不同的函数,原因就 ...

  6. C++ | 虚拟地址空间

    在 x86 32位系统下,进程的虚拟地址空间为 232 (4G)大小,其中在windows系统下4G地址空间中0x00000000-0x7FFFFFFF 是用户地址空间,0x80000000-0xFF ...

  7. 关于 video 播放的新探索

    前端同学要使用 HTML5 播放器视频,必然会使用 video 标签,不过大多数同学只是使用了较简单的功能,其实它本身拥有不凡之力有待我们发现. 首先,我们先来看下 video 最基础的用法: 使用 ...

  8. ES6-11学习笔记--数组遍历

    ES5中数组遍历方式: for循环 forEach():没有返回值,只是针对每个元素调用func map():返回新的Array,每个元素为调用func的结果 filter():返回符合func条件的 ...

  9. webpack的安装 以及 问题 以及 作用

    参考链接: https://blog.csdn.net/Rnger/article/details/81086938     https://blog.csdn.net/qq_38111015/art ...

  10. 学习Java必用的9个网站,最后一个最好用!

    Java语言已经成为IT编程界中一种持久的语言,从主要开放源码网站中统计的每月编程语言排名来看,Java一直位居榜首.因此,我们的程序员不能放弃学习Java呀!今日小编为大家整理了几个关于Java学习 ...