PHP生成唯一ID之SnowFlake算法


Posted in PHP onDecember 17, 2016

前言:最近需要做一套CMS系统,由于功能比较单一,而且要求灵活,所以放弃了WP这样的成熟系统,自己做一套相对简单一点的。文章的详情页URL想要做成url伪静态的格式即xxx.html 其中xxx考虑过直接用自增主键,但是感觉这样有点暴露文章数量,有同学说可以把初始值设高一点,可是还是可以通过ID差算出一段时间内的文章数量,所以需要一种可以生成唯一ID的算法。

考虑过的方法有

  1. 直接用时间戳,或者以此衍生的一系列方法
  2. Mysql自带的uuid

以上两种方法都可以查到就不多做解释了

最终选择了Twitter的SnowFlake算法

这个算法的好处很简单可以在每秒产生约400W个不同的16位数字ID(10进制)

原理很简单

ID由64bit组成

其中 第一个bit空缺

41bit用于存放毫秒级时间戳

10bit用于存放机器id

12bit用于存放自增ID

除了最高位bit标记为不可用以外,其余三组bit占位均可浮动,看具体的业务需求而定。默认情况下41bit的时间戳可以支持该算法使用到2082年,10bit的工作机器id可以支持1023台机器,序列号支持1毫秒产生4095个自增序列id。
下面是PHP源码

<?php
namespace App\Services;

abstract class Particle {
  const EPOCH = 1479533469598;
  const max12bit = 4095;
  const max41bit = 1099511627775;

  static $machineId = null;

  public static function machineId($mId = 0) {
    self::$machineId = $mId;
  }

  public static function generateParticle() {
    /*
    * Time - 42 bits
    */
    $time = floor(microtime(true) * 1000);

    /*
    * Substract custom epoch from current time
    */
    $time -= self::EPOCH;

    /*
    * Create a base and add time to it
    */
    $base = decbin(self::max41bit + $time);


    /*
    * Configured machine id - 10 bits - up to 1024 machines
    */
    if(!self::$machineId) {
      $machineid = self::$machineId;
    } else {
      $machineid = str_pad(decbin(self::$machineId), 10, "0", STR_PAD_LEFT);
    }
    
    /*
    * sequence number - 12 bits - up to 4096 random numbers per machine
    */
    $random = str_pad(decbin(mt_rand(0, self::max12bit)), 12, "0", STR_PAD_LEFT);

    /*
    * Pack
    */
    $base = $base.$machineid.$random;

    /*
    * Return unique time id no
    */
    return bindec($base);
  }

  public static function timeFromParticle($particle) {
    /*
    * Return time
    */
    return bindec(substr(decbin($particle),0,41)) - self::max41bit + self::EPOCH;
  }
}

?>

调用方法如下

Particle::generateParticle($machineId);//生成ID
Particle::timeFromParticle($particle);//反向计算时间戳

这里我做了改良 如果机器ID传0 就会去掉这10bit 因为有些时候我们可能用不到这么多ID

PHP 相关文章推荐
LotusPhp笔记之:Cookie组件的使用详解
May 06 PHP
如何使用php绘制在图片上的正余弦曲线
Jun 08 PHP
解析php addslashes()与addclashes()函数的区别和比较
Jun 24 PHP
PHP删除数组中空值的方法介绍
Apr 14 PHP
PHP 面向对象程序设计(oop)学习笔记 (四) - 异常处理类Exception
Jun 12 PHP
PHP中文编码小技巧
Dec 25 PHP
全面解读PHP的人气开发框架Laravel
Oct 15 PHP
PHP实现QQ登录实例代码
Jan 14 PHP
PHP与服务器文件系统的简单交互
Oct 21 PHP
ThinkPHP3.2框架使用addAll()批量插入数据的方法
Mar 16 PHP
php合并数组并保留键值的实现方法
Mar 12 PHP
php反射学习之依赖注入示例
Jun 14 PHP
简单解决微信文章图片防盗链问题
Dec 17 #PHP
PHP 7.1新特性的汇总介绍
Dec 16 #PHP
浅谈PHP命令执行php文件需要注意的问题
Dec 16 #PHP
PHP+Ajax 检测网络是否正常实例详解
Dec 16 #PHP
php微信公众号开发(4)php实现自定义关键字回复
Dec 15 #PHP
php微信公众号开发(3)php实现简单微信文本通讯
Dec 15 #PHP
php微信公众号开发(2)百度BAE搭建和数据库使用
Dec 15 #PHP
You might like
windows下开发并编译PHP扩展的方法
2011/03/18 PHP
sql注入与转义的php函数代码
2013/06/17 PHP
解决file_get_contents无法请求https连接的方法
2013/12/17 PHP
Laravel中使用阿里云OSS Composer包分享
2015/02/10 PHP
phpMyAdmin无法登陆的解决方法
2017/04/27 PHP
php引用和拷贝的区别知识点总结
2019/09/23 PHP
关闭浏览器输入框自动补齐 兼容IE,FF,Chrome等主流浏览器
2014/02/11 Javascript
一个支付页面DEMO附截图
2014/07/22 Javascript
JQuery选择器绑定事件及修改内容的方法
2015/01/23 Javascript
jquery实现textarea 高度自适应
2015/03/11 Javascript
JQuery中DOM事件合成用法实例分析
2015/06/13 Javascript
JavaScript编程的单例设计模讲解
2015/11/10 Javascript
jQuery解析json数据实例分析
2015/11/24 Javascript
jQuery过滤特殊字符及JS字符串转为数字
2016/05/26 Javascript
jquery自适应布局的简单实例
2016/05/28 Javascript
jquery实现点击页面回到顶部
2016/11/23 Javascript
vue中使用vue-router切换页面时滚动条自动滚动到顶部的方法
2017/11/28 Javascript
webpack4 css打包压缩问题的解决
2018/05/18 Javascript
vue项目配置 webpack-obfuscator 进行代码加密混淆的实现
2021/02/26 Vue.js
python 字典中取值的两种方法小结
2018/08/02 Python
分析python请求数据
2018/08/19 Python
pandas求两个表格不相交的集合方法
2018/12/08 Python
django使用JWT保存用户登录信息
2020/04/22 Python
Python利用Xpath选择器爬取京东网商品信息
2020/06/01 Python
Python实现迪杰斯特拉算法过程解析
2020/09/18 Python
DAWGS鞋官方网站:鞋,凉鞋,靴子
2016/10/04 全球购物
Zavvi荷兰:英国大型音像制品和图书游戏零售商
2018/03/22 全球购物
Juicy Couture Beauty官方网站:香水和化妆品
2019/03/12 全球购物
凌阳科技股份有限公司C++程序员面试题笔试题
2014/11/20 面试题
口才训练演讲稿范文
2014/09/16 职场文书
2014财务人员自我评价范文
2014/09/21 职场文书
奖学金个人总结
2015/03/04 职场文书
2015年安全生产月活动总结
2015/03/26 职场文书
爱国电影观后感
2015/06/19 职场文书
python代码实现扫码关注公众号登录的实战
2021/11/01 Python
Python接口自动化之文件上传/下载接口详解
2022/04/05 Python