通常在分布式系统中,有生成唯一ID的需求,唯一ID有多种实现方式。我们选择其中几种,简单阐述一下实现原理、适用场景、优缺点等信息。
目录
- 数据库多主复制
- UUID
- 工单服务器
- 雪花算法
- 总结
数据库多主复制
数据库通常有自增属性,在单机数据库场景中自增的步长通常是1。但是,在分布式场景中,往往存在多个数据库,此时数据库自增的步长不再是1,而应该是k, k为数据库的个数。
例如有三个数据中心,A,B,C。那么步长应该为3 ,A生成的ID依次是1, 4,7, …;B生成的ID为 2,5,8,… ;C生成的步长为3,6,9…
缺点:无法灵活扩展或者收缩,当需要增加或者减少数据库数量时,调整步长会很麻烦,需要额外的同步和协作。升成的唯一ID可能是不连续的,非递增的。
适用场景:适合数据中心数量稳定,且不要求ID单调增的场景。
UUID
UUID是一个128位数据,且重复的概率极低,可忽略不计。有很多现成的接口可供调用。
UUID与时间、识别号等信息有关,也有多种格式,如GUID、标准UUID等。具体的详细信息,请参考文章https://zhuanlan.zhihu.com/p/438580928
优点:生成简单,不需要各个服务器之间协同。可以任意扩展服务器数量,而不受影响。
缺点:ID是非单调增的,不连续的。ID是非数字的,可能包含字母。
工单服务器
工单服务器由Flicker公司实现。一个Flickr 的Ticket服务器只包含一个独立的MySQL数据库服务,结合MySQL的[“REPLACE INTO”]http://dev.mysql.com/doc/refman/5.0/en/replace.html扩展,就能获取到一个ID。
详细的原理和使用方法请参考文章:Ticket Servers: Distributed Unique Primary Keys on the Cheap[https://code.flickr.net/2010/02/08/ticket-servers-distributed-unique-primary-keys-on-the-cheap/]。文中也讲述了单点故障问题的解决方法。笔者对此文也进行了简单的翻译概括,有兴趣的话可以前去查阅https://blog.csdn.net/hg_zhh/article/details/137588387
优点:ID是单调增的,是纯数字的,容易实现,更适合中小型应用。
缺点:可能存在单点故障,官方虽然给了解决方法,但是也正如官方所说的,不够优雅。
雪花算法
雪花算法由推特公司(如今的X公司)实现。这里就不详细介绍了,相信很多大佬讲解的更好更详细。主要思想是,将ID分成多个部分,每个部分单独生成,这样就很大程度避免了重复问题。雪花算法将64位的ID分成了五部分:
具体每个部分的长度,可以根据实际需要灵活调整。
优点:ID是纯数字的,ID是单调增的,适合中大型服务。
缺点:分布式场景中时间不同步,会导致生成ID存在偏差。如果发生始终回拨,会导致生成的ID错乱,典型的例子就是NSQ消息队列中使用雪花算法生成消息ID,但是当时间变化时,直接导致消息队列不工作,坑苦了我们!!
总结
该文只是简单的总结了一些不同的唯一ID生成方法,可能不全面,不能说哪个一定好,哪个一定差,关键是找到合适自己的,也可以在已有的方法上做针对性修改。如果文中有错误,请各位批评指正!