分布式自增ID解决方案 twitter/snowflake JAVA版 谁可以帮忙改写成PHP版本的呢?

zhouyuan24 发布于 2013/02/25 09:30
阅读 5K+
收藏 8
PHP

毫秒级时间41位+机器ID 10位+毫秒内序列12位

1.twitter/snowflake

地址:https://github.com/twitter/snowflake


下面是淘宝一个人改写成JAVA的, 

目前我需要PHP版本。 哪位朋友可以抽空改写下呢?

@红薯 俺又来求助啦~

public class IdWorker {
	private final long workerId;
	private final static long twepoch = 1361753741828L;
	private long sequence = 0L;
	private final static long workerIdBits = 4L;
	public final static long maxWorkerId = -1L ^ -1L << workerIdBits;
	private final static long sequenceBits = 10L;

	private final static long workerIdShift = sequenceBits;
	private final static long timestampLeftShift = sequenceBits + workerIdBits;
	public final static long sequenceMask = -1L ^ -1L << sequenceBits;

	private long lastTimestamp = -1L;

	public IdWorker(final long workerId) {
		super();
		if (workerId > this.maxWorkerId || workerId < 0) {
			throw new IllegalArgumentException(String.format(
					"worker Id can't be greater than %d or less than 0",
					this.maxWorkerId));
		}
		this.workerId = workerId;
	}

	public synchronized long nextId() {
		long timestamp = this.timeGen();
		if (this.lastTimestamp == timestamp) {
			this.sequence = (this.sequence + 1) & this.sequenceMask;
			if (this.sequence == 0) {
				System.out.println("###########" + sequenceMask);
				timestamp = this.tilNextMillis(this.lastTimestamp);
			}
		} else {
			this.sequence = 0;
		}
		if (timestamp < this.lastTimestamp) {
			try {
				throw new Exception(
						String.format(
								"Clock moved backwards.  Refusing to generate id for %d milliseconds",
								this.lastTimestamp - timestamp));
			} catch (Exception e) {
				e.printStackTrace();
			}
		}

		this.lastTimestamp = timestamp;
		long nextId = ((timestamp - twepoch << timestampLeftShift))
				| (this.workerId << this.workerIdShift) | (this.sequence);
//		System.out.println("timestamp:" + timestamp + ",timestampLeftShift:"
//				+ timestampLeftShift + ",nextId:" + nextId + ",workerId:"
//				+ workerId + ",sequence:" + sequence);
		return nextId;
	}

	private long tilNextMillis(final long lastTimestamp) {
		long timestamp = this.timeGen();
		while (timestamp <= lastTimestamp) {
			timestamp = this.timeGen();
		}
		return timestamp;
	}

	private long timeGen() {
		return System.currentTimeMillis();
	}
	
	
	public static void main(String[] args){
		IdWorker worker2 = new IdWorker(2);
		System.out.println(worker2.nextId());

		
	}

}
加载中
0
zhouyuan24
zhouyuan24
目前是修改成这样, 可是在长整型计算的时候((sprintf('%.0f', $timestamp) - sprintf('%.0f', self::$twepoch) )) 有负数产生, 产生的ID会收影响为-的
<?php 
class Idwork
{
	const debug = 1;
	static $workerId;
	static $twepoch = 1361775855078;
	static $sequence = 0;
	const workerIdBits = 4;
	static $maxWorkerId = 15;
	const sequenceBits = 10;
	static $workerIdShift = 10;
	static $timestampLeftShift = 14;
	static $sequenceMask = 1023;
	private  static $lastTimestamp = -1;

	function __construct($workId){
		if($workId > self::$maxWorkerId || $workId< 0 )
		{
				throw new Exception("worker Id can't be greater than 15 or less than 0");
		}
		self::$workerId=$workId;

		echo 'logdebug->__construct()->self::$workerId:'.self::$workerId;
		echo '</br>';	
			
	}

	function timeGen(){
		//获得当前时间戳
	 $time = explode(' ', microtime());
	 $time2= substr($time[0], 2, 3);
	 $timestramp = $time[1].$time2;
	 echo 'logdebug->timeGen()->$timestramp:'.$time[1].$time2;
	 echo '</br>';
	 return  $time[1].$time2;
	}
	function  tilNextMillis($lastTimestamp) {
		$timestamp = $this->timeGen();
		while ($timestamp <= $lastTimestamp) {
			$timestamp = $this->timeGen();
		}
		
		echo 'logdebug->tilNextMillis()->$timestamp:'.$timestamp;
		echo '</br>';		
		return $timestamp;
	}

	function  nextId()
	{
		$timestamp=$this->timeGen();
		echo 'logdebug->nextId()->self::$lastTimestamp1:'.self::$lastTimestamp;
		echo '</br>';	
		if(self::$lastTimestamp == $timestamp) {
		self::$sequence = (self::$sequence + 1) & self::$sequenceMask;
		if (self::$sequence == 0) {
		    echo "###########".self::$sequenceMask;
		    $timestamp = $this->tilNextMillis(self::$lastTimestamp);
		    echo 'logdebug->nextId()->self::$lastTimestamp2:'.self::$lastTimestamp;
	    	echo '</br>';			
		  }
		} else {
			self::$sequence  = 0;
		    echo 'logdebug->nextId()->self::$sequence:'.self::$sequence;
	    	echo '</br>';		
		}
		if ($timestamp < self::$lastTimestamp) {
		   throw new Excwption("Clock moved backwards.  Refusing to generate id for ".(self::$lastTimestamp-$timestamp)." milliseconds");
		   }
		self::$lastTimestamp  = $timestamp;
		echo 'logdebug->nextId()->self::$lastTimestamp3:'.self::$lastTimestamp;
		echo '</br>';

		echo 'logdebug->nextId()->(($timestamp - self::$twepoch << self::$timestampLeftShift )):'.((sprintf('%.0f', $timestamp) - sprintf('%.0f', self::$twepoch) ));
		echo '</br>';	
		$nextId = ((sprintf('%.0f', $timestamp) - sprintf('%.0f', self::$twepoch)  )) | ( self::$workerId << self::$workerIdShift ) | self::$sequence;
		echo 'timestamp:'.$timestamp.'-----';
		echo 'twepoch:'.sprintf('%.0f', self::$twepoch).'-----';
		echo 'timestampLeftShift ='.self::$timestampLeftShift.'-----';
		echo 'nextId:'.$nextId.'----';
		echo 'workId:'.self::$workerId.'-----';
		echo 'workerIdShift:'.self::$workerIdShift.'-----';
		return $nextId;
	}

}
$Idwork = new Idwork(1);
$a= $Idwork->nextId();
$Idwork = new Idwork(2);
$a= $Idwork->nextId();
?>
0
MGL_TECH
MGL_TECH

会重复


public static void main(String[] args) {


Thread t = new Thread(new Runnable() {


@Override
public void run() {
// TODO Auto-generated method stub
StringBuffer s = new StringBuffer();
for (int i = 0; i < 1000; i++) {
IdWorker worker2 = new IdWorker(2);
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");


}
try {
FileUtils.writeStringToFile(new File("f:/1.txt"), s.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t.start();


Thread t2 = new Thread(new Runnable() {


@Override
public void run() {
// TODO Auto-generated method stub
StringBuffer s = new StringBuffer();
for (int i = 0; i < 1000; i++) {
IdWorker worker2 = new IdWorker(2);
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");


}
try {
FileUtils.writeStringToFile(new File("f:/2.txt"), s.toString());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
});
t2.start();


}

0
linapex
linapex

正确的测试方式:

public class IdWorkerTest
{


public static void main(String[] args)
{


Thread t = new Thread(new Runnable()
{
@Override
public void run()
{
StringBuffer s = new StringBuffer();
IdWorker worker2 = new IdWorker(2);
for (int i = 0; i < 1000; i++)
{
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
}
try
{
FileUtils.writeStringToFile(new File("c:/project/1.txt"), s.toString());
} catch (IOException e)
{
e.printStackTrace();
}
}
});
t.start();


Thread t2 = new Thread(new Runnable()
{


@Override
public void run()
{
StringBuffer s = new StringBuffer();
IdWorker worker2 = new IdWorker(3);
for (int i = 0; i < 1000; i++)
{
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
s.append(worker2.nextId() + "\n");
}
try
{
FileUtils.writeStringToFile(new File("c:/project/2.txt"), s.toString());
} catch (IOException e)
{
e.printStackTrace();
}
}
});
t2.start();


}


}


0
技术揣摩
技术揣摩
分布式自增ID。。。。难道是为了容灾???63位字符为什么不用UUID
zhouyuan24
zhouyuan24
UUID 不是纯数字的。 并且也没有前后顺序性,
返回顶部
顶部