Java几种分布式全局唯一ID生成方案

Java几种分布式全局唯一ID生成方案包括:

  1. 基于UUID的方案

UUID是通用唯一识别码,可以根据时间、硬件等因素生成唯一ID。Java内置了UUID工具类java.util.UUID,使用非常方便。UUID有36个字符,可以通过去除其中的“-”符号,将其减少至32位,降低传输成本。但是,UUID并不是顺序递增的序列,如果需要使用有序递增的ID,则需要结合其他方案使用。

  1. 基于Snowflake算法的方案

Snowflake算法是Twitter开源的算法,可以生成唯一的ID序列。具体实现是将64位的ID分为5个部分:时间戳、数据中心ID、机器ID、序列号。其中时间戳占据了41位,可以使用到2082年,数据中心和机器ID各占5位,可以支持32个数据中心和每个数据中心32台机器,序列号占据了12位,每毫秒可以生成4096个唯一ID。

代码示例如下:

public class IdWorker {
    private long datacenterId;  //数据中心ID
    private long workerId;  //机器ID
    private long sequence = 0L; //序列号
    private long twepoch = 1288834974657L; //时间戳基准值
    private long datacenterIdBits = 5L; //数据中心ID位数
    private long workerIdBits = 5L; //机器ID位数
    private long sequenceBits = 12L; //序列号位数
    private long workerIdShift = sequenceBits; //机器ID左移位数
    private long datacenterIdShift = sequenceBits + workerIdBits; //数据中心ID左移位数
    private long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits; //时间戳左移位数
    private long sequenceMask = ~(-1L << sequenceBits); //序列号掩码
    private long lastTimestamp = -1L; //上次生成ID的时间戳

    public IdWorker(long datacenterId, long workerId) {
        this.datacenterId = datacenterId;
        this.workerId = workerId;
    }

    public synchronized long nextId() {
        long timestamp = timeGen();
        if (timestamp < lastTimestamp) {
            throw new RuntimeException("时钟回拨的时间太短了");
        }
        if (lastTimestamp == timestamp) {
            sequence = (sequence + 1) & sequenceMask;
            if (sequence == 0) {
                timestamp = tilNextMillis(lastTimestamp);
            }
        } else {
            sequence = 0L;
        }
        lastTimestamp = timestamp;

        return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift) |
                (workerId << workerIdShift) | sequence;
    }

    private long tilNextMillis(long lastTimestamp) {
        long timestamp = timeGen();
        while (timestamp <= lastTimestamp) {
            timestamp = timeGen();
        }
        return timestamp;
    }

    private long timeGen() {
        return System.currentTimeMillis();
    }
}
  1. 基于Redis的方案

Redis可以作为分布式系统中的数据存储中心,提供全局唯一ID生成的服务。具体实现是使用Redis的原子性操作incr命令,每次请求incr命令都会自动+1,如果设置了过期时间,可以在过期后重置序列号。这种方案需要设置适当的过期时间,以免在系统宕机时导致ID重复。

示例代码如下:

public class RedisIdGenerator {
    private static final String ID_KEY = "my-id-generator";
    private static final int TIMEOUT = 60;
    private RedisTemplate redisTemplate;
    private RedisSerializer keySerializer = new StringRedisSerializer();
    private RedisSerializer valueSerializer = new Jackson2JsonRedisSerializer(Object.class);

    public RedisIdGenerator(RedisTemplate redisTemplate) {
        this.redisTemplate = redisTemplate;
        this.redisTemplate.setKeySerializer(keySerializer);
        this.redisTemplate.setValueSerializer(valueSerializer);
    }

    public Long nextId() {
        ValueOperations<String, Long> ops = redisTemplate.opsForValue();
        Long id = ops.increment(ID_KEY, 1L);
        if (id == 1L) {
            redisTemplate.expire(ID_KEY, TIMEOUT, TimeUnit.SECONDS);
        }
        return id;
    }
}

以上是Java几种分布式全局唯一ID生成方案的详细讲解,如果有需要可以根据实际情况选择使用其中的一种方案。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java几种分布式全局唯一ID生成方案 - Python技术站

(0)
上一篇 2023年5月22日
下一篇 2023年5月22日

相关文章

  • MySQL 如何分析查询性能

    MySQL 是一个常用的关系型数据库,查询性能对于应用程序的质量至关重要。MySQL 提供了一些工具来分析查询性能以优化查询。以下是一些如何分析查询性能的攻略: 1. 使用 EXPLAIN 分析查询语句 使用 EXPLAIN 命令可以分析查询语句的执行计划和成本,并提供有关查询优化的有用信息。EXPLAIN 命令返回一行结果集,其中列描述了查询优化器的执行计…

    database 2023年5月19日
    00
  • SQL 从不固定位置提取字符串的元素

    当我们需要从字符串中提取指定的元素时,通过在SQL中使用一些内置的函数,例如SUBSTRING()和CHARINDEX()函数,可以轻松完成这个任务。 在下面的示例中,我将向您展示如何从不同位置提取字符串中的元素: 示例1:从起始位置提取字符串的元素 假设我们有以下这个字符串 “Hello World”,现在我们想要从字符串的起始位置提取前4个字符。可以通过…

    database 2023年3月27日
    00
  • Python连接数据库并批量插入包含日期记录的操作

    下面是Python连接数据库并批量插入包含日期记录的操作的完整攻略: 1. 连接数据库 Python连接数据库需要使用到相应的的库,比如MySQL数据库需要使用pymysql库。下面是一个连接MySQL数据库的样例代码: import pymysql #连接数据库 db = pymysql.connect(host = ‘localhost’, port =…

    database 2023年5月21日
    00
  • Ubuntu下MySQL中文乱码的问题解决

    针对Ubuntu下MySQL中文乱码的问题,可以参考以下步骤进行解决: 问题描述 在Ubuntu系统下使用MySQL时,可能出现中文乱码的问题。 原因分析 MySQL默认使用的字符集为Latin1,而Latin1并不支持中文字符集。如果在使用MySQL时没有指定字符集,那么MySQL会使用默认的Latin1字符集,因此在插入中文字符时会出现乱码。 解决方法 …

    database 2023年5月22日
    00
  • LINUX下Oracle数据导入导出的方法详解

    LINUX下Oracle数据导入导出的方法详解 本文将介绍在LINUX系统下如何进行Oracle数据库的数据导入和导出,以及一些常用的导入导出命令。 数据库导出 在LINUX系统下,在使用Oracle数据库进行数据导出时,可以使用expdp命令进行导出。该命令的语法如下: expdp system/password@ORACLE_SID SCHEMAS=SC…

    database 2023年5月22日
    00
  • Elasticsearch 和 Amazon DynamoDB的区别

    Elasticsearch和Amazon DynamoDB是两个经常被用于数据存储和检索的工具。虽然它们都可以用于存储和检索数据,但它们在细节方面有很多区别。下面将详细介绍它们之间的区别。 1. 数据模型的不同 Elasticsearch和DynamoDB的数据模型是不同的。Elasticsearch是一个全文搜索引擎,数据以文档(document)的方式存…

    database 2023年3月27日
    00
  • wordpress 网站转移服务器操作的两种方法

    下面是详细的攻略过程,包含两条示例说明: 一、使用文件传输协议(FTP)转移 FTP是最常用的服务器之间文件传输的协议。如果您的服务器在互联网上开放FTP访问权限,可以使用FTP将您的WordPress网站从一个服务器转移到另一个服务器。 备份网站数据:在操作过程中可能会导致数据丢失或损坏,提前备份您的整个WordPress文件夹和数据库。 在新的服务器上安…

    database 2023年5月22日
    00
  • SQL 将含有字母和数字的字符串转换为数字

    将含有字母和数字的字符串转换为数字需要使用SQL中的函数进行转换,下面是完整攻略和两个实例: 1. 使用CAST函数进行转换 CAST函数将一个数据类型转换为另一个数据类型,可以用于将字符串转换为数字。具体用法如下: CAST(string AS datatype) 其中string是待转换的字符串,datatype是目标数据类型。 例如,将字符串’123’…

    database 2023年3月27日
    00
合作推广
合作推广
分享本页
返回顶部