1、UUID

实现方式

String uuid = UUID.randomUUID().toString().replaceAll("-","");

优点:

  • 生成简单,本地生成无网络消耗,具有唯一性

缺点:

  • 无序的字符串,不具备趋势自增特性
  • 没有具体的业务含义
  • 长度过长,存储以及查询对MySQL的性能消耗较大。

2、数据库自增id

实现方式

需要一个单独的MySQL表用来生成ID

CREATE DATABASE `SEQ_ID`;
CREATE TABLE SEQID.SEQUENCE_ID (id bigint(20) unsigned NOT NULL auto_increment, stub char(10) NOT NULL default '',PRIMARY KEY (id),UNIQUE KEY value(stub)
) ENGINE=MyISAM;begin:
replace into SEQUENCE_ID(stub) VALUES('anyword');
select last_insert_id();
commit;

优点:

  • 实现简单,ID单调自增,数值类型查询速度快

缺点:

  • DB单点存在宕机风险,无法扛住高并发场景

那如果采用基于数据库的主从或者多主模式,就能够解决上面的高并发场景了吗,答案是否定的

问题

  • 主从复制间存在延时,主机刚刚插入一个新的id,还没有同步到从机就挂机了。从机变为主机后会生成重复id
  • 多主模式下要设置起始值和自增步长,且不利于后续扩容,而且实际上单个数据库自身压力还是大,依旧无法满足高并发场景。

3、基于数据库的号段模式

号段模式是当下分布式ID生成器的主流实现方式之一,号段模式可以理解为从数据库批量的获取自增ID,每次从数据库取出一个号段范围,例如 (1,1000] 代表1000个ID,具体的业务服务将本号段,生成1~1000的自增ID并加载到内存。表结构如下:

CREATE TABLE id_generator (id int(10) NOT NULL,max_id bigint(20) NOT NULL COMMENT '当前最大id',step int(20) NOT NULL COMMENT '号段的步长',biz_type    int(20) NOT NULL COMMENT '业务类型',version int(20) NOT NULL COMMENT '版本号',PRIMARY KEY (`id`)
)
  • biz_type :代表不同业务类型
  • max_id :当前最大的可用id
  • step :代表号段的长度
  • version :是一个乐观锁,每次都更新version,保证并发时数据的正确性

等这批号段ID用完,再次向数据库申请新号段,对max_id字段做一次update操作,update max_id= max_id + step,update成功则说明新号段获取成功,新的号段范围是(max_id ,max_id +step]。

update id_generator set max_id = #{max_id+step}, version = version + 1 where version = # {version} and biz_type = XXX

由于多业务端可能同时操作,所以采用版本号version乐观锁方式更新,这种分布式ID生成方式不强依赖于数据库,不会频繁的访问数据库,对数据库的压力小很多

4、基于Redis模式

Redis也同样可以实现,原理就是利用redis的 incr命令实现ID的原子性自增。

优点:

  • 不依赖于数据库,灵活方便,且性能优于数据库。
  • 数字ID天然排序,对分页或者需要排序的结果很有帮助。

缺点:

  • 如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。

  • 防止redis挂机需要配置集群,RDB方式会有延时,而AOF恢复的时间较长(要执行较多的incr命令)

5、雪花算法(Snowflake)模式


Snowflake生成的是Long类型的ID,一个Long类型占8个字节,每个字节占8比特,也就是说一个Long类型占64个比特。

  • 第一个bit位(1bit):代表正负,正数是0,负数是1,默认为0。
  • 时间戳部分(41bit):毫秒级的时间,(当前时间戳 - 固定开始时间戳)的差值,可以使产生的ID从更小的值开始;41位大概使用69年
  • 工作机器id(10bit):机房或者机器号组合都可以。
  • 序列号部分(12bit),自增值支持同一毫秒内同一个节点可以生成4096个ID

优点:

  • 不依赖于数据库,灵活方便,且性能优于数据库。
  • ID按照时间在单机上是递增的。

缺点:

  • 在单机上是递增的,但是由于涉及到分布式环境,每台机器上的时钟不可能完全同步,也许有时候也会出现不是全局递增的情况。

6、百度的uid-generator

uid-generator是基于Snowflake算法实现的,与原始的snowflake算法不同在于,uid-generator支持自定义时间戳、工作机器ID和 序列号 等各部分的位数,而且uid-generator中采用用户自定义workId的生成策略。

  • workId,占用了22个bit位。需要与数据库配合使用,需要新增一个WORKER_NODE表。当应用重启时会向数据库表中去插入一条数据,插入成功后返回的自增ID就是该机器的workId,应用运行时workId不变

  • 时间占用了28个bit位,时间的单位改成了秒

  • 序列化占用了13个bit位

解决时钟回拨问题

  • synchronized保证线程安全;
  • 如果时间有任何的回拨,那么直接抛出异常;
  • 如果当前时间和上一次是同一秒时间,那么sequence自增。如果同一秒内自增值超过2^13-1,那么就会自旋等待下一秒(getNextSecond);
  • 如果是新的一秒,那么sequence重新从0开始;

7、美团(Leaf)

美团的Leaf也是一个分布式ID生成框架。它非常全面,即支持号段模式,也支持snowflake模式。号段模式这里就不介绍了,和上面的分析类似。

Leaf中的snowflake模式和原始snowflake算法的不同点,也主要在workId的生成,Leaf中workId是基于ZooKeeper的顺序Id来生成的,每个应用在使用Leaf-snowflake时,在启动时都会都在Zookeeper中生成一个顺序Id,相当于一台机器对应一个顺序节点,也就是一个workId。

[java] 分布式id生成方案相关推荐

  1. 面试官:你会几种分布式 ID 生成方案???

    1. 为什么需要分布式 ID 对于单体系统来说,主键 ID 常用主键自动的方式进行设置.这种 ID 生成方法在单体项目是可行的,但是对于分布式系统,分库分表之后就不适应了.比如订单表数据量太大了,分成 ...

  2. easyui treegrid获取父节点的id_超简单的分布式ID生成方案!美团开源框架介绍

    目录 阐述背景 Leaf snowflake 模式介绍 Leaf segment 模式介绍 Leaf 改造支持 RPC 阐述背景 不吹嘘,不夸张,项目中用到 ID 生成的场景确实挺多.比如业务要做幂等 ...

  3. 超简单的分布式ID生成方案!美团开源框架介绍

    目录 阐述背景 Leaf snowflake 模式介绍 Leaf segment 模式介绍 Leaf 改造支持 RPC 阐述背景 不吹嘘,不夸张,项目中用到 ID 生成的场景确实挺多.比如业务要做幂等 ...

  4. 常见分布式ID生成方案

    文章目录 一.为什么要用分布式ID 1.什么是分布式ID 2.那么分布式ID需要满足哪些条件 二. 分布式ID有哪些生成方式 1.基于UUID 2.基于数据库自增ID 3.基于数据库集群模式 4.基于 ...

  5. 分布式 ID 生成方案

    不管我们是不是有身份的人,我们一定是有身份证的人,身份证上面的号码就是我们的 ID,理论上这个 ID 是全国唯一的,而且通过这个号码,我们还可以得到一些个人信息,比如前两位可以确定我们第一次申请身份证 ...

  6. 分布式ID生成方案(二):SnowFlake雪花算法

    雪花算法(SnowFlake) 是twitter公司内部分布式项目采用的ID生成算法,开源后广受国内大厂的好评,在该算法影响下各大公司相继开发出各具特色的分布式生成器. SnowFlake算法生成id ...

  7. 分布式ID详解(5种分布式ID生成方案)

    分布式架构会涉及到分布式全局唯一ID的生成,今天我就来详解分布式全局唯一ID,以及分布式全局唯一ID的实现方案@mikechen 什么是分布式系统唯一ID 在复杂分布式系统中,往往需要对大量的数据和消 ...

  8. 一线大厂的分布式唯一ID生成方案是什么样的?

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 一.前言 分布式系统中我们会对一些数据量大的业务进行分拆,如:用户 ...

  9. 一起学习下一线大厂的分布式唯一ID生成方案!

    来源 | http://www.toutiao.com/i6682672464708764174 一.前言 分布式系统中我们会对一些数据量大的业务进行分拆,如:用户表,订单表.因为数据量巨大一张表无法 ...

最新文章

  1. Ubuntu 及其衍生版安装使用录屏工具【SimpleScreenRecoder】
  2. Redis安装(CentOS7/tar.gz)
  3. 使用 gperf 实现高效的 C/C++ 命令行处理
  4. android自定义渐变色,Android设置背景渐变色
  5. Flask 蓝图机制及应用
  6. Django:ORM基本操作-CRUD,管理器对象objects,----->新增
  7. BaseRecyclerViewAdapterHelper: 灵活强大的循环适配器
  8. 量体裁衣:将DevOps转型融入到企业文化
  9. 34.了解那些算法要求使用排序的区间作为参数
  10. 《微处理器体系结构》1.1 汇编语言与机器语言及应用
  11. 关于Win10家庭版安装VirtualBox时的一些问题(e.g.报错2203)
  12. 一本通1645Fibonacci
  13. hdu-5761 Rower Bo(数学)
  14. 密码加盐原理及其实现
  15. 利用百度地图API接口自制地图
  16. 《Spring揭秘》读书笔记 3:Spring MVC
  17. CSS进阶-Less
  18. n-queens(n皇后问题)
  19. Flutter:加载本地Html、WebView与JS交互
  20. 终端连接工具Tabby的下载、安装与配置

热门文章

  1. 程序员的吐槽大会,动机何在?
  2. java计算机毕业设计后勤招标采购管理系统2021源码+mysql数据库+系统+lw文档+部署
  3. (转)CSS 基本知识
  4. Error: Could not create the Java Virtual Machine.Error: A fatal exception has occurred. Progra
  5. ssci源刊里有开源期刊吗_计算机类SCI检索源刊,期刊影响因子排名
  6. 工业企业数字化转型中的数据治理
  7. 几种图像颜色特征空间
  8. 被讨厌的勇气-思维导图
  9. 技术写作:如何编写软件文档
  10. 从零开始实现k线图走势图绘制(iOS理论篇)