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 相关文章推荐
Search Engine Friendly的URL设计
Oct 09 PHP
一个简单的域名注册情况查询程序
Oct 09 PHP
PHP 字符串操作入门教程
Dec 06 PHP
PHP 加密解密内部算法
Apr 22 PHP
关于php 接口问题(php接口主要也就是运用curl,curl函数)
Jul 01 PHP
如何使用PHP批量去除文件UTF8 BOM信息
Aug 05 PHP
PHP中实现接收多个name相同但Value不相同表单数据实例
Feb 03 PHP
PHP版QQ互联OAuth示例代码分享
Jul 05 PHP
基于thinkPHP实现的微信自定义分享功能示例
Sep 23 PHP
php版交通银行网银支付接口开发入门教程
Sep 26 PHP
PHP中大括号'{}'用法实例总结
Feb 08 PHP
微信第三方登录(原生)demo【必看篇】
May 26 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
PHP syntax error, unexpected $end 错误的一种原因及解决
2008/10/25 PHP
php一维二维数组键排序方法实例总结
2014/11/13 PHP
浅析php创建者模式
2014/11/25 PHP
PHP中使用hidef扩展代替define提高性能
2015/04/09 PHP
CodeIgniter辅助之第三方类库third_party用法分析
2016/01/20 PHP
TP5框架请求响应参数实例分析
2019/10/17 PHP
详解CSS样式中的 !important * _ 符号
2021/03/09 HTML / CSS
javascript下阻止表单重复提交、防刷新、防后退
2007/08/17 Javascript
juqery 学习之五 文档处理 包裹、替换、删除、复制
2011/02/11 Javascript
avalon js实现仿微博拖动图片排序
2015/08/14 Javascript
JS实现的系统调色板完整实例
2016/12/21 Javascript
JS正则替换去空格的方法
2017/03/24 Javascript
微信小程序支付之c#后台实现方法
2017/10/19 Javascript
Angular中sweetalert弹框的基本使用教程
2018/07/22 Javascript
react基本安装与测试示例
2020/04/27 Javascript
python操作oracle的完整教程分享
2018/01/30 Python
[原创]windows下Anaconda的安装与配置正解(Anaconda入门教程)
2018/04/05 Python
Python实现字典按key或者value进行排序操作示例【sorted】
2019/05/03 Python
Python中的类与类型示例详解
2019/07/10 Python
Python3如何对urllib和urllib2进行重构
2019/11/25 Python
Python实现结构体代码实例
2020/02/10 Python
Pycharm中安装Pygal并使用Pygal模拟掷骰子(推荐)
2020/04/08 Python
将python字符串转化成长表达式的函数eval实例
2020/05/11 Python
Pytorch 使用opnecv读入图像由HWC转为BCHW格式方式
2020/06/02 Python
澳大利亚领先的在线美容商城:Adore Beauty
2017/04/14 全球购物
阿里健康大药房:阿里自营网上药店
2017/08/01 全球购物
大学应届毕业生个人求职信
2013/09/23 职场文书
2014年维稳工作总结
2014/11/18 职场文书
2014年卫生保健工作总结
2014/12/08 职场文书
《1942》观后感
2015/06/08 职场文书
机器人总动员观后感
2015/06/09 职场文书
警示教育观后感
2015/06/17 职场文书
公司岗位说明书
2015/10/08 职场文书
PHP新手指南
2021/04/01 PHP
MySQL系列之十五 MySQL常用配置和性能压力测试
2021/07/02 MySQL
JavaScript展开运算符和剩余运算符的区别详解
2022/02/18 Javascript