| | class IdWork | | { | | | | | | const twepoch = 1474992000000; | | | | | | const workerIdBits = 5; | | | | | | const datacenterIdBits = 5; | | | | | | const sequenceBits = 12; | | | | protected $workId = 0; | | protected $datacenterId = 0; | | | | static $lastTimestamp = -1; | | static $sequence = 0; | | | | | | function __construct($workId=0, $datacenterId=0){ | | | | $maxWorkerId = -1 ^ (-1 << self::workerIdBits); | | if($workId > $maxWorkerId || $workId< 0){ | | throw new Exception("workerId can't be greater than ".$this->maxWorkerId." or less than 0"); | | } | | | | $maxDatacenterId = -1 ^ (-1 << self::datacenterIdBits); | | if ($datacenterId > $maxDatacenterId || $datacenterId < 0) { | | throw new Exception("datacenter Id can't be greater than ".$maxDatacenterId." or less than 0"); | | } | | | | $this->workId = $workId; | | $this->datacenterId = $datacenterId; | | } | | | | | | public function nextId(){ | | $timestamp = $this->timeGen(); | | $lastTimestamp = self::$lastTimestamp; | | | | if ($timestamp < $lastTimestamp) { | | throw new Exception("Clock moved backwards. Refusing to generate id for %d milliseconds", ($lastTimestamp - $timestamp)); | | } | | | | if ($lastTimestamp == $timestamp) { | | $sequenceMask = -1 ^ (-1 << self::sequenceBits); | | self::$sequence = (self::$sequence + 1) & $sequenceMask; | | if (self::$sequence == 0) { | | $timestamp = $this->tilNextMillis($lastTimestamp); | | } | | } else { | | self::$sequence = 0; | | } | | self::$lastTimestamp = $timestamp; | | | | | | $timestampLeftShift = self::sequenceBits + self::workerIdBits + self::datacenterIdBits; | | $datacenterIdShift = self::sequenceBits + self::workerIdBits; | | $workerIdShift = self::sequenceBits; | | | | $nextId = (($timestamp - self::twepoch) << $timestampLeftShift) | | | ($this->datacenterId << $datacenterIdShift) | | | ($this->workId << $workerIdShift) | self::$sequence; | | return $nextId; | | } | | | | | | protected function timeGen(){ | | $timestramp = (float)sprintf("%.0f", microtime(true) * 1000); | | return $timestramp; | | } | | | | | | protected function tilNextMillis($lastTimestamp) { | | $timestamp = $this->timeGen(); | | while ($timestamp <= $lastTimestamp) { | | $timestamp = $this->timeGen(); | | } | | return $timestamp; | | } | | | | } | | | | | | $obj = new IdWork(); | | print_r($obj->nextId()); |
|
转自:http://r6d.cn/MEXV