1. ID服务概述
苍穹平台提供了分布式ID服务,用来生成集群环境内全局唯一ID。
ID的类型有long和String,它们之间可以相互转换。
ID使用snowflake算法生成(请百度了解),ID(Long类型)组成:0 time worker sequence。
服务嵌入到微服务节点内,每个微服务节点都含一个ID服务,一个ID服务可含多个woker,worker个数可配置,默认为1。
ID值在一个ID服务的一个worker内的ID产生是严格有序的(递增),由于集群由多个微服务节点同时提供服务,不同节点产生的ID值,顺序存在交错(worker的值交错),但总体上是趋势有序,因生成的时候存在时间差。
2. 使用接口:kd.bos.id.ID
#生成long类型ID值 long genLongId() long[] genLongIds(int) #生成String类型ID值(39进制) String genStringId() String[] genStringIds(int) #long与39进制字符互转 String toStringId(long) long toLongId(String) #long与36进制字符互转 String longTo36Radix(long) long longFrom36Radix(String) #获取id生成时间 Date getCreateTime(long) Date getCreateTime(String)
DB、ORM里的id接口,最终使用了kd.bos.id.ID (建议直接用这个)。
3.ID编码与长度
ID有long、string两种数据类型,string通过进制编码与long类型转换。
默认long to string使用Base39Code,组成的字符集为:+/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ
另外提供了36进制编码(longTo36Radix),用于不能有+/=字符的场合,字符集:0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ
字符集不含小写字母的原因:苍穹产品中对数据库的查询,字符不区分大小写。
long类型对应ksql的bigint,整型长度为19。
39进制,字符最大长度为12。
36进制,字符最大长度为13。
4.FAQ
1)为什么要有单独的ID服务?
数据表的自增字段,在插入值后才产生,但我们的领域模型中,通常需要先产生id值,在模型间引用传递。
自增方式会限制以后使用分表。
而ID服务可用于产生表行主键,也适用于其他需要全局唯一值的场景。
ID的趋势递增特性,做集聚索引,可减少表数据的移动。
2)表主键用ID什么类型好?
作为数据表主键,用long类型,它占8个字节,而字符类型占12~13个字节,数值类型比较更高效。
其他情况根据具体需要选择long/39string/36sting类型。
3)ORM save的时候为什么会产生主键冲突?
从ID生成的原理分析(ID服务内置时间回拨检测机制),在一个集群内,是不可能产生重复ID的。
一般是这种情况引起:ORM query出来的对象再save,此时所有操作都是insert,与已有的行就冲突了。
正确的用法是,ORM load出来的对象才能save,因为load出来的对象有快照,save时对比快照生成对应的增删改SQL。
4)怎么设置对象的主键?
用下面方法,生成唯一ID填补到无主键值的对象(含其分录、子分录对象)。
ORM.create().setPrimaryKey(DynamicObject)
推荐阅读