分布式ID解决方法

183 阅读2分钟

以数据库为例,会出现的问题

image.png

解决方法

1.使用UUID进行处理

1.概念

UUID 是指Universally Unique Identifier,翻译为中⽂是通⽤唯⼀识别码 产⽣重复 UUID 并造成错误的情况⾮常低,是故⼤可不必考虑此问题。 Java中得到⼀个UUID,可以使⽤java.util包提供的⽅法.

2.使用方式

直接调用jdk的方法。

public class MyTest { public static void main(String[] args) { 
System.out.println(java.util.UUID.randomUUID().toString()); } }
3.不足

因为uuid比较长,且包含字符串,所以可以无法为主键建立索引,在一定程度上影响效率。

2.单独建表存id

使用方式

⽐如A表分表为A1表和A2表,那么肯定不能让A1表和A2表的ID⾃增,那么ID怎么获取呢?我们可 以单独的创建⼀个Mysql数据库,在这个数据库中创建⼀张表,这张表的ID设置为⾃增,其他地⽅ 需要全局唯⼀ID的时候,就模拟向这个Mysql数据库的这张表中模拟插⼊⼀条记录,此时ID会⾃ 增,然后我们可以通过Mysql的select last_insert_id() 获取到刚刚这张表中⾃增⽣成的ID.

-- Table structure for DISTRIBUTE_ID
-- ---------------------------- DROP TABLE IF EXISTS `DISTRIBUTE_ID`;
CREATE TABLE `DISTRIBUTE_ID`
( `id` bigint(32) NOT NULL AUTO_INCREMENT COMMENT '主键',
`createtime` datetime DEFAULT NULL, PRIMARY KEY (`id`) )
ENGINE=InnoDB DEFAULT CHARSET=utf8;

当分布式集群环境中哪个应⽤需要获取⼀个全局唯⼀的分布式ID的时候,就可以使⽤代码连接这个 数据库实例,执⾏如下sql语句即可。

insert into DISTRIBUTE_ID(createtime) values(NOW());
select LAST_INSERT_ID();

缺陷

  1. 当主键数据库挂了,会导致整个数据库系统无法使用。
  2. 对本数据库的操作很频繁,且都是插入操作,性能受影响。

3.使用雪花算法

雪花算法是Twitter推出的⼀个⽤于⽣成分布式ID的策略。 雪花算法是⼀个算法,基于这个算法可以⽣成ID,⽣成的ID是⼀个long型,那么在Java中⼀个long 型是8个字节,算下来是64bit,如下是使⽤雪花算法⽣成的⼀个ID的⼆进制形式示意:

image.png

4.使用redis的incr获取全局唯一id(推荐)

为啥能获取唯一id?

redis是单线程,不会出现线程冲突,争抢等问题,所以每次生成的id都是独立且唯一的。

借助Redis的Incr命令

Redis Incr 命令将 key 中储存的数字值增⼀。如果 key 不存在,那么 key 的值会先被初始化为 0 ,然后再执⾏ INCR 操作。 .incr(id) 1 2 3 4 image.png

使用方法
  1. 引入jar包
  2. 调用redis的api
jedis.incr("id"); //返回long