您的位置:首页 > 运维架构 > 网站架构

(三)架构篇之分布式id生成策略

2018-10-24 13:58 260 查看
版权声明:版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_37465368/article/details/83342631

 

分布式系统常见的一种场景就是要求id全局唯一,以下介绍七种,并分析优劣。

1、利用数据库自增id特性。

优点:

1)简单。

2)ID有序排列,分页和排序方便,方便统计数据增长。

缺点:

1)可用性难以保证:数据库常见架构是一主多从+读写分离,生成自增ID是写请求,主库挂了就玩不转了

2)扩展性差,性能有上限:因为写入是单点,数据库主库的写性能决定ID的生成性能上限,并且难以扩展

改进方法:

1)增加主库,避免写入单点

2)数据水平切分,保证各主库生成的ID不重复

2、UUID

常见的方式。可以利用数据库也可以利用程序生成,一般来说全球唯一。

优点:

1)简单,代码方便。

2)生成ID性能非常好,基本不会有性能问题。

3)全球唯一,在遇见数据迁移,系统数据合并,或者数据库变更等情况下,可以从容应对。

缺点:

1)没有排序,无法保证趋势递增。

2)UUID往往是使用字符串存储,查询的效率比较低。

3)存储空间比较大,如果是海量数据库,就需要考虑存储量的问题。

4)传输数据量大

5)不可读。

3、取当前毫秒数

uuid是一个本地算法,生成性能高,但无法保证趋势递增,且作为字符串ID检索效率低

取当前毫秒数是一种常见方案:uint64 ID = GenTimeMS();

优点:

(1)本地生成ID,不需要进行远程调用,时延低

(2)生成的ID趋势递增

(3)生成的ID是整数,建立索引后查询效率高

缺点:

如果并发量超过1000,会生成重复的ID(1s=1000ms)

不能保证ID的唯一性。当然,使用微秒可以降低冲突概率,但每秒最多只能生成1000000个ID,再多的话就一定会冲突了,所以使用微秒并不从根本上解决问题。

 

优化:使用GUID生成前十位+GUID生成的时间(6位)

 

4、Redis生成id

       当使用数据库来生成ID性能不够要求的时候,我们可以尝试使用Redis来生成ID。这主要依赖于Redis是单线程的,所以也可以用生成全局唯一的ID。可以用Redis的原子操作 INCR和INCRBY来实现。

优点:

1)性能优。

2)ID有序排列,分页和排序方便,方便统计数据增长。

缺点:

1)如果系统中没有Redis,还需要引入新的组件,增加系统复杂度。

2)需要编码和配置的工作量比较大。

 

5、流弊到不行的twitter开源的的snowflake算法

这是目前比较好的一个分布式唯一id的生成办法。

开源地址:https://github.com/twitter-archive/snowflake

建议在大型架构过程中,id生成器单独抽离出来做成一个服务。

我自己写的一个使用snowflake的服务: https://github.com/skyywj/Id-Service

核心思想是:使用41bit作为毫秒数,10bit作为机器的ID(5个bit是数据中心,5个bit的机器ID),12bit作为毫秒内的流水号(意味着每个节点在每毫秒可以产生 4096 个 ID),最后还有一个符号位,永远是0

使用:

[code]//获取一个id接口
long snowflakeNextId()
//获取count个id接口
long[] snowflakeNextIds(int count) throws InvalidSystemClock;

优点:

[code]快,一秒大约可生成。
没有啥依赖,实现也特别简单。
知道原理之后可以根据实际情况调整各各位段,方便灵活。

缺点:

只能趋势递增。(有些也不叫缺点,网上有些如果绝对递增,竞争对手中午下单,第二天在下单即可大概判断该公司的订单量,危险!!!)
依赖机器时间,如果发生回拨会导致可能生成id重复。
 

6. 利用zookeeper生成唯一ID

zookeeper主要通过其znode数据版本来生成序列号,可以生成32位和64位的数据版本号,客户端可以使用这个版本号来作为唯一的序列号。很少会使用zookeeper来生成唯一ID。主要是由于需要依赖zookeeper,并且是多步调用API,如果在竞争较大的情况下,需要考虑使用分布式锁。因此,性能在高并发的分布式环境下,也不甚理想。

7. MongoDB的ObjectId


       MongoDB的ObjectId和snowflake算法类似。它设计成轻量型的,不同的机器都能用全局唯一的同种方法方便地生成它。MongoDB 从一开始就设计用来作为分布式数据库,处理多个节点是一个核心要求。使其在分片环境中要容易生成得多。

 

阅读更多
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: