ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

一文读懂分布式唯一ID生成

2019-07-29 11:55:21  阅读:163  来源: 互联网

标签:缓存 数据库 生成 读懂 QPS 递增 ID 分布式


很多大的互联网公司数据量很大,都采用分库分表,那么分库后就需要统一的唯一ID进行存储。这个ID可以是数字递增的,也可以是UUID类型的。

如果是递增的话,那么拆分了数据库后,可以按照id的hash,均匀的分配到数据库中,并且mysql数据库如果将递增的字段作为主键存储的话会大大提高存储速度。但是如果把订单ID按照数字递增的话,别人能够很容易猜到你有多少订单了,这种情况就可以需要一种非数字递增的方式进行ID的生成。

想到分布式ID的生成,大家可能想到采用Redis进行生成ID,使用Redis的INCR命令去生成和获取这个自增的ID,这个没有问题,但是这个INCR的生成QPS速度为200400(官网发布的测试结果),也就是20W这样子,如果QPS没有超过这些的话,显然使用Redis比较合适。

那么我们对于要达到高可用,高QPS,低延迟我们有没有更好的想法呢。接下来一起看一下snowflake算法,由twitter公司开源的雪花算法。

一文读懂分布式唯一ID生成

snowflake一共64位:
  • 1.第一位不用。

  • 2. 41位是时间戳。 2^41以毫秒为单位的话,可得到69年,非常够用了。

  • 3. 10位位工作机器,可以有2^10=1024个工作节点,有的公司将其拆分为5位工作中心编码,5位分给工作机器。

  • 4. 最后12位用于生成递增数据共4096个数。

如果用这个理论上的QPS上的QPS为409W/S。

这种方式的优点为:
  • 1. QPS非常高,性能也非常够。高性能条件也满足了。

  • 2. 不需要依赖其他第三方的中间件,比如Redis。少了依赖,可用率提高了。

  • 3. 可以根据自己定制进行调节。也就是里边的10位进行自由分配。
缺点:

此种算法很依赖时钟,假如时钟进行回拨了,将有可能生成相同的ID。

UUID是采用32位二进制数据生成的,它生成的性能非常好,但是它是基于机器MAC地址生成的,而且不是分布式的,所以不是咱们讨论的范畴。

  下面咱们看一下一些大公司的分布式ID实现机制,通过生成创建一张表,采用8个Byte, 64位进行存储使用,用这张表记录所产生ID的位置,比如ID从0开始,然后使用了1000个,那么数据库里边记录里边的最大值是一千,同时还有个步长值,比如1000,那么获取下一个值得时候最大值为2001,即最大的没有使用的值。

具体的实现步骤如下:
  • 1. 提供一个生成分布式ID的服务,这个ID的服务是读取数据库里边的值和步长值计算生成需要的值和范围,然后服务消费方拿到后进行将号段存储到缓存中使用。

  • 2.当给到服务调用方之后,数据库立即更新数据。
这种情况下的优点为:
  • 1.  容灾性能好,如果DB出现问题,因为数据放到内存中,还是可以支撑一段时间。

  • 2. 8个Byte可以满足业务生成ID使用。

  • 3. 最大值可以自己定义,这样有些迁移的业务还可以自己定义最大值继续使用。
当然缺点也存在:
  • 1. 当数据库挂了整个系统将不能使用。

  • 2. 号段递增的,容易被其他人猜到。

  • 3. 如果很多服务同时访问获取这个ID或者网络波动导致数据库IO升高的时候,系统稳定性会出现问题。

然后针对上述情况的解决方法是他们采用了双缓存机制,即将号码段读取到内存中之后开始使用,当使用到了10%的时候重新启动一个新线程,然后当一个缓存用完了之后去用另一块缓存的数据。当另一个缓存的数据达到10%的时候再重启激动一个新线程获取,依次反复。

这样做的好处是避免同时访问大量数据库,导致I/O增多。同时可以通过两个缓存段解决了单一缓存导致很快用完的情况。当然把这个号段设置成QPS大小的600倍,这样数据库挂了10-20分钟内还是可以继续提供服务的。

以上一直提到了一个问题,就是ID递增,咱们如何解决这个问题呢。就是采用snowflake,然后解决里边的时钟问题,有些公司采用ZK去比较当前workerId也就是节点ID使用的时间是否有回拨,如果有回拨就进行休眠固定时间,看是否能赶上时间,如果能赶上的话,继续生成ID,如果一直没有赶上达到某个值得话,那么就报错处理。因为中间10位是表示不同的节点,那么不同的节点生成的ID就不会存在递增的情况。

这些思路都是某公司已经实现了的,如果有兴趣继续研究的话,那么在GITHUB上搜索下开源的Leaf可以直接拿着使用的。

标签:缓存,数据库,生成,读懂,QPS,递增,ID,分布式
来源: https://blog.51cto.com/14230003/2424482

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有