文档章节

修改自Twitter的Snowflake算法

思_无_邪
 思_无_邪
发布于 2015/10/20 15:51
字数 545
阅读 78
收藏 1
<?php
/**
 * 得到唯一识别码
 * 修改自Twitter的Snowflake算法
 * 此算法支持分布式自增ID
 * @author cwsky@163.com
 */

abstract class Uniq
{
	//初始时间码,开站设定一次,可用以下语句得到
	//floor(microtime(true) * 1000);
	private static $twepoch = 1380553425155;

	//数据中心,8表示可以有255个数据中心,最大取值为8
	private static $dataCenterIDBits = 8;

	//数据中心ID最大值
	//private static $maxDatacenterID = -1 ^ (-1 << $datacenterIDBits);

	//机器标识符,13表示可以有8191台机器,最大取值为13
	//当dataCenterIDBits与workerIDBits变大时,会产生负数,就不好玩了
	private static $workerIDBits = 13;

	//机器ID最大值
	//private static $maxWorkerId = -1 ^ (-1 << $workerIDBits);

	//毫秒内自增位
	private static $sequenceBits = 12;

	//机器ID偏左移12位
	//private static $workerIDShift = self::$sequenceBits;
	private static $workerIDShift = 12;

	//数据中心ID左移17位
	//private $dataCenterIDShift = $sequenceBits + $workerIDBits;

	//时间毫秒左移22位
	//private $timestampLeftShift = $sequenceBits + $workerIDBits + $datacenterIDBits;
	//private $sequenceMask = -1 ^ (-1 << $sequenceBits);

	private static $lastTimestamp = -1;

	private static $sequence = 0;

	public static function id($dataCenterID, $workerID)
	{
		//数据中心ID最大值
		$maxDataCenterID = -1 ^ (-1 << self::$dataCenterIDBits);

		//机器ID最大值
		$maxWorkerID = -1 ^ (-1 << self::$workerIDBits);

		//数据中心ID左移17位
		$dataCenterIDShift = self::$sequenceBits + self::$workerIDBits;

		//时间毫秒左移22位
		$timestampLeftShift = self::$sequenceBits + self::$workerIDBits + self::$dataCenterIDBits;
		$sequenceMask = -1 ^ (-1 << self::$sequenceBits);

		//检查workerID完整性
		if($workerID > $maxWorkerID || $workerID < 0)
		{
			return 0;
		}

		//检查数据中心完整性
		if($dataCenterID > $maxDataCenterID || $dataCenterID < 0)
		{
			return 0;
		}

		//echo sprintf("worker starting. timestamp left shift %d, datacenter id bits %d, maxDatacenterID:%d, worker id bits %d, maxWorkerID:%d, sequence bits %d, workerid %d", $timestampLeftShift, self::$dataCenterIDBits, $maxDataCenterID, self::$workerIDBits, $maxWorkerID, self::$sequenceBits, $workerID);

		$timestamp = self::timeGen();

		if($timestamp < self::$lastTimestamp)
		{
			return 0;
		}

		if (self::$lastTimestamp == $timestamp)
		{
			//当前毫秒内,则+1
			self::$sequence = (self::$sequence + 1) & $sequenceMask;
			if(self::$sequence == 0)
			{
				//当前毫秒内计数满了,则等待下一秒
				$timestamp = self::tilNextMillis(self::$lastTimestamp);
			}
		}
		else
		{
			self::$sequence = 0;
		}

		self::$lastTimestamp = $timestamp;

		$id = (($timestamp - self::$twepoch << $timestampLeftShift)) | ($dataCenterID << $dataCenterIDShift) | ($workerID << self::$workerIDShift) | (self::$sequence);

		return $id;
	}

	public static function timeGen()
	{
		return floor(microtime(true) * 1000);
	}

	public static function tilNextMillis($lastTimestamp)
	{
		$timestamp = self::timeGen();

		while($timestamp <= $lastTimestamp)
		{
			$timestamp = self::timeGen();
		}

		return $timestamp;
	}

	public static function getUUID()
	{
		return strtoupper(sprintf( '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
	        // 32 bits for "time_low"
	        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ),

	        // 16 bits for "time_mid"
	        mt_rand( 0, 0xffff ),

	        // 16 bits for "time_hi_and_version",
	        // four most significant bits holds version number 4
	        mt_rand( 0, 0x0fff ) | 0x4000,

	        // 16 bits, 8 bits for "clk_seq_hi_res",
	        // 8 bits for "clk_seq_low",
	        // two most significant bits holds zero and one for variant DCE1.1
	        mt_rand( 0, 0x3fff ) | 0x8000,

	        // 48 bits for "node"
	        mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff ), mt_rand( 0, 0xffff )
	    ));
	}
}
?>


© 著作权归作者所有

共有 人打赏支持
思_无_邪

思_无_邪

粉丝 2
博文 3
码字总数 4338
作品 1
海淀
CTO(技术副总裁)
私信 提问
一个实现 Twitter SnowFlake 算法 的 Go 分布式 UID 生成器

goSnowFlake According to the Twitter SnowFlake Theory, A ThreadSafe Unique ID Generator written by Golang 根据 Twitter SnowFlake 算法, 实现的分布式线程安全 UID 生成器 Feature 线......

ethantonylam
2016/04/07
48
0
PHP唯一ID生成扩展--Atom

使用Twitter的 Snowflake算法,有兴趣可以了解一下这个算法: https://github.com/twitter/snowflake php.ini的配置项: [ukey]ukey.datacenter = integerukey.worker = integerukey.twepoch ......

liexusong
2013/08/27
3.7K
1
golang 实现的 id 发号器--gosnowflake

gosnowflake 是一个golang 实现的 id 发号器,使用的是twitter的snowflake的算法,对twitter的snowflake项目进行了一些改造和优化,变的更可靠,现在主要是采用golang的gob编码rpc方式调用。...

LoveSai
2014/05/04
1K
0
gosnowflake 发布 1.0.1

gosnowflake 是一个golang 实现的 id 发号器,使用的是twitter的snowflake的算法,对twitter的snowflake项目进行了一些改造和优化,变的更可靠,现在主要是采用golang的gob编码rpc方式调用。...

LoveSai
2014/05/04
268
0
对新UUID算法的说明

原来的算法产生36位的字符串类型的UUID,当数据量比较大时有很大可能会成为性能瓶颈。另外算法本身完全基于时间产生的随机数,还是有小概率生成不唯一的ID。基于以上两点原因,我又搜索了一下...

sieg
2015/03/01
4
3

没有更多内容

加载失败,请刷新页面

加载更多

阿里强制要求的21条Java开发规范,可以避免很多坑

1. 【强制】避免通过一个类的对象引用访问此类的静态变量或静态方法,无谓增加编译器解析成本,直接用类名来访问即可。 2. 【强制】所有的覆写方法,必须加@Override注解。 说明:getObject...

天王盖地虎626
17分钟前
1
0
oracle dg 备库未设置convert参数导致ORA-01111,ORA-01110

查看trace 文件: MRP0: Background Managed Standby Recovery process started (amls) started logmerger process Sun Jan 20 07:55:53 2019 Managed Standby Recovery starting Real Time ......

hnairdb
37分钟前
2
0
乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linux-tao
今天
1
0
乱入Linux界的我是如何学习的

欢迎来到建哥学Linux,咳!咳!咳!开个玩笑哈,我是一个IT男,IT界的入门选手,正在学习Linux。 在之前,一直想进军IT界,学习IT技术,但是苦于没有人指导,也不知道学什么,最开始我自己在...

linuxprobe16
今天
9
0
OSChina 周日乱弹 —— 没时间 没头发 但有钱

Osc乱弹歌单(2019)请戳(这里) 【今日歌曲】 @开源中国总经办主任 :分享齐一的单曲《这个年纪》 《这个年纪》- 齐一 手机党少年们想听歌,请使劲儿戳(这里) @肿肿卷 :我真的可以睡一天...

小小编辑
今天
143
7

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部