在分布式系统中,需要生成全局UID的场合还是比较多的,twitter的snowflake解决了这种需求,实现也还是很简单的,除去配置信息,核心代码就是毫秒级时间41位+机器ID 10位+毫秒内序列12位。
twitter的分布式自增id算法snowflake,每秒能产生20w+的自增id,也适用于php。
<?php 2 class Idwork 3 { 4 const debug = 1; 5 static $workerId; 6 static $twepoch = 1361775855078; 7 static $sequence = 0; 8 const workerIdBits = 4; 9 static $maxWorkerId = 15; 10 const sequenceBits = 10; 11 static $workerIdShift = 10; 12 static $timestampLeftShift = 14; 13 static $sequenceMask = 1023; 14 private static $lastTimestamp = -1; 15 16 function __construct($workId){ 17 if($workId > self::$maxWorkerId || $workId< 0 ) 18 { 19 throw new Exception("worker Id can't be greater than 15 or less than 0"); 20 } 21 self::$workerId=$workId; 22 23 echo 'logdebug->__construct()->self::$workerId:'.self::$workerId; 24 echo '</br>'; 25 26 } 27 28 function timeGen(){ 29 //获得当前时间戳 30 $time = explode(' ', microtime()); 31 $time2= substr($time[0], 2, 3); 32 $timestramp = $time[1].$time2; 33 echo 'logdebug->timeGen()->$timestramp:'.$time[1].$time2; 34 echo '</br>'; 35 return $time[1].$time2; 36 } 37 function tilNextMillis($lastTimestamp) { 38 $timestamp = $this->timeGen(); 39 while ($timestamp <= $lastTimestamp) { 40 $timestamp = $this->timeGen(); 41 } 42 43 echo 'logdebug->tilNextMillis()->$timestamp:'.$timestamp; 44 echo '</br>'; 45 return $timestamp; 46 } 47 48 function nextId() 49 { 50 $timestamp=$this->timeGen(); 51 echo 'logdebug->nextId()->self::$lastTimestamp1:'.self::$lastTimestamp; 52 echo '</br>'; 53 if(self::$lastTimestamp == $timestamp) { 54 self::$sequence = (self::$sequence + 1) & self::$sequenceMask; 55 if (self::$sequence == 0) { 56 echo "###########".self::$sequenceMask; 57 $timestamp = $this->tilNextMillis(self::$lastTimestamp); 58 echo 'logdebug->nextId()->self::$lastTimestamp2:'.self::$lastTimestamp; 59 echo '</br>'; 60 } 61 } else { 62 self::$sequence = 0; 63 echo 'logdebug->nextId()->self::$sequence:'.self::$sequence; 64 echo '</br>'; 65 } 66 if ($timestamp < self::$lastTimestamp) { 67 throw new Excwption("Clock moved backwards. Refusing to generate id for ".(self::$lastTimestamp-$timestamp)." milliseconds"); 68 } 69 self::$lastTimestamp = $timestamp; 70 echo 'logdebug->nextId()->self::$lastTimestamp3:'.self::$lastTimestamp; 71 echo '</br>'; 72 73 echo 'logdebug->nextId()->(($timestamp - self::$twepoch << self::$timestampLeftShift )):'.((sprintf('%.0f', $timestamp) - sprintf('%.0f', self::$twepoch) )); 74 echo '</br>'; 75 $nextId = ((sprintf('%.0f', $timestamp) - sprintf('%.0f', self::$twepoch) )) | ( self::$workerId << self::$workerIdShift ) | self::$sequence; 76 echo 'timestamp:'.$timestamp.'-----'; 77 echo 'twepoch:'.sprintf('%.0f', self::$twepoch).'-----'; 78 echo 'timestampLeftShift ='.self::$timestampLeftShift.'-----'; 79 echo 'nextId:'.$nextId.'----'; 80 echo 'workId:'.self::$workerId.'-----'; 81 echo 'workerIdShift:'.self::$workerIdShift.'-----'; 82 return $nextId; 83 } 84 85 } 86 $Idwork = new Idwork(1); 87 $a= $Idwork->nextId(); 88 $Idwork = new Idwork(2); 89 $a= $Idwork->nextId(); 90 ?>