当前位置: 首页 > 科技观察

雪花算法:分布式唯一ID生成工具

时间:2023-03-19 18:24:49 科技观察

前言以分布式ID为例,其生成往往需要唯一性、增量性、高可用和高性能。并且在业务处理过程中,还需要防止爬虫根据ID的自增来爬取数据。雪花算法在这些方面表现良好。CommonDistributedIDGeneration市面上常见的分布式ID生成算法和类库:UUID:Java自带API生成一串唯一的随机36位字符串(32个字符串+4个“-”)。可以保证唯一性,但可读性较差,不能有序递增。SnowFlake:Snowflake算法,Twitter开源的由64位整数组成的分布式ID,具有高性能,单机增量。GitHub上的官方地址:https://github.com/twitter-archive/snowflake/tree/snowflake-2010。UidGenerator:百度开源分布式ID生成器,基于雪花算法。GitHub参考链接:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md。该项目的文档和测试用例值得深入研究。Leaf:美团开源的分布式ID生成器可以保证全局唯一,而且有越来越大的趋势,但是需要依赖关系型数据库、Zookeeper等中间件。相关实现可参考本文:https://tech.meituan.com/2017/04/21/mt-leaf.html。雪花算法雪花(snowflake)是美丽的、独特的、不可预测的。在自然界中很难找到两个相同的雪花。雪花的这些特征在雪花算法中表现出来了。SnowFlake算法是Twitter开源的分布式ID生成算法。核心思想是:使用一个64位长的数字作为全球唯一的ID。该算法还引入了时间戳,基本保证了自增特性。最初版本的雪花算法是基于scala编写的,当然可以根据其算法逻辑实现不同的编程语言。雪花算法原理SnowFlake算法生成的ID的结果是一个64位整数,结构如下:算法分析:第一部分:1位,无意义,固定为0。二进制的最高位是符号位,1表示负数,0表示正数。ID都是正整数,所以固定为0。第二部分:41位,代表时间戳,精确到毫秒,可以使用69年。时间戳具有自动递增属性。第三部分:10位,代表一个10位的机器ID,最多支持1024个节点。这部分也可以拆分为5位datacenterId和5位workerId,其中datacenterId代表机房ID,workerId代表机器ID。第四部分:12位,表示序列化,即部分列的自增ID,可支持同一节点在同一毫秒内最多生成4095个ID序号。由于Java中64位整型是long类型,所以Java中SnowFlake算法生成的id存储在long中。SnowflakeAlgorithmJava实现雪花算法Java工具类实现:publicclassSnowFlake{/***起始时间戳(可以设置当前时间之前的时间)*/privatefinalstaticlongSTART_STAMP=1480166465631L;/***序列号占用的位数*/privatefinalstaticlongSEQUENCE_BIT=12;/***机器标识占用的位数*/privatefinalstaticlongMACHINE_BIT=5;/***数据中心占用的位数*/privatefinalstaticlongDATA_CENTER_BIT=5;/***每个部分的最大值*/privatefinalstaticlongMAX_DATA_CENTER_NUM=~(-1L<MAX_DATA_CENTER_NUM||dataCenterId<0){thrownewIllegalArgumentException("dataCenterId不能大于MAX_DATA_CENTER_NUM"+"0");}if(machineId>MAX_MACHINE_NUM||machineId<0){thrownewIllegalArgumentException("machineId不能大于MAX_MACHINE_NUM或小于0");}this.dataCenterId=dataCenterId;this.machineId=machineId;}/***生成下一个ID*/publicsynchronizedlongnextId(){longcurrStamp=getNewStamp();if(currStamp