当前位置:

首页 > 编程开发 > redis分布式ID解决方法有哪些

redis分布式ID解决方法有哪些

IDM
IDM

IDM(Internet Download Manager)是一款专为 Win 平台打造的高速下载利器,享受超快的下载速度和极致的下载体验。在数码荔枝可以更优惠的价格购买正版 IDM,避免使用破解,获得安全稳定的服务。

立即下载
¥59
Windows 2026-10-12
Internet Download Manager 正版软件 Windows idm 装机必备

常用的分布式ID解决方案在分布式系统中,生成全局唯一ID是非常重要的,因为在分布式系统中,多个节点同时生成ID可能会导致ID冲突。下面介绍几种常用的分布式ID解决方案。UUIDUUID(通用唯一标识符)是由128位数字组成的标识符,它可以保证在全球范围内的唯一性,因为其生成算法基于时间戳、节点ID等因素。UUID可以使用Java自带的UUID类来生成,如下所示:javaCopycodeimportjava.util.UUID;publicclassUuidGenerator{publicstaticvoi

本文目录

      常用的分布式ID解决方案

      在分布式系统中,生成全局唯一ID是非常重要的,因为在分布式系统中,多个节点同时生成ID可能会导致ID冲突。

      下面介绍几种常用的分布式ID解决方案。

      UUID

      UUID(通用唯一标识符)是由128位数字组成的标识符,它可以保证在全球范围内的唯一性,因为其生成算法基于时间戳、节点ID等因素。UUID可以使用Java自带的UUID类来生成,如下所示:

      javaCopy code
      import java.util.UUID;
      public class UuidGenerator {
          public static void main(String[] args) {
              UUID uuid = UUID.randomUUID();
              System.out.println(uuid.toString());
          }
      }

      UUID的优点是简单易用,无需额外的配置和管理,可以直接使用Java自带的UUID类生成。但是UUID长度较长(128位),不太适合作为数据库表的主键,且不易于排序和索引。

      Snowflake

      Snowflake是Twitter开源的一种分布式ID生成算法,它可以生成64位的唯一ID,其中包含了时间戳、数据中心ID和机器ID等信息。Snowflake算法的Java代码如下所示:

      Snowflake算法的Java代码:
      javaCopy code
      public class SnowflakeGenerator {
          private final static long START_STMP = 1480166465631L;
          private final static long SEQUENCE_BIT = 12;
          private final static long MACHINE_BIT = 5;
          private final static long DATACENTER_BIT = 5;
          private final static long MAX_DATACENTER_NUM = -1L ^ (-1L << DATACENTER_BIT);
          private final static long MAX_MACHINE_NUM = -1L ^ (-1L << MACHINE_BIT);
          private final static long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BIT);
          private final static long MACHINE_LEFT = SEQUENCE_BIT;
          private final static long DATACENTER_LEFT = SEQUENCE_BIT + MACHINE_BIT;
          private final static long TIMESTMP_LEFT = DATACENTER_LEFT + DATACENTER_BIT;
          private long datacenterId;
          private long machineId;
          private long sequence = 0L;
          private long lastStmp = -1L;
          public SnowflakeGenerator(long datacenterId, long machineId) {
              if (datacenterId > MAX_DATACENTER_NUM || datacenterId < 0) {
                  throw new IllegalArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
              }
              if (machineId > MAX_MACHINE_NUM || machineId < 0) {
                  throw new IllegalArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
              }
              this.datacenterId = datacenterId;
              this.machineId = machineId;
          }
          public synchronized long nextId() {
              long currStmp = getNewstmp();
              if (currStmp < lastStmp) {
                  throw new RuntimeException("Clock moved backwards.  Refusing to generate id");
              }
              if (currStmp == lastStmp) {
                  sequence = (sequence + 1) & MAX_SEQUENCE;
                  if (sequence == 0L) {
                      currStmp = getNextMill();
                  }
              } else {
                  sequence = 0L;
              }
              lastStmp = currStmp;
              return (currStmp - START_STMP) << TIMESTMP_LEFT
                      | datacenterId << DATACENTER_LEFT
                      | machineId << MACHINE_LEFT
                      | sequence;
          }
          private long getNextMill() {
              long mill = getNewstmp();
              while (mill <= lastStmp) {
                  mill = getNewstmp();
              }
              return mill;
          }
          private long getNewstmp() {
              return System.currentTimeMillis();
          }
      }

      Snowflake算法的优点是生成ID的性能高,且ID长度较短(64位),可以作为数据库表的主键,且便于排序和索引。但是需要注意,如果集群中的节点数超过了机器ID所占的位数,或者集群规模很大,时间戳位数不够用,那么就需要考虑其他的分布式ID生成算法。

      Leaf

      Leaf是美团点评开源的一种分布式ID生成算法,它可以生成全局唯一的64位ID。Leaf算法的Java代码如下所示:

      Leaf算法的Java代码:
      javaCopy code
      public class LeafGenerator {
          private static final Logger logger = LoggerFactory.getLogger(LeafGenerator.class);
          private static final String WORKER_ID_KEY = "leaf.worker.id";
          private static final String PORT_KEY = "leaf.port";
          private static final int DEFAULT_PORT = 8080;
          private static final int DEFAULT_WORKER_ID = 0;
          private static final int WORKER_ID_BITS = 10;
          private static final int SEQUENCE_BITS = 12;
          private static final int MAX_WORKER_ID = (1 << WORKER_ID_BITS) - 1;
          private static final int MAX_SEQUENCE = (1 << SEQUENCE_BITS) - 1;
          private static final long EPOCH = 1514736000000L;
          private final SnowflakeIdWorker idWorker;
          public LeafGenerator() {
              int workerId = SystemPropertyUtil.getInt(WORKER_ID_KEY, DEFAULT_WORKER_ID);
              int port = SystemPropertyUtil.getInt(PORT_KEY, DEFAULT_PORT);
              this.idWorker = new SnowflakeIdWorker(workerId, port);
              logger.info("Initialized LeafGenerator with workerId={}, port={}", workerId, port);
          }
          public long nextId() {
              return idWorker.nextId();
          }
          private static class SnowflakeIdWorker {
              private final long workerId;
              private final long port;
              private long sequence = 0L;
              private long lastTimestamp = -1L;
              SnowflakeIdWorker(long workerId, long port) {
                  if (workerId < 0 || workerId > MAX_WORKER_ID) {
                      throw new IllegalArgumentException(String.format("workerId must be between %d and %d", 0, MAX_WORKER_ID));
                  }
                  this.workerId = workerId;
                  this.port = port;
              }
              synchronized long nextId() {
                  long timestamp = System.currentTimeMillis();
                  if (timestamp < lastTimestamp) {
                      throw new RuntimeException("Clock moved backwards. Refusing to generate id");
                  }
                  if (timestamp == lastTimestamp) {
                      sequence = (sequence + 1) & MAX_SEQUENCE;
                      if (sequence == 0L) {
                          timestamp = tilNextMillis(lastTimestamp);
                      }
                  } else {
                      sequence = 0L;
                  }
                  lastTimestamp = timestamp;
                  return ((timestamp - EPOCH) << (WORKER_ID_BITS + SEQUENCE_BITS))
                          | (workerId << SEQUENCE_BITS)
                          | sequence;
              }
              private long tilNextMillis(long lastTimestamp) {
                  long timestamp = System.currentTimeMillis();
                  while (timestamp <= lastTimestamp) {
                      timestamp = System.currentTimeMillis();
                  }
                  return timestamp;
              }
          }
      }

      Leaf算法的特点是生成ID的速度比Snowflake算法略慢,但是可以支持更多的Worker节点。Leaf算法生成的ID由三部分组成,分别是时间戳、Worker ID和序列号,其中时间戳占用42位、Worker ID占用10位、序列号占用12位,总共64位。

      以上是常见的分布式ID生成算法,当然还有其他的一些方案,如:MongoDB ID、UUID、Twitter Snowflake等。不同的方案适用于不同的业务场景,具体实现细节和性能表现也有所不同,需要根据实际情况选择合适的方案。

      除了上述介绍的分布式ID生成算法,还有一些新的分布式ID生成方案不断涌现,例如Flicker的分布式ID生成算法,它使用了类似于Snowflake的思想,但是采用了不同的位数分配方式,相比Snowflake更加灵活,并且可以根据需要动态调整每个部分占用的位数。此外,Facebook还推出了ID Generation Service (IGS)方案,该方案将ID的生成和存储分离,提供了更加灵活和可扩展的方案,但是需要进行更加复杂的架构设计和实现。

      针对不同的业务需求,可以设计多套分布式ID生成方案。下面是我个人的一些建议:

      • 基于数据库自增ID生成:使用数据库自增ID作为全局唯一ID,可以很好的保证ID的唯一性,并且实现简单,但是并发量较高时可能会导致性能瓶颈。因此,在高并发场景下不建议使用。

      • 基于UUID生成:使用UUID作为全局唯一ID,可以很好地保证ID的唯一性,但是ID长度较长(128位),不便于存储和传输,并且存在重复ID的概率非常小但不为0。因此,建议在分布式系统中使用时要考虑ID的长度和存储传输的成本。

      • 基于Redis生成:使用Redis的原子性操作,可以保证ID的唯一性,并且生成ID的速度非常快,可以适用于高并发场景。但是需要注意,如果Redis宕机或者性能不足,可能会影响ID的生成效率和可用性。

      • 基于ZooKeeper生成:使用ZooKeeper的序列号生成器,可以保证ID的唯一性,并且实现较为简单,但是需要引入额外的依赖和资源,并且可能会存在性能瓶颈。

      选择适合自己业务场景的分布式ID生成方案,需要综合考虑ID的唯一性、生成速度、长度、存储成本、可扩展性、可用性等多个因素。同时需要注意,不同方案的实现细节和性能表现也有所不同,需要根据实际情况进行权衡和选择。

      下面给出每种方案的详细代码demo:

      基于数据库自增ID生成

      javaCopy code
      public class IdGenerator {
          private static final String JDBC_URL = "jdbc:mysql://localhost:3306/test";
          private static final String JDBC_USER = "root";
          private static final String JDBC_PASSWORD = "password";
          public long generateId() {
              Connection conn = null;
              PreparedStatement pstmt = null;
              ResultSet rs = null;
              try {
                  Class.forName("com.mysql.jdbc.Driver");
                  conn = DriverManager.getConnection(JDBC_URL, JDBC_USER, JDBC_PASSWORD);
                  pstmt = conn.prepareStatement("INSERT INTO id_generator (stub) VALUES (null)", Statement.RETURN_GENERATED_KEYS);
                  pstmt.executeUpdate();
                  rs = pstmt.getGeneratedKeys();
                  if (rs.next()) {
                      return rs.getLong(1);
                  }
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  try {
                      if (rs != null) {
                          rs.close();
                      }
                      if (pstmt != null) {
                          pstmt.close();
                      }
                      if (conn != null) {
                          conn.close();
                      }
                  } catch (Exception e) {
                      e.printStackTrace();
                  }
              }
              return 0L;
          }
      }

      基于UUID生成

      javaCopy code
      import java.util.UUID;
      public class IdGenerator {
          public String generateId() {
              return UUID.randomUUID().toString().replace("-", "");
          }
      }

      基于Redis生成

      javaCopy code
      import redis.clients.jedis.Jedis;
      public class IdGenerator {
          private static final String REDIS_HOST = "localhost";
          private static final int REDIS_PORT = 6379;
          private static final String REDIS_PASSWORD = "password";
          private static final int ID_GENERATOR_EXPIRE_SECONDS = 3600;
          private static final String ID_GENERATOR_KEY = "id_generator";
          public long generateId() {
              Jedis jedis = null;
              try {
                  jedis = new Jedis(REDIS_HOST, REDIS_PORT);
                  jedis.auth(REDIS_PASSWORD);
                  long id = jedis.incr(ID_GENERATOR_KEY);
                  jedis.expire(ID_GENERATOR_KEY, ID_GENERATOR_EXPIRE_SECONDS);
                  return id;
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  if (jedis != null) {
                      jedis.close();
                  }
              }
              return 0L;
          }
      }

      基于ZooKeeper生成

      javaCopy code
      import java.util.concurrent.CountDownLatch;
      import org.apache.zookeeper.CreateMode;
      import org.apache.zookeeper.WatchedEvent;
      import org.apache.zookeeper.Watcher;
      import org.apache.zookeeper.ZooDefs.Ids;
      import org.apache.zookeeper.ZooKeeper;
      public class IdGenerator implements Watcher {
          private static final String ZK_HOST = "localhost";
          private static final int ZK_PORT = 2181;
          private static final int SESSION_TIMEOUT = 5000;
          private static final String ID_GENERATOR_NODE = "/id_generator";
          private static final int ID_GENERATOR_EXPIRE_SECONDS = 3600;
          private long workerId = 0;
          public IdGenerator() {
              try {
                  ZooKeeper zk = new ZooKeeper(ZK_HOST + ":" + ZK_PORT, SESSION_TIMEOUT, this);
                  CountDownLatch latch = new CountDownLatch(1);
                  latch.await();
                  if (zk.exists(ID_GENERATOR_NODE, false) == null) {
                      zk.create(ID_GENERATOR_NODE, null, Ids.OPEN_ACL_UNSAFE, CreateMode.PERSISTENT);
                  }
                  workerId = zk.getChildren(ID_GENERATOR_NODE, false).size();
                  zk.create(ID_GENERATOR_NODE + "/worker_" + workerId, null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL);
              } catch (Exception e) {
                  e.printStackTrace();
              }
          }
          public long generateId() {
              ZooKeeper zk = null;
              try {
                  zk = new ZooKeeper(ZK_HOST + ":" + ZK_PORT, SESSION_TIMEOUT, null);
                  CountDownLatch latch = new CountDownLatch(1);
                  latch.await();
                  zk.create(ID_GENERATOR_NODE + "/id_", null, Ids.OPEN_ACL_UNSAFE, CreateMode.EPHEMERAL_SEQUENTIAL, (rc, path, ctx, name) -> {}, null);
                  byte[] data = zk.getData(ID_GENERATOR_NODE + "/worker_" + workerId, false, null);
                  long id = Long.parseLong(new String(data)) * 10000 + zk.getChildren(ID_GENERATOR_NODE, false).size();
                  return id;
              } catch (Exception e) {
                  e.printStackTrace();
              } finally {
                  if (zk != null) {
                      try {
                          zk.close();
                      } catch (Exception e) {
                          e.printStackTrace();
                      }
                  }
              }
              return 0L;
          }
          @Override
          public void process(WatchedEvent event) {
              if (event.getState() == Event.KeeperState.SyncConnected) {
                  System.out.println("Connected to ZooKeeper");
                  CountDownLatch latch = new CountDownLatch(1);
                  latch.countDown();
              }
          }
      }

      注意,这里使用了ZooKeeper的临时节点来协调各个工作节点,如果一个工作节点挂掉了,它的临时节点也会被删除,这样可以保证每个工作节点获得的ID是唯一的。

      本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
      作者最新文章
      编程开发
      相关文章 更多
      iPhone17
      iPhone17

      iPhone 17 Pro Max相册锁设置全攻略:给你的隐私加把“锁” 给你的iPhone 17 Pro Max相册加上一把锁,其实非常简单。只需在设置中进入“照片”选项,开启“使用面容ID”或“使用密码”,就能有效守护你的个人隐私。下面这份详细指南,带你一步步搞定。 一、为什么需要设置相册锁?

      如何设置新iPhone16?10个步骤快速完成初始配置
      如何设置新iPhone16?10个步骤快速完成初始配置

      想让新到手的iPhone 16尽快进入工作状态?核心其实很简单:跟着系统引导走,重点搞定Apple ID、面容ID、数据迁移和隐私这几项,半小时内你就能用上新手机。 1. 开机并选择语言和地区 长按侧边按钮,看到苹果标志亮起,这事儿就成了。滑动屏幕开始,第一个选择题来了:选语言和地区。别小看这一步,

      iPhone15怎么改密码?详细步骤与常见问题解答
      iPhone15怎么改密码?详细步骤与常见问题解答

      想给你的iPhone 15换个新密码?操作其实很简单:进入“设置”,找到“面容ID与密码”或“触控ID与密码”,验证旧密码后就能直接设置新密码了。 iPhone15密码修改详细步骤 拿到iPhone 15,无论是哪款型号,修改密码的路径都设计得非常直观。整个过程就在“设置”里完成,跟着下面的步骤走,

      php72w redis,docker php7安装php-redis
      php72w redis,docker php7安装php-redis

      在Docker环境下为PHP安装Redis扩展:手动编译需下载源码、安装phpize、配置编译并安装,生成redis.so并在php.d目录新建redis.ini加载,重启PHP-FPM;也可直接yum安装php72w-pecl-redis,免手动编译。

      php 如何配置 redis,php 如何设置redis
      php 如何配置 redis,php 如何设置redis

      配置PHP的Redis扩展:先安装Redis服务,从GitHub下载phpredis源码,用phpize编译安装,修改php.ini添加extension=redis.so,重启php-fpm或Apache,通过phpinfo验证并连接Redis。

      屏下Face ID有什么优势?苹果iPhone何时会有屏下Face ID?
      屏下Face ID有什么优势?苹果iPhone何时会有屏下Face ID?

      苹果屏下FaceID因传感器难题推迟至2025年,屏下TouchID优先级较低。新方案融合短波红外线与光学系统,支持指纹识别及血氧等健康监测,识别速度更快。

      屏下Face ID有什么优势?iPhone 15系列会有Face ID吗?
      屏下Face ID有什么优势?iPhone 15系列会有Face ID吗?

      苹果对Face ID的执着,业内一直有目共睹。当安卓厂商早已全面铺开屏下指纹技术时,苹果依然坚持“安全第一”的路线,宁愿砸下更高成本研发屏下Face ID,也不肯回头用指纹识别。 所谓屏下Face ID,就是把Face ID所需的传感器藏在屏幕下方——类似屏下摄像头的思路——让用户再也看不到iPho

      屏下Face ID摄像头有什么优点?哪款iPhone会配备屏下Face ID摄像头?
      屏下Face ID摄像头有什么优点?哪款iPhone会配备屏下Face ID摄像头?

      苹果计划明年在iPhone16Pro上首次应用屏下FaceID技术,彻底移除刘海和灵动岛,仅保留前置摄像头单打孔,实现真正全面屏视觉体验,大幅提升屏占比与一体感。

      面容ID不可用怎么办?iPhone升级iOS 16后Face ID不能用解决办法
      面容ID不可用怎么办?iPhone升级iOS 16后Face ID不能用解决办法

      升级iOS16后,部分iPhone的面容ID提示不可用。首先建议重启设备,其次更新系统,然后揭下贴膜并擦拭传感器,最后尝试恢复出厂设置。若因摔落或进水导致硬件损坏,则需联系苹果售后维修。同时还可检查面容设置、强制重启,并备份数据。

      升级iOS 16 后 Face ID不可用怎么办?
      升级iOS 16 后 Face ID不可用怎么办?

      升级iOS16后部分iPhone用户遭遇FaceID不可用提示,原因不明且苹果未发布官方说明。可通过检查更新、面容ID设置、确认无遮挡、重启设备、添加替用外貌、重设面容ID或联系支持等九种方法尝试解决。

      查看更多
      精品专题 更多
      装机必备
      装机必备

      正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

      Windows
      Windows

      正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

      PDF教程
      PDF教程

      正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

      Mac软件 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      Aperty macOS版
      Aperty macOS版
      macOS

      Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

      WINDOWS 更多
      讯飞智作 网页版
      讯飞智作 网页版
      Windows/ macOS/ Linux

      讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

      火山引擎 网页版
      火山引擎 网页版
      Windows/ macOS/ Linux

      火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

      PixTV 网页版
      PixTV 网页版
      Windows

      PixTV 是一款在浏览器中使用的 AI 视觉内容创作平台,提供图片、视频、音频、文字生成、AI 分镜、局部重绘、提示词反推和无限画布等工具,适合短剧、漫剧、广告及社交媒体内容制作。

      即将离开本站
      您即将前往第三方网站,请确认是否继续?