分布式ID
2023-06-03 16:33:08 6 举报
AI智能生成
分布式ID是用于在分布式系统中生成唯一标识符的一种方法。它能够保证在多个节点和服务器之间生成的ID是唯一且不重复的,从而避免了数据冲突和混乱。常见的分布式ID生成算法包括雪花算法、UUID等。这些算法通常基于时间戳、机器IP地址、序列号等信息进行组合生成,以确保ID的唯一性和有序性。分布式ID的实现需要考虑高并发、高可用性等因素,以保证系统的稳定性和可靠性。在实际应用中,分布式ID常常用于订单号、用户ID、消息队列等场景,为系统提供了唯一的标识和管理手段。
作者其他创作
大纲/内容
概述
什么是分布式ID?
在我们业务数据量不大的时候,单库单表完全可以支撑现有业务,数据再大一点搞个MySQL主从同步读写分离也能对付。<br><br>但随着数据日渐增长,主从同步也扛不住了,就需要对数据库进行 <b>分库分表</b>,但分库分表后需要有一个唯一ID来标识一条数据,数据库的自增ID显然不能满足需求;特别一点的如订单、优惠券也都需要有<b>唯一ID</b>做标识。此时一个能够生成<b>全局唯一ID</b>的系统是非常必要的。那么这个<b>全局唯一ID</b>就叫<b>分布式ID</b>
分布式ID需要满足哪些条件?
<b>全局唯一:</b>必须保证ID是全局性唯一的,基本要求
<b>高性能:</b>高可用低延时,ID生成响应要块,否则反倒会成为业务瓶颈
<b>高可用:</b>100%的可用性是骗人的,但是也要无限接近于100%的可用性
<b>好接入:</b>要秉着拿来即用的设计原则,在系统设计和实现上要尽可能的简单
<b>趋势递增:</b>最好趋势递增,这个要求就得看具体业务场景了,一般不严格要求
常用的分布式ID方案
UUID
优点
生成足够简单,本地生成无网络消耗,具有唯一性
缺点
<ul><li><b>无序</b>的字符串,<b>不具备趋势自增特性</b></li><li>没有具体的业务含义</li><li>长度过长16 字节128位,36位长度的字符串,<b>存储以及查询对MySQL的性能消耗较大</b>,MySQL官方明确建议<b>主键要尽量越短越好</b>,作为数据库主键 <font color="#e74f4c">UUID 的无序性会导致数据位置频繁变动,严重影响性能</font>。</li><li>插入性能低</li><li><b>数据库优化 : 无法排序</b></li></ul>
<font color="#a66a30">归根结底还是Mysql的索引结构问题,详细看Mysql索引原理</font>
基于数据库自增ID
基于数据库的<font color="#e74f4c">auto_increment</font>自增ID完全可以充当分布式ID
数据库的自增原理看Mysql原理
优点
实现简单,ID单调自增,数值类型查询速度快
缺点
DB单点存在宕机风险,无法扛住高并发场景
基于数据库集群模式
多个MySQL实例的自增ID都从1开始,会生成重复的ID怎么办?
解决方案:设置<b>起始值</b>和<b>自增步长</b>`
那如果集群后的性能还是扛不住高并发咋办?就要进行MySQL扩容增加节点,这是一个比较麻烦的事。
优点
解决DB单点问题
缺点
<b>不利于后续扩容</b>,而且实际上单个数据库自身压力还是大,依旧无法满足高并发场景
基于数据库的号段模式
号段模式可以理解为从数据库批量的获取自增ID,每次从数据库取出一个号段范围
基于Redis模式
Redis也同样可以实现,原理就是利用redis的 <font color="#e74f4c">incr </font>命令实现ID的<b>原子性自增</b>
Redis也可以采取号段模式, 每次拿一个步长的数据。 <font color="#a23c73"> incr by step</font>
基于雪花算法(Snowflake)模式
Snowflake生成的是<b>Long类型的ID</b>,一个Long类型占<font color="#e74f4c">8个字节</font>,每个字节占8比特,也就是说一个Long类型占64个比特。
Snowflake ID组成结构:<b>正数位</b>(占1比特)+ <b>时间戳</b>(占41比特)+ <b>机器ID</b>(占5比特)+ <b>数据中心</b>(占5比特)+ <b>自增值</b>(占12比特),总共64比特组成的一个Long类型。
<b>第一个bit位(1bit)</b>:java中long的最高位是符号位<font color="#e74f4c">代表正负</font>,正数是0,负数是1,一般生成ID都为正数,所以默认为0。
<b>时间戳部分(41bit)</b>:毫秒级的时间,不建议存当前时间戳,而是用(当前时间戳 - 固定开始时间戳)的差值,可以使产生的ID从更小的值开始;<font color="#e74f4c">41位的时间戳可以使用69年</font>,(1L << 41) / (1000L *60* 60 *24* 365) = 69年
<b>工作机器id(10bit)</b>:也被叫做`workId`,这个可以灵活配置,机房或者机器号组合都可以。(`机器ID + 数据中心`)
<b>序列号部分(12bit)</b>,自增值支持同一毫秒内同一个节点可以生成 `<font color="#e74f4c">4096</font>` 个ID <font color="#e74f4c">2^12`</font>
<font color="#e74f4c"><b>同一机器同一时间截(毫秒)内产生的 4096 个ID序号 (极大程度上避免了分布式ID生产问题)</b></font>
缺点
<font color="#e74f4c">依赖机器时钟</font>,如果机器时钟回拨,会导致重复ID生成;
在单机上是递增的,但是由于设计到分布式环境,每台机器上的时钟不可能完全同步,有时候会出现不是全局递增的情况(此缺点可以认为无所谓,一般分布式ID只要求`<font color="#e74f4c">趋势递增</font>`,并不会严格要求递增,90%的需求都只要求趋势递增)。
<b>百度(uid-generator)</b>
<b>uid-generator是基于Snowflake算法实现的</b>,与原始的snowflake算法不同在于,uid-generator支持<font color="#e74f4c">自定义时间戳</font>、<font color="#e74f4c">工作机器ID</font>`和 序列号 等各部分的位数,而且`uid-generator`中采用用户自定义`workId`的生成策略。
<font color="#e74f4c">uid-generator需要与数据库配合使用</font>,需要新增一个WORKER_NODE表。当应用启动时会向数据库表中去插入一条数据,插入成功后返回的自增ID就是<b>该机器的workId数据由host,port组成。</b>
官方文档
美团(Leaf)
Leaf`同时支持<b>号段模式</b>和<b>snowflake</b>算法模式
号段模式
snowflake 模式
滴滴(Tinyid)
0 条评论
下一页