• 3


    对于分布式系统,生成 唯一ID的方法,大致分为3类:
    (1)UUID
    (2)依赖数据库的 flicker 方案
    (3)twitter 的 snowflake 算法
     
    后面要介绍一种 阿里的 TDDL 中的方案,同样依赖数据库,但是比 Flicker 性能更高
     
    此外,很多公司实际上是采用分布式ID生成系统来解决这种问题的,放弃了对网络IO方面的考虑,做到统一管理,这种方式有利有弊,美团,达达都是采用这种方式,这个问题要怎么看呢,如果服务宕掉,问题还是挺大的。
     
     
     
    UUID

    UUID是通用唯一识别码 (Universally Unique Identifier),在其他语言中也叫GUID,可以生成一个长度32位的全局唯一识别码。
    String uuid = UUID.randomUUID().toString()
    结果示例:
    046b6c7f-0b8a-43b9-b35d-6489e6daee91
     
    缺点:
    • 对于无序的 UUID,如果需要插入 mysql 的话,一般情况下 UUID 是作为主键 的。由于 MySQL 的存储是采用 B+ 树实现的,所以最好要自增,否则对于树扩展的性能会有影响,而且也会造成节点数据不均匀。从存储性能的角度来看的话,这种方法存在一定的弊端
    • UUID 16个字节,128位长,通常以 36个字节的字符串表示,能否缩短这个长度?
     
    Flicker方案

    • 使用 MySQL 自身的特性实现自增,如果想要提高性能,可以用多个库/表,设置步长,第一个表1,4,7,10…,第二个表2,5,8,11…,第三个表3,6,9,12… 这种方式能够加快 id 生成。
    • 使用 Redis ,同样也可以分布到多个 key 上。
     
    缺点:
    • 这种方式依赖于数据库
    • 每次获取唯一 ID 都需要 IO 操作
     
    SnowFlake方案

     
     
    SnowFlake所生成的ID一共分成四部分:
    1.第一位
    占用1bit,其值始终是0,没有实际作用。
    2.时间戳
    占用41bit,精确到毫秒,总共可以容纳约140年的时间。
    3.工作机器id
    占用10bit,其中高位5bit是数据中心ID(datacenterId),低位5bit是工作节点ID(workerId),做多可以容纳1024个节点。
    4.序列号
    占用12bit,这个值在同一毫秒同一节点上从0开始不断累加,最多可以累加到4095。
     
    第一位一般用做符号位
     
    可以看到这是 64位,比 UUID 要缩短一半。而如果用16进制表示,也只用了16个字节,要比36个字节短很多
     
    SnowFlake算法在同一毫秒内最多可以生成多少个全局唯一ID呢?只需要做一个简单的乘法:
    同一毫秒的ID数量 = 1024 X 4096 =  4194304
    这个数字在绝大多数并发场景下都是够用的。
     
    有几点需要解释一下:
    1.获得单一机器的下一个序列号,使用Synchronized控制并发,而非CAS的方式,是因为CAS不适合并发量非常高的场景。对于高并发的场景,CAS 会经常失败,所以会增加读的次数。
    2.如果当前毫秒在一台机器的序列号已经增长到最大值4095,则使用while循环等待直到下一毫秒。
    3.如果当前时间小于记录的上一个毫秒值,则说明这台机器的时间回拨了,抛出异常。但如果这台机器的系统时间在启动之前回拨过,那么有可能出现ID重复的危险。可以看到对于重启来说不是很友好。
    在单机上是递增的,但是由于涉及到分布式环境,每台机器上的时钟不可能完全同步,有时候会出现不是全局递增的情况。
     
    TDDL 中的策略

    (1)使用数据库同步ID信息
    (2)每次批量去一定数量的可用ID在内存中,使用完后,再请求数据库重新获取下一批可用ID,每次获取量由步长控制
     
    相比于Flicker方案,大大降低数据库写压力,数据库不再是性能瓶颈。
     
    但是种种方式同样是强依赖数据库,当数据库异常时,系统仍然不可用。
     
     
    这篇博文给出了一种基于 SnowFlake的发号器方案
     
     
    这是美团的方案
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
     
  • 相关阅读:
    函数的逻辑读成零
    SQL逻辑读变成零
    体系结构中共享池研究
    执行计划基础 动态采样
    执行计划基础 统计信息
    识别低效率的SQL语句
    oracle 知识
    XPATH 带命名空间数据的读取
    ACTIVITI 研究代码 之 模版模式
    ACTIVITI 源码研究之命令模式执行
  • 原文地址:https://www.cnblogs.com/43726581Gavin/p/9043978.html
Copyright © 2020-2023  润新知