【教程】shardingjdbc(七)分布式序列
分⽚带来的主键唯⼀问题
当⼀个表的数据被切分到多个表的时候,那么单表的唯⼀主键就⽆法通过数据库来控制了,因为需要保证同⼀个表在多个真实表的主键id的唯⼀性。
注意:5.x 版本和4.x版本在配置上有略微的差别
内置解决⽅案
shardingjdbc内置了2种主键算法来供选择;
uuid
uuid 就是利⽤了jdk⽣成的uuid 字符串,来保证主键id 的不重复的特点
内置算法类是 UUIDKeyGenerateAlgorithm
使⽤⽅式也很简单
keyGenerateStrategy:
column: order_id
keyGeneratorName: uuid
keyGenerators:
uuid:
type: UUID
缺点:1.主键必须是 字符串类型;
2. 主键⾮连续的,对于b-tree索引插⼊数据时,建⽴索引的性能⽐连续数据的性能⽐较差;
优点: ⽐较简单
不是很推荐的⼀种⽅式;
雪花算法
雪花算法是Twitter 开源的⼀种分布式序列算法。⽣成的是⼀个64bit的整数。并且⽣成的是根据时间连续的;
整体结构 是 时间戳 + workid 机器id + 毫秒的序列化
具体的详细介绍这⾥不在赘述,请⾃⾏百度或google
使⽤⽅式:
配置主键id 列,配置类型,配置属性可以配置⼀个work-id 也就是中间的机器id能够有效的避免重复;
灰姑娘英文版
keyGenerateStrategy:
column: order_id
keyGeneratorName: snowflak
在最后⾯定义snowflow
优点: ⽣成的序列 是根据时间有序的;
缺点:依赖时钟,如果时钟回拨可能会导致重复;
注意⽣成的id 是64位的整数,在返给前端的时候记得做⼀些处理⽅案。 ⽐如处理json序列化将long 按照string来序列化
⾃定义算法
当然如果内置的2种算法⽆法满⾜需求,shardingjdbc⽀持spi拓展分布式序列算法;
1. ⾸先定义⼀个序列算法类,这⾥仅仅使⽤AtomicLong 做⼀个全局⾃增的操作,当然实际业务中可⾃定扩展;
实现getType ⽅法,返回此算法的类型名称
ample.shardingjdbcdemo.spi;
import org.apache.shardingsphere.sharding.spi.KeyGenerateAlgorithm;
import t.annotation.Scope;
import org.springframework.stereotype.Component;
import java.util.Properties;
import urrent.atomic.AtomicLong;
@Component
public final class IncrementKeyGenerate implements KeyGenerateAlgorithm {
private AtomicLong atomicLong;
@Override
public Properties getProps() {
return Props();
}
@Override
public void tProps(Properties props) {
KeyGenerateAlgorithm.super.tProps(props);
}
@Override
public String getType() {
dining hallreturn "INCREMENT";
}
@Override
public Comparable<?> generateKey() {
AndIncrement();
}
@Override
public void init() {
atomicLong = new AtomicLong(1);
}
宝马英文
@Override
public boolean isDefault() {
return true;
}
}
2. 定义spi 使⾃定义的类能被扫描到;
resoruce 下创建 META-INF ⽂件夹,下⾯再创建rvices ⽂件夹,严格安装java spi 标准来定义。
⽂件名称为来实现的接⼝名称 org.apache.shardingsphere.sharding.spi.KeyGenerateAlgorithm
内部写⼊具体实现类
3. 接下来 在定义主键算法的类型的时候就可以使⽤⾃⼰定义的类型了;
mini bus
完整配置如下
spring:
application:
name: shardingjdbcDemocrixus
main:
allow-bean-definition-overriding: true
shardingsphere:
#数据源信息
datasource:
#名称为dbsource-0的数据源
dbsource-0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: sql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://127.0.0.1:3306/db1?rverTimezone=Asia/Shanghai&uUnicode=true&characterEncoding=utf8&uSSL=fal urname: root
password: 123456
names: dbsource-0
#规则的配置
rules:
sharding:
tables:
#order表的规则
t_order:
actual-data-nodes: dbsource-0.t_order_$->{0..1}
#分表策略
table-strategy:
#标准策略
standard:
sharding-column: ur_id
sharding-algorithm-name: order-alg
keyGenerateStrategy:
column: order_id
keyGeneratorName: order-incr
#ur表的配置
t_ur:
actual-data-nodes: dbsource-0.t_ur_$->{0..1}
table-strategy:
#标准策略
standard:
sharding-column: ur_id
sharding-algorithm-name: ur-alg
keyGenerateStrategy:
hipstercolumn: ur_id
keyGeneratorName: ur-incr
#分⽚算法
sharding-algorithms:
order-alg:
type: INLINE
props:
algorithm-expression: t_order_$->{ur_id % 2}
ur-alg:
type: INLINE
props:
algorithm-expression: t_ur_$->{ur_id % 2}
algorithm-expression: t_ur_$->{ur_id % 2}
binding-tables:
- t_order,t_ur
keyGenerators:
ur-incr:
type: INCREMENT
order-incr:
type: INCREMENTdandy 342
corners
props:
sql-show: true
sql-comment-par-enabled: true
简单说明:在 keyGenerators 中定义算法名称 和算法类型和⼀些属性信息;
biceph
然后在具体的表的 keyGenerateStrategy 中使⽤ keyGeneratorName 来写⼊定义的名称,就完成了⼀个主键⽣成算法的关联定义;
remember when插⼊数据后,就会安装顺序递增的⽅式对每个表写⼊id;
注意:这⾥在下⾯定义2个算法是为了不同的表使⽤不同的实例类,避免不同的表使⽤⼀个⾃增id
注意:如果使⽤mybatis-plus 的时候要指定id 的type = IdType.AUTO 才能⽣效;
@TableId(type = IdType.AUTO)
⼀些其他的分布式序列⽅案
redis全局⾃增,使⽤redis 的incr命令维护全局⾃增顺序
mysql维护⾃增,使⽤⼀个单独的数据表记录每个业务表的⾃增位置等信息;
leaf 算法,美团的⾃增算法