一个简单的短ID生成器
为什么需要ID生成器?
在大多数开发过程中,实体类的属性中都有一个唯一标识用来获取这条数据的详情信息,无规律且唯一。在满足获取详情的基础上,需要可以保证这个ID在现在互联网中的分布式开发可以保证唯一,所以需要一个特有的ID生成器。
有哪些ID生成器?
UUID
通用唯一识别码(Universally Unique Identifier,简称UUID)是一种软件建构的标准,亦为开放软件基金会组织在分布式计算环境领域的一部分。
UUID的目的,是让分布式系统中的所有元素,都能有唯一的辨识信息,而不需要通过中央控制端来做辨识信息的指定。如此一来,每个人都可以创建不与其它人冲突的UUID。
UUID是由一组32位数的16进制数字所构成,是故UUID理论上的总数为1632=2128,约等于3.4 x 1038。也就是说若每纳秒产生1兆个UUID,要花100亿年才会将所有UUID用完。UUID的标准型式包含32个16进制数字,以连字号分为五段,形式为8-4-4-4-12
的32个字元。示例:
0b0324d0-1fc1-4331-8142-756598cf16f4
数据库自增ID
基于数据库的auto_increment
自增ID完全可以充当分布式ID,具体实现:需要一个单独的MySQL实例用来生成ID,实现简单,ID单调自增。通过集群模式设置不同步长可解决DB单点问题。
雪花算法
雪花算法(Snowflake)是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器。
Snowflake生成的是Long类型的ID,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特。
Snowflake ID
组成结构:正数位(占1比特)+ 时间戳(占41比特)+ 机器ID(占5比特)+ 数据中心(占5比特)+ 自增值(占12比特)
,总共64比特组成的一个Long类型。
- 第一个bit位(1bit):Java中long的最高位是符号位代表正负,正数是0,负数是1,一般生成ID都为正数,所以默认为0。
- 时间戳部分(41bit):毫秒级的时间,不建议存当前时间戳,而是用(当前时间戳 - 固定开始时间戳)的差值,可以使产生的ID从更小的值开始;41位的时间戳可以使用69年,
(1L << 41) / (1000L * 60 * 60 * 24 * 365) = 69年
- 工作机器id(10bit):也被叫做workId,这个可以灵活配置,机房或者机器号组合都可以。
- 序列号部分(12bit),自增值支持同一毫秒内同一个节点可以生成4096个ID
自定义实现短ID
以上三种已有的实现不适用,需要生成一个短ID。下面是使用随机数和引用hashIds
生成短ID的步骤
引入依赖
maven
引入hashids
依赖
<dependency>
<groupId>org.hashids</groupId>
<artifactId>hashids</artifactId>
<version>1.0.3</version>
</dependency>
工具类实现
通过随机数加盐,并且使用Hashids
生成短ID
@Slf4j
public class CnCodeUtil {
private static Random rand =new Random();
private CnCodeUtil(){}
/**
* 获取唯一码
* @return
*/
public static String code() {
final String SALT = this.getRandomString(8);
final int MIN_HASH_LENGTH = 11;
Hashids hashids = new Hashids(SALT, MIN_HASH_LENGTH);
return hashids.encode(347L);
}
/**
* 生成随机字符串
*
* @param length 表示生成字符串的长度
* @return
*/
public static String getRandomString(int length) {
String base = "0123456789";
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
int number = rand.nextInt(base.length());
sb.append(base.charAt(number));
}
return sb.toString();
}
小结
以上列举了几种已经有的,常用分布式ID实现方案,但我需要的是短ID,方便数据库存储,且保证唯一值。使用了hashIds结合随机数的方式实现,在实现过程中可以替换加盐为任一方式,保证随机性即可。
转载自:https://juejin.cn/post/7127243689390407687