## 分布式ID服务简介

分布式ID服务，提供生成环境内全局唯一ID：

- 全局唯一
- 趋势有序
- 高性能
- 高可靠

**全局唯一**

在一个cluster内产生的id是唯一的。

**趋势有序**

不能确保在极短的时间(取决于微服务节点之间的时间差)内生成的多个id是严格有序的，因此不能作为数据行生成的排序依据。

ID值含有当前服务节点的时间值，一个服务节点产生的id是严格有序，多个服务节点之间的时间可能存在误差，因此无法保证严格有序，但趋势有序。

**高性能**
	服务本节点内生成ID，仅在启动服务的时候，需要通过网络获取种子(workerId)。	

**高可用**
	1) 避免单点故障：ID服务由多个group组成，group内含多个worker；
	2) 容错与复用：含时钟回拨容错机制，可复用异常宕机服务节点的workerId。



## 生成接口与示例

`kd.bos.id.ID`接口：

```java
static long genLongId()
static long[] genLongIds(int count)

static String genStringId()
static String[] genStringIds(int count)

static String toStringId(long id)
static long toLongId(String id) 

// 获取创建ID的时间，可用于判断数据生成的大致时间。
static Date getCreateTime(long id)
static Date getCreateTime(String id)
```

创建id示例：

```java
long id = ID.genLongId();
long[] ids = ID.genLongIds(10);
```



## ID值说明

产生的id值有long和string两种，它们之间可以相互转换。

```java
// string 转为 long
ID.toLongId("xxx")
    
// long 转为 string
ID.toStringId(xxx)
```

_注意：系统的初始化数据，其id值可能不是通过id服务生成的，第三方系统的数据也不是，不能相互转换。_



string类型的id是对long进行了Base39编码，转换后保持有序。

>  如long v1<v2，转换成string后，v1转换的string id < v2转换的string id。

Base39编码字符集：`+/0123456789=ABCDEFGHIJKLMNOPQRSTUVWXYZ`



**数据库ID字段设计**

long类型：bigint(19)

string类型：varchar(12)

>  string类型最长为12个字节。



**获取ID创建时间**

```java
// 2019-08-22 10:58:36.212
Date createTime = ID.getCreateTime(698290515157716992L);
```



## ID服务配置

**1) 配置**

默认情况下不需要做任何配置。

```properties
IDService.store.zookeeper=指定使用的zk服务器地址，默认为集群使用的zk服务器。
IDService.worker=一个节点启动的id生成器(worker)个数，默认为1。
```

在zookeeper下的保存路径：`集群名称/runtime/ids`

**2) 启动**

ID服务是懒启动的，有调用到获取id值时ID服务才会启动。

ID服务启动是需要获取workerId种子，会用到分布式锁(DLock)，分布式锁不能用会导致ID服务启动不起来。

**3) 异常**

服务长期运行后，若抛**WorkerId已用完**的异常，则是因为微服务节点频繁重启，且运行期间时间有跳动(差额>10秒)导致，种子被用完。(种子最大可用数为1024个)

需关闭所有服务节点，然后清除种子：种子节点保存在/ids/w下，节点名称为数值(0-1023)，可删除整个w目录。

