分布式ID生成器的解决方案总结

  在互联网的业务系统中,涉及到各类各样的ID,如在支付系统中就会有支付ID、退款ID等。那通常生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,咱们应该采用哪一种适合本身的解决方案是十分重要的。下面咱们一一来列举一下,不必定所有适合,这些解决方案仅供你参考,或许对你有用。html

  一个ID通常来讲有下面几种要素:node

  惟一性:确保生成的ID是全网惟一的。git

  有序递增性:确保生成的ID是对于某个用户或者业务是按必定的数字有序递增的。github

  高可用性:确保任什么时候候都能正确的生成ID。算法

  带时间:ID里面包含时间,一眼扫过去就知道哪天的交易。数据库

  系统时间毫秒数数组

  咱们可使用当前系统时间精确到毫秒数+业务属性+用户属性+随机数+...等参数组合形式来确保ID的惟一性,缺点是ID的有序性难以保证,要保证有序性就要依赖数据库或者其余中间存储媒介。安全

  UUID分布式

  Java自带的生成UUID的方式就能生成一串惟一随机32位长度数据,并且够咱们用N亿年,保证惟一性确定是不用说的了,但缺点是它不包含时间、业务数据可读性太差了,并且也不能ID的有序递增。性能

  这是一种简单的生成方式,简单,高效,但在通常业务系统中我还没见过有这种生成方式。

  数据库自增ID

  咱们都知道为数据库主键设置自增序号,以必定的趋势自增,以保证主键ID的惟一性。

  这个方案很简单,但最主要的问题在于依赖数据库自己,这就无形增长了对数据库的访问压力和依赖,一旦对单库进行分库分表或者数据迁移就尴尬了。

  因此,这也不是合适的ID生成方法。

  批量生成ID

  一次按需批量生成多个ID,每次生成都须要访问数据库,将数据库修改成最大的ID值,并在内存中记录当前值及最大值。这样就避免了每次生成ID都要访问数据库并带来压力。

  这种方案服务就是单点了,若是服务重启势必会形成ID丢失不连续的状况,并且这种方式也不利于水平扩展。

  中间件

  Redis的全部命令操做都是单线程的,自己提供像incr这样的自增命令,因此能保证生成的ID确定是惟一有序的。

  这种方式不依赖关系数据库,并且速度快。但系统要引入Redis这一中间件,增长维护成本,并且编码和配置工做量比较大。即便已经有了Redis组件,但生成ID的高频率访问对单线程的Redis性能势必也会形成影响。

  还能够利用像Zookeeper中的znode数据版原本生成序列号,及MongoDB的ObjectId等,这种利用中间件的作法不是很推荐。

  snowflake算法

  

https://img4.mukewang.com/5d30793e000156eb06310263.jpg


  image

  如上图的所示,Twitter的snowflake算法下面几部分组成:

  41位的时间序列,精确到毫秒,可使用69年

  10位的机器标识,最多支持部署1024个节点

  12位的序列号,支持每一个节点每毫秒产生4096个ID序号,最高位是符号位始终为0。

  这种方案性能好,在单机上是递增的,可是因为涉及到分布式环境,每台机器上的时钟不可能彻底同步,也许有时候也会出现不是全局递增的状况。

  并且这个项目在2010就中止维护了,但这个设计思路仍是应用于其余各个ID生成器及变种。

  UidGenerator

  UidGenerator是百度开源的分布式ID生成器,基于于snowflake算法的实现,看起来感受还行。不过,国内开源的项目维护性真是担心。

  你们能够参考具体使用:

  https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md

  Leaf

  Leaf是美团开源的分布式ID生成器,能保证全局惟一性、趋势递增、单调递增、信息安全,里面也提到了几种分布式方案的对比,但也须要依赖关系数据库、Zookeeper等中间件。

  具体能够参考官网说明:

  https://tech.meituan.com/MT_Leaf.html

  好了,就这么多了,不一样的方案应用的场景和系统也是不一样的。你们有更好的方案也能够在下面留言,一块儿讨论下你们都是怎么作的。

相关文章
相关标签/搜索