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 相关文章推荐
PHP开发文件系统实例讲解
Oct 09 PHP
php错误提示failed to open stream: HTTP request failed!的完美解决方法
Jun 06 PHP
利用ThinkPHP内置的ThinkAjax实现异步传输技术的实现方法
Dec 19 PHP
一个简单且很好用的php分页类
Oct 26 PHP
PHP中mysql_field_type()函数用法
Nov 24 PHP
php简单分页类实现方法
Feb 26 PHP
PHP实现C#山寨ArrayList的方法
Jul 16 PHP
php 使用curl模拟登录人人(校内)网的简单实例
Jun 06 PHP
PHP简单实现上一页下一页功能示例
Sep 14 PHP
PHP获取中国时间(上海时区时间)及美国时间的方法
Feb 23 PHP
PHP使用XMLWriter读写xml文件操作详解
Jul 31 PHP
Centos7安装swoole扩展操作示例
Mar 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学习之输出字符串(echo,print,printf,print_r和var_dump)
2011/04/17 PHP
强制PHP命令行脚本单进程运行的方法
2014/04/15 PHP
YII CLinkPager分页类扩展增加显示共多少页
2016/01/29 PHP
php使用pclzip类实现文件压缩的方法(附pclzip类下载地址)
2016/04/30 PHP
laravel5.2表单验证,并显示错误信息的实例
2019/09/29 PHP
js取滚动条的尺寸的函数代码
2011/11/30 Javascript
Javascript学习笔记之 函数篇(一) : 函数声明和函数表达式
2014/06/24 Javascript
javascript基本类型详解
2014/11/28 Javascript
jquery中$each()方法的使用指南
2015/04/30 Javascript
Javascript编程中几种继承方式比较分析
2015/11/28 Javascript
JavaScript中的Reflect对象详解(ES6新特性)
2016/07/22 Javascript
js删除Array数组中指定元素的两种方法
2016/08/03 Javascript
浅析jQuery操作select控件的取值和设值
2016/12/07 Javascript
深入理解Angular.JS中的Scope继承
2017/06/04 Javascript
老生常谈Bootstrap媒体对象
2017/07/06 Javascript
Angular项目中$scope.$apply()方法的使用详解
2017/07/26 Javascript
利用vue + koa2 + mockjs模拟数据的方法教程
2017/11/22 Javascript
AngularJS双向数据绑定原理之$watch、$apply和$digest的应用
2018/01/30 Javascript
redux-saga 初识和使用
2018/03/10 Javascript
手写简单的jQuery雪花飘落效果实例
2018/04/22 jQuery
微信小程序点击列表跳转到对应详情页过程解析
2019/09/26 Javascript
[03:54]Ehome出征西雅图 回顾2016国际邀请赛晋级之路
2016/08/02 DOTA
python3编写C/S网络程序实例教程
2014/08/25 Python
Python多线程经典问题之乘客做公交车算法实例
2017/03/22 Python
Python字符串的一些操作方法总结
2019/06/10 Python
最小二乘法及其python实现详解
2020/02/24 Python
Python3创建Django项目的几种方法(3种)
2020/06/03 Python
L’Artisan Parfumeur官网:法国香水品牌
2020/08/11 全球购物
农村面貌改造提升实施方案
2014/03/18 职场文书
关于中国梦的演讲稿
2014/04/23 职场文书
学校个人对照检查材料
2014/08/26 职场文书
个人授权委托书模板
2014/09/14 职场文书
教师节横幅标语
2014/10/08 职场文书
2014年社区个人工作总结
2014/12/02 职场文书
死者家属慰问信
2015/03/24 职场文书
大学生支教感言
2015/08/01 职场文书