1.什么是分布式ID在分布式系统中,往往需要一些全局唯一的ID来唯一标识数据、消息、http请求等,那么这个全局唯一ID称为分布式ID2。为什么需要分布式ID1?如果我们对id使用数据库的自增长类型,在分布式系统中需要分库分表时,会出现两张相同的表,可能会出现主键冲突。2、电商订单号采用自增方式,是最简单的生成规则。但!这个与序列号相同的订单号很容易被竞争对手看到,从而看到贵公司的真实经营信息。3、分布式ID需要满足什么条件全局唯一:必须保证ID全局唯一高性能:高可用低延迟,ID生成响应要快,否则会成为业务瓶颈高可用:100%可用alie是的,但也需要无限接近100%的可用性和良好的可访问性:要坚持开箱即用的设计原则,系统设计和实现要尽可能简单,具体视具体业务而定场景,一般对安全性要求不高:如果不断生成ID,必然会泄露业务信息,甚至可能被猜到,所以一定不能有规则和违规行为。易读性:不要太长。试想一下,用户在售后服务的时候心情很焦躁,要他报/录很长的订单号,很容易造成很高的错误率。这个时候,只能是惹是生非。如果订单号太长,还有一个办法:断句。可扩展性:淘宝订单号原来是12位或14位,现在变成了16位。随着一个网站的交易量逐年增加,订单号必然会变长。4.分布式ID生成方式UUID数据库自增ID数据库多主模式数段模式Redis雪花算法(SnowFlake)美团(Leaf)注:主流的ID生成方案都是基于数据库数段模式和雪花算法5.优点和缺点1.基于UUID优点:简单,本地生成,无网络消耗,独特缺点:字符串无序,无趋势自增特性,无具体业务意义长度太长16bytes128bits,36bitslengthstring,storage和查询消耗大量的MySQL性能。MySQL官方建议主键越短越好。UUID作为数据库主键的乱序会导致数据位置频繁变化,严重影响性能。2、基于数据库自增ID当我们需要ID时,往表中插入一条记录,返回主键ID,但是这种方式有一个致命的缺点。当访问量激增时,MySQL本身就是系统的瓶颈。用它来实现分布式服务的风险比较高,所以不推荐!优点:实现简单,ID单调递增,数值类型查询速度快缺点:DB存在单点宕机风险,无法应对高并发场景3.基于前面提到的数据库集群模式单点数据库的方式不可取,所以对上面的方式做一些高可用的优化,换成主从模式的集群。如果怕其中一个master节点失效不能用,那就创建一个双主模式的集群,即两个Mysql实例可以独立产生自增ID。那么就会有问题。两个MySQL实例的自增ID都是从1开始的,出现重复ID怎么办?解决方法:设置初始值和自增步长MySQL_1配置:set@@auto_increment_offset=1;--startvalueset@@auto_increment_increment=2;--stepsizeMySQL_2配置:set@@auto_increment_offset=2;--startvalue设置@@auto_increment_increment=2;添加的ID分别是:1、3、5、7、92、4、6、8、10,如果集群后的性能还是无法应对高并发怎么办?需要扩容MySQL,增加节点,比较麻烦。事物。添加第三个MySQL实例,需要手动修改第一和第二个MySQL实例的初始值和步长,并将第三个机器的ID生成位置设置得远于已有的最大自增ID位置。但必须在第一个和第二个MySQL实例ID还没有增加到第三个MySQL实例的初始ID值时,否则自增ID会重复,必要时可能需要停止修改。优点:解决了DB单点的问题缺点:不利于后续的扩展,而且其实单库本身的压力还是很大的,还是不能满足高并发的场景。4、基于数据库的号段模式号段模式是目前分布式ID生成器的主流实现方式之一。号段模式可以理解为从数据库中批量获取自增ID,每次从数据库中取出一个范围的号段。例如(1,1000]代表1000个ID,具体业务服务会根据这个数段生成一个1~1000的自增ID,加载到内存中。由于可能有多个业务终端同时操作,所以采用版本号乐观锁方式更新,这种分布式ID生成方式对数据库的依赖不强,不频繁访问数据库,对数据库的压力小很多。5、基于Redis模式,使用redis的incr命令实现ID的原子自增。127.0.0.1:6379>setseq_id1//初始化自增ID为1OK127.0.0.1:6379>incrseq_id//增加1,返回增加后的值(整数)2需要注意redis的实现,考虑redis改造的持久化问题。Redis有两种持久化方式:RDB和AOFRDB会周期性的做快照进行持久化。如果自增继续但redis没有及时持久化,Redis会挂掉,重启Redis后会出现ID重复。AOF会持久化每个写命令。即使Redis挂了,也不会出现重复ID。但是由于incr命令的特殊性,Redis重启恢复数据的时间会过长。6、基于雪花算法(Snowflake)模式雪花(Snowflake)是twitter内部分布式项目采用的ID生成算法。Snowflake生成一个Long类型ID。Long类型占8个字节,每个字节占8个字节。位,也就是说一个Long类型占64位。SnowflakeID组成结构:正数(1位)+时间戳(41位)+机器ID(5位)+数据中心(5位)+自增值(12位),共64位ALong类型。第一位(1bit):Java中long的最高位是符号位,代表正或负。正数为0,负数为1。一般生成的ID为正数,所以默认为0。时间戳部分(41bit):毫秒级时间,不建议保存当前时间戳,但使用(当前时间戳-固定开始时间戳)之间的差异,以便生成的ID可以从较小的值开始;41位时间戳可以使用69年,(1L<<41)/(1000L*60*60*24*365)=69年Workmachineid(10bit):也叫workId,这个可以灵活配置,电脑roomormachinenumber任何组合都可以。序号部分(12bit),支持自增,同一个节点可以在同一毫秒内生成4096个ID按照这个算法的逻辑,只需要用Java语言实现这个算法,封装成一个工具方法,那么每个业务应用都可以直接使用该工具方法获取分布式ID,只需要保证每个业务应用都有自己的工作机id,而不需要单独构建一个应用来获取分布式ID。雪花算法目前存在时间回调问题,不同机器不能完全保证相同时间,因此可能会出现重复问题。7.Meituan(Leaf)Leaf由美团开发。支持数段模式和雪花算法模式,可切换。
