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 相关文章推荐
关于BIG5-HKSCS的解决方法
Mar 20 PHP
php和数据库结合的一个简单的web实例 代码分析 (php初学者)
Jul 28 PHP
php数组函数序列 之shuffle()和array_rand() 随机函数使用介绍
Oct 29 PHP
php删除字符串末尾子字符,删除开始字符,删除两端字符(实现代码)
Jun 27 PHP
php fsockopen解决办法 php实现多线程
Jan 20 PHP
smarty内置函数{loteral}、{ldelim}和{rdelim}用法实例
Jan 22 PHP
PHP中返回引用类型的方法
Apr 03 PHP
php计算税后工资的方法
Jul 28 PHP
php+redis在实际项目中HTTP 500: Internal Server Error故障排除
Feb 05 PHP
PHP基于自定义函数实现的汉字转拼音功能实例
Sep 30 PHP
thinkphp5 模型实例化获得数据对象的教程
Oct 18 PHP
Laravel 验证码认证学习记录小结
Dec 20 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中chdir()函数用法实例
2014/11/13 PHP
php实现的读取CSV文件函数示例
2017/02/07 PHP
Laravel多域名下字段验证的方法
2019/04/04 PHP
laravel框架模板之公共模板、继承、包含实现方法分析
2019/08/30 PHP
node.js中的path.sep方法使用说明
2014/12/08 Javascript
高性能JavaScript DOM编程(1)
2015/08/11 Javascript
基于javascript实现tab切换特效
2016/03/29 Javascript
JavaScript实战之带收放动画效果的导航菜单
2016/08/16 Javascript
jQuery事件绑定方法学习总结(推荐)
2016/11/21 Javascript
js实现仿购物车加减效果
2017/03/01 Javascript
JavaScript中 DOM操作方法小结
2017/04/25 Javascript
监控Nodejs的性能实例代码
2019/07/02 NodeJs
koa-passport实现本地验证的方法示例
2020/02/20 Javascript
jQuery实现全选按钮
2021/01/01 jQuery
python数据库操作常用功能使用详解(创建表/插入数据/获取数据)
2013/12/06 Python
python处理中文编码和判断编码示例
2014/02/26 Python
详解Python中的序列化与反序列化的使用
2015/06/30 Python
详解Python中的__new__、__init__、__call__三个特殊方法
2016/06/02 Python
python+opencv轮廓检测代码解析
2018/01/05 Python
PyCharm代码整体缩进,反向缩进的方法
2018/06/25 Python
python list转矩阵的实例讲解
2018/08/04 Python
django中ORM模型常用的字段的使用方法
2019/03/05 Python
为什么从Python 3.6开始字典有序并效率更高
2019/07/15 Python
Django实现CAS+OAuth2的方法示例
2019/10/30 Python
Python协程 yield与协程greenlet简单用法示例
2019/11/22 Python
Python中使用socks5设置全局代理的方法示例
2020/04/15 Python
html Table 表头固定的实现
2019/01/22 HTML / CSS
h5封装下拉刷新
2020/08/25 HTML / CSS
英国舒适型鞋履品牌:FitFlop
2017/05/17 全球购物
Notino法国:购买香水和化妆品
2019/04/15 全球购物
美国肌肉和力量商店:Muscle & Strength
2019/06/22 全球购物
模具专业毕业推荐信
2014/03/08 职场文书
公安局负责人查摆问题及整改方案
2014/09/27 职场文书
总经理司机岗位职责
2015/04/10 职场文书
机关干部正风肃纪心得体会
2016/01/15 职场文书
mysql分组后合并显示一个字段的多条数据方式
2022/01/22 MySQL