• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

雪花算法PHP

武飞扬头像
陈卿诺语
帮助1

简介
现在的服务基本是分布式、微服务形式的,而且大数据量也导致分库分表的产生,对于水平分表就需要保证表中 id 的全局唯一性。

对于 MySQL 而言,一个表中的主键 id 一般使用自增的方式,但是如果进行水平分表之后,多个表中会生成重复的 id 值。那么如何保证水平分表后的多张表中的 id 是全局唯一性的呢?

如果还是借助数据库主键自增的形式,那么可以让不同表初始化一个不同的初始值,然后按指定的步长进行自增。例如有3张拆分表,初始主键值为1,2,3,自增步长为3。

当然也有人使用 UUID 来作为主键,但是 UUID 生成的是一个无序的字符串,对于 MySQL 推荐使用增长的数值类型值作为主键来说不适合。

也可以使用 Redis 的自增原子性来生成唯一 id,但是这种方式业内比较少用。

当然还有其他解决方案,不同互联网公司也有自己内部的实现方案。雪花算法是其中一个用于解决分布式 id 的高效方案,也是许多互联网公司在推荐使用的。

SnowFlake 雪花算法

SnowFlake 中文意思为雪花,故称为雪花算法。最早是 Twitter 公司在其内部用于分布式环境下生成唯一 ID。在2014年开源 scala 语言版本。

雪花算法的原理就是生成一个的 64 位比特位的 long 类型的唯一 id。

  1. 最高 1 位固定值 0,因为生成的 id 是正整数,如果是 1 就是负数了。
  2. 接下来 41 位存储毫秒级时间戳,2^41/(1000*60*60*24*365)=69,大概可以使用 69 年。
  3. 再接下 10 位存储机器码,包括 5 位 datacenterId 和 5 位 workerId。最多可以部署 2^10=1024 台机器。
  4. 最后 12 位存储序列号。同一毫秒时间戳时,通过这个递增的序列号来区分。即对于同一台机器而言,同一毫秒时间戳下,可以生成 2^12=4096 个不重复 id。

可以将雪花算法作为一个单独的服务进行部署,然后需要全局唯一 id 的系统,请求雪花算法服务获取 id 即可。

对于每一个雪花算法服务,需要先指定 10 位的机器码,这个根据自身业务进行设定即可。例如机房号 机器号,机器号 服务号,或者是其他可区别标识的 10 位比特位的整数值都行。
 

  1.  
    <?php
  2.  
    /**
  3.  
    * 分布式 id 生成类 组成: <毫秒级时间戳 机器id 序列号>
  4.  
    * 默认情况下41bit的时间戳可以支持该算法使用到2082年,10bit的工作机器id可以支持1023台机器,序列号支持1毫秒产生4095个自增序列id
  5.  
    * @author zhangqi
  6.  
    */
  7.  
    class IdCreate
  8.  
    {
  9.  
    const EPOCH = 1479533469598; //开始时间,固定一个小于当前时间的毫秒数
  10.  
    const max12bit = 4095;
  11.  
    const max41bit = 1099511627775;
  12.  
     
  13.  
    static $machineId = null; // 机器id
  14.  
     
  15.  
    public static function machineId($mId = 0)
  16.  
    {
  17.  
    self::$machineId = $mId;
  18.  
    }
  19.  
     
  20.  
    public static function createOnlyId()
  21.  
    {
  22.  
    // 时间戳 42字节
  23.  
    $time = floor(microtime(true) * 1000);
  24.  
    // 当前时间 与 开始时间 差值
  25.  
    $time -= self::EPOCH;
  26.  
    // 二进制的 毫秒级时间戳
  27.  
    $base = decbin(self::max41bit $time);
  28.  
    // 机器id 10 字节
  29.  
    if(!self::$machineId)
  30.  
    {
  31.  
    $machineid = self::$machineId;
  32.  
    }
  33.  
    else
  34.  
    {
  35.  
    $machineid = str_pad(decbin(self::$machineId), 10, "0", STR_PAD_LEFT);
  36.  
    }
  37.  
    // 序列数 12字节
  38.  
    $random = str_pad(decbin(mt_rand(0, self::max12bit)), 12, "0", STR_PAD_LEFT);
  39.  
    // 拼接
  40.  
    $base = $base.$machineid.$random;
  41.  
    // 转化为 十进制 返回
  42.  
    return bindec($base);
  43.  
    }
  44.  
    }
  45.  
     
  46.  
    ?>
学新通
  1.  
    public function snowflake()
  2.  
    {
  3.  
    IdCreate::machineId(1);
  4.  
    echo IdCreate::createOnlyId();
  5.  
    }

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhhjgaea
系列文章
更多 icon
同类精品
更多 icon
继续加载