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单件模式结合命令链模式使用说明
Sep 07 PHP
PHP网页游戏学习之Xnova(ogame)源码解读(十五)
Jun 30 PHP
php jsonp单引号转义
Nov 23 PHP
PHP中实现Bloom Filter算法
Mar 30 PHP
学习PHP Cookie处理函数
Aug 09 PHP
利用PHP判断文件是否为图片的方法总结
Jan 06 PHP
PHP实现RSA签名生成订单功能【支付宝示例】
Jun 06 PHP
PHP使用PDO访问oracle数据库的步骤详解
Sep 29 PHP
PHP实现数据库的增删查改功能及完整代码
Apr 18 PHP
解决laravel中日志权限莫名变成了root的问题
Oct 17 PHP
laravel csrf排除路由,禁止,关闭指定路由的例子
Oct 21 PHP
微信小程序和php的登录实现
Apr 01 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 简单数组排序实现代码
2009/08/05 PHP
php foreach 使用&amp;(与运算符)引用赋值要注意的问题
2010/02/16 PHP
PHP字符串函数系列之nl2br(),在字符串中的每个新行 (\n) 之前插入 HTML 换行符br
2011/11/10 PHP
解析mysql left( right ) join使用on与where筛选的差异
2013/06/18 PHP
排序算法之PHP版快速排序、冒泡排序
2014/04/09 PHP
php短信接口代码
2016/05/13 PHP
Yii2框架中日志的使用方法分析
2017/05/22 PHP
php中file_get_contents()函数用法实例
2019/02/21 PHP
限制文本框输入N个字符的js代码
2010/05/13 Javascript
javascript中2个感叹号的用法实例详解
2014/09/04 Javascript
JS实现图片放大镜效果的方法
2015/02/27 Javascript
JavaScript获取网页表单提交方式的方法
2015/04/02 Javascript
javascript每日必学之运算符
2016/02/16 Javascript
深入浅析javascript继承体系
2017/10/23 Javascript
vue.js分页中单击页码更换页面内容的方法(配合spring springmvc)
2018/02/10 Javascript
浅谈ng-zorro使用心得
2018/12/03 Javascript
vue 使用element-ui中的Notification自定义按钮并实现关闭功能及如何处理多个通知
2019/08/17 Javascript
Element MessageBox弹框的具体使用
2020/07/27 Javascript
python连接池实现示例程序
2013/11/26 Python
开始着手第一个Django项目
2015/07/15 Python
Python处理文本文件中控制字符的方法
2017/02/07 Python
django的登录注册系统的示例代码
2018/05/14 Python
python数据批量写入ScrolledText的优化方法
2018/10/11 Python
int在python中的含义以及用法
2019/06/27 Python
pandas分区间,算频率的实例
2019/07/04 Python
Python实现多线程/多进程的TCP服务器
2019/09/03 Python
python xlwt如何设置单元格的自定义背景颜色
2019/09/03 Python
python mqtt 客户端的实现代码实例
2019/09/25 Python
如何在scrapy中捕获并处理各种异常
2020/09/28 Python
特步官方商城:Xtep
2017/03/21 全球购物
自动化专业毕业生自荐信
2013/11/01 职场文书
计算机应用与科学个人的自我评价
2013/11/15 职场文书
班主任工作年限证明
2014/01/12 职场文书
爱耳日宣传活动总结
2014/07/05 职场文书
Redis中缓存穿透/击穿/雪崩问题和解决方法
2021/12/04 Redis
电脑只能进入安全模式无法正常启动的解决办法
2022/04/08 数码科技