分布式系统 ID 生成器实现方案

版权声明:本文为博主原创文章,如需转载请注明原文出处: https://blog.csdn.net/u010979642/article/details/90727289

分布式系统 ID

一个唯一 ID 在一个分布式系统中是非常重要的一个业务属性,其中包括一些如订单 ID,消息 ID ,会话 ID,他们都有一些共有的特性:

  • 全局唯一(唯一标识某个请求,某个业务)
  • 趋势递增

解决方案

基于数据库

可以利用 MySQL 中的自增属性 auto_increment 来生成全局唯一 ID,也能保证趋势递增。 但这种方式太依赖 DB,如果数据库挂了那就非常容易出问题

水平扩展改进

可以将数据库水平拆分,如果拆为了两个库 A 库和 B 库。 A 库的递增方式可以是 0 ,2 ,4 ,6。B 库则是 1 ,3 ,5 ,7。这样的方式可以提高系统可用性,并且 ID 也是趋势递增的

存在的问题:

  • 想要扩容增加性能变的困难,之前已经定义好了 A B 库递增的步数,新加的数据库不好加入进来,水平扩展困难
  • 也是强依赖与数据库,并且如果其中一台挂掉了那就不是绝对递增了

本地 UUID 生成

还可以采用 UUID 的方式生成唯一 ID,由于是在本地生成没有了网络之类的消耗,所有效率非常高

存在的问题:

  • 生成的 ID 是无序性的,不能做到趋势递增
  • 由于是字符串并且不是递增,所以不太适合用作主键

采用本地时间

这种做法非常简单,可以利用本地的毫秒数加上一些业务 ID 来生成唯一ID,这样可以做到趋势递增,并且是在本地生成效率也很高

存在的问题:

  • 当并发量足够高的时候唯一性就不能保证了

Redis 生成 ID

依赖于 Redis 是单线程的,所以可以用来生成全局唯一的 ID。 可以使用 Redis 的原子性操作 INCR 和 INCRBY 来实现。

可以使用 Redis 集群方案来获取更高的吞吐量。

假如一个 Redis Cluster 中有5台 Redis 节点,可以初始化每个 Redis 节点的值分别为1,2,3,4,5, 然后步长都是5, 各个 Redis 节点生成的 ID为:

  • node_1: 1, 6, 11, 16, 21 …
  • node_2: 2, 7, 12, 17, 22 …
  • node_3: 3, 8, 13, 18, 23 …
  • node_4: 4, 9, 14, 19, 24 …
  • node_5: 5, 10, 15, 20, 25 …

优点:

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

缺点:

  • 果系统中没有Redis,还需要引入新的组件,增加系统复杂度
  • 需要编码和配置的工作量比较大

Twitter 雪花算法

Twitter的分布式自增ID算法snowflake (Java版)

猜你喜欢

转载自blog.csdn.net/u010979642/article/details/90727289