ShardingSphere 集成 CosId 实战

背景
在软件系统演进过程中,随着业务规模的增长 (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请求频次提升性能,提供多种存储后端:关系型数据库、Redis、Zookeeper 供用户选择。SegmentChainId(推荐):SegmentChainId(lock-free) 是对SegmentId的增强。性能可达到近似AtomicLong的 TPS 性能: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.0PR,已经合并了 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类图。
- IntelliJ IDEA: https://www.jetbrains.com/help/idea/class-diagram.html
引用说明
- ShardingSphere 官方文档:https://shardingsphere.apache.org/document/current/cn/overview/
- IntelliJ IDEA: https://www.jetbrains.com/help/idea/class-diagram.html
- CosId-ShardingSphere: https://cosid.ahoo.me/guide/cosid-shardingsphere.html
ShardingSphere 集成 CosId 实战的更多相关文章
- Jenkins持续集成企业实战系列之Jenkins插件下载及邮件配置-----05
注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任. 最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...
- Jenkins持续集成企业实战系列之Jenkins手动构建-----04
注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任. 最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...
- Jenkins持续集成企业实战系列之Jenkins配置演示-----03
注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任. 最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...
- Jenkins持续集成企业实战系列之Jenkins持续集成简介及安装-----02
1. Jenkins持续集成简介 注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任. 最初接触Jenkins也是由于公司需求, ...
- Jenkins持续集成企业实战系列之两种网站部署的流程-----01
注:原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任. 最初接触Jenkins也是由于公司需求,根据公司需求Java代码项目升级的.(公司是 ...
- Jenkins持续集成企业实战
阅读目录: Jenkins持续集成企业实战1.1 目前主流网站部署的流程1.2 Jenkins持续集成简介1.3 Jenkins持续集成组件1.4 Jenkins平台安装部署1.5 Jenkins相关 ...
- Spring Boot 集成 RabbitMQ 实战
Spring Boot 集成 RabbitMQ 实战 特别说明: 本文主要参考了程序员 DD 的博客文章<Spring Boot中使用RabbitMQ>,在此向原作者表示感谢. Mac 上 ...
- go-micro集成RabbitMQ实战和原理
在go-micro中异步消息的收发是通过Broker这个组件来完成的,底层实现有RabbitMQ.Kafka.Redis等等很多种方式,这篇文章主要介绍go-micro使用RabbitMQ收发数据的方 ...
- Java SpringBoot集成RabbitMq实战和总结
目录 交换器.队列.绑定的声明 关于消息序列化 同一个队列多消费类型 注解将消息和消息头注入消费者方法 关于消费者确认 关于发送者确认模式 消费消息.死信队列和RetryTemplate RPC模式的 ...
随机推荐
- 小技巧之“将Text文件中的数据导入到Excel中,这里空格为分割符为例”
1.使用场景 将数据以文本导出后,想录入到Excel中,的简便方案, 起因:对于Excel的导出,Text导出明显会更方便些 2.将Text文件中的数据导入到Excel中,这里空格为分割符为例的步骤 ...
- 180度\360度sg90舵机的使用及代码程序
大部资料都是在网上找到网友大神所共享的,在网上找了几种舵机的,刚接触有点懵,之后找得多了就理解了,想要控制一个硬件就要先了解这个硬件.这里有介绍180度舵机和360度舵机的具体使用,有网上大神的程序, ...
- (stm32f103学习总结)—stm32定时器中断
一.定时器介绍 STM32F1的定时器非常多,由2个基本定时器(TIM6.TIM7).4个通 用定时器(TIM2-TIM5)和2个高级定时器(TIM1.TIM8)组成.基本定 时器的功能最为简单,类似 ...
- PC端操作系统、移动端操作系统、嵌入式操作系统
左侧部分已是历史的操作系统,右侧的还是活跃的操作系统.安卓系统Android 是Google开发的基于Linux平台的开源手机操作系统.它包括操作系统.用户界面和应用程序-- 移动电话工作所需的全部软 ...
- React 和 ES6 工作流之 Webpack的使用(第六部分)
这是React和ECMAScript2015系列文章的最后一篇,我们将继续探索React 和 Webpack的使用. 下面是所有系列文章章节的链接: React . ES6 - 介绍(第一部分) Re ...
- PAT B1091 N-自守数
输入样例: 3 92 5 233 输出样例: 3 25392 1 25 No '解题思路:判断的时候将结果转换成字符串,判断后面几位数字和输入数字是否相同,掉进了N是从1到10的坑,而不是1到9 ...
- Android:setOnItemClickListener cannot be used with a spinner报错
错误原因: Spinner对象不支持使用setOnItemClickListener方法监听点击事项 解决方法: 使用setOnItemSelectedListener方法代替setOnItemCli ...
- 浅谈ES6中的Async函数
转载地址:https://www.cnblogs.com/sghy/p/7987640.html 定义:Async函数是一个异步操作函数,本质上,Async函数是Generator函数的语法糖.asy ...
- MySQL性能优化的5个维度
面试官如果问你:你会从哪些维度进行MySQL性能优化?你会怎么回答? 所谓的性能优化,一般针对的是MySQL查询的优化.既然是优化查询,我们自然要先知道查询操作要经过哪些环节,然后思考可以在哪些环节进 ...
- vue3项目后台管理系统模板
Vue3.0 发布第一个版本至今有一段时间了,到现在一直在更新优化,在性能方面,对比 Vue2.x ,性能的提升比较明显,打包后体积更小 来看下 Vue3.x 新增了哪些功能和特性. Performa ...



