第2-2-4章 常见组件与中台化-常用组件服务介绍-分布式ID-附Snowflake雪花算法的代码实现

目录

  • 2.3 分布式ID
    • 2.3.1 功能概述
    • 2.3.2 应用场景
    • 2.3.3 使用说明
    • 2.3.4 项目截图
    • 2.3.5 Snowflake雪花算法的代码实现
2.3 分布式ID2.3.1 功能概述ID,全称Identifier,中文翻译为标识符 , 是用来唯一标识对象或记录的符号 。比如我们每个人都有自己的身份证号,这个就是我们的标识符 , 有了这个唯一标识,就能快速识别出每一个人 。
在计算机世界里,复杂的分布式系统中,经常需要对大量的数据、消息、HTTP 请求等进行唯一标识 。比如对于分微服务架构的系统中,服务间相互调用需要唯一标识,幂等处理,调用链路分析,日志追踪的时候都需要使用这个唯一标识 , 此时我们的系统就迫切的需要一个全局唯一的ID 。
另外随着社会的发展,各种金融、电商、支付、等系统中产生的数据越来越多,对数据库进行分库分表是比较常见的,而分库后则需要有一个唯一ID来标识一条数据或消息,单个数据库的自增ID显然不能满足需求,此时也会需要一个能够生成全局唯一ID的系统 。
工程结构:
第2-2-4章 常见组件与中台化-常用组件服务介绍-分布式ID-附Snowflake雪花算法的代码实现

文章插图
2.3.2 应用场景【第2-2-4章 常见组件与中台化-常用组件服务介绍-分布式ID-附Snowflake雪花算法的代码实现】1、全局唯一
这个最简单 , 就是说不能出现重复的ID,既然是唯一标识,这是最基本的要求 。比如采用UUID.randomUUID()的方式产生唯一且不重复的分布式主键 。最终生成一个字符串类型的主键 。缺点是生成的主键无序 。
2、趋势递增
先来了解下什么是趋势递增?
简单说就是在一段时间内,生成的ID是递增的趋势,而不强求下一个ID必须大于前一ID 。例如在一段时间内生成的ID在【0,1000】之间,过段时间生成的ID在【1000,2000】之间 。
为什么要趋势递增?
目前大部分的互联网公司使用了开源的MySQL数据库 , 存储引擎选择InnoDB 。MySQL InnoDB引擎中使用的是聚集索引 , 由于多数RDBMS数据库使用B-tree的数据结构来存储索引数据,在主键的选择上面我们应该尽量使用有序的主键,这样在插入新的数据时B-tree的结构不会时常被打乱重塑,能有效的提高存取效率 。
3、单调递增
通俗的说就是下一个ID一定大于上一个ID,例如事务版本号、IM增量消息、排序等特殊需求 。
4、信息安全
如果ID是连续递增的,那么恶意用户可以根据当前ID推测出下一个ID,爬取系统中数据的工作就非常容易实现,直接按照顺序访问指定URL即可;如果是订单号就更加危险,竞争对手可以直接知道系统一天的总订单量 。所以在一些应用场景下,会需要ID无规则、不规则,切不易被破解 。
5、雪花算法SNOWFLAKE
雪花算法,能够保证不同进程主键的不重复性,相同进程主键的有序性 。二进制形式包含4部分,从高位到低位分表为:1bit符号位、41bit时间戳位、10bit工作进程位以及12bit序列号位 。
  • 符号位(1bit)
预留的符号位,恒为零 。
  • 时间戳位(41bit)
41位的时间戳可以容纳的毫秒数是2的41次幂,一年所使用的毫秒数是:365 * 24 * 60 * 60 * 1000 Math.pow(2, 41) / (365 * 24 * 60 * 60 * 1000L) = 69.73年不重复;
  • 工作进程位(10bit)
该标志在Java进程内是唯一的,如果是分布式应用部署应保证每个工作进程的id是不同的 。该值默认为0,可通过属性设置 。
  • 序列号位(12bit)
该序列是用来在同一个毫秒内生成不同的ID 。如果在这个毫秒内生成的数量超过4096(2的12次幂) , 那么生成器会等待到下个毫秒继续生成 。
第2-2-4章 常见组件与中台化-常用组件服务介绍-分布式ID-附Snowflake雪花算法的代码实现

文章插图
优点:
  • 毫秒数在高位 , 自增序列在低位,整个ID都是趋势递增的 。
  • 不依赖第三方组件,稳定性高,生成ID的性能也非常高 。
  • 可以根据自身业务特性分配bit位,非常灵活
    缺点:
    强依赖机器时钟,如果机器上时钟回拨,会导致发号重复 。
2.3.3 使用说明分布式ID生成系统部署完成后,第三方系统接入即可直接获取ID 。

推荐阅读