Added degenerate.

This commit is contained in:
李铭昕 2019-08-14 12:14:49 +08:00
parent 5cff71a2c6
commit 2b3d4cb6f9
5 changed files with 65 additions and 31 deletions

View File

@ -19,4 +19,6 @@ interface IdGeneratorInterface
const LEVEL_MILLISECOND = 2;
public function generate(?Meta $meta = null): int;
public function degenerate(int $id): Meta;
}

View File

@ -26,11 +26,6 @@ class Meta
const MACHINE_ID_BITS = 7;
/**
* @var int
*/
public $beginSecond;
/**
* @var int [0, 15]
*/
@ -51,7 +46,7 @@ class Meta
*/
public $sequence;
public function __construct(int $beginSecond, int $businessId, int $dataCenterId, int $machineId, int $sequence)
public function __construct(int $businessId, int $dataCenterId, int $machineId, int $sequence)
{
if ($businessId < 0 || $businessId > $this->maxBusinessId()) {
throw new SnowflakeException('Business Id can\'t be greater than 15 or less than 0');
@ -66,29 +61,28 @@ class Meta
throw new SnowflakeException('Sequence can\'t be greater than 4096 or less than 0');
}
$this->beginSecond = $beginSecond;
$this->businessId = $businessId;
$this->dataCenterId = $dataCenterId;
$this->machineId = $machineId;
$this->sequence = $sequence;
}
private function maxMachineId()
protected function maxMachineId()
{
return -1 ^ (-1 << self::MACHINE_ID_BITS);
}
private function maxDataCenterId()
protected function maxDataCenterId()
{
return -1 ^ (-1 << self::DATA_CENTER_ID_BITS);
}
private function maxBusinessId()
protected function maxBusinessId()
{
return -1 ^ (-1 << self::BUSINESS_ID_BITS);
}
private function maxSequence()
protected function maxSequence()
{
return -1 ^ (-1 << self::SEQUENCE_BITS);
}

View File

@ -23,6 +23,6 @@ class RandomMetaGenerator implements MetaGeneratorInterface
$machineId = rand(0, 127);
$sequence = ($this->sequence++) % 4096;
return new Meta(15657528167, $businessId, $dataCenterId, $machineId, $sequence);
return new Meta($businessId, $dataCenterId, $machineId, $sequence);
}
}

View File

@ -29,10 +29,11 @@ class Snowflake implements IdGeneratorInterface
*/
protected $beginSecond;
public function __construct(MetaGeneratorInterface $metaGenerator, int $level = self::LEVEL_MILLISECOND)
public function __construct(MetaGeneratorInterface $metaGenerator, int $level = self::LEVEL_MILLISECOND, int $beginSecond = 1565712000)
{
$this->metaGenerator = $metaGenerator;
$this->level = $level;
$this->beginSecond = $level == self::LEVEL_SECOND ? $beginSecond : $beginSecond * 1000;
}
public function generate(?Meta $meta = null): int
@ -41,12 +42,52 @@ class Snowflake implements IdGeneratorInterface
$timestamp = $this->getTimestamp();
$t = ($timestamp - $this->getBeginTimestamp($meta)) << (Meta::SEQUENCE_BITS + Meta::MACHINE_ID_BITS + Meta::DATA_CENTER_ID_BITS + Meta::BUSINESS_ID_BITS);
$b = $meta->businessId << (Meta::SEQUENCE_BITS + Meta::MACHINE_ID_BITS + Meta::DATA_CENTER_ID_BITS);
$dc = $meta->dataCenterId << (Meta::SEQUENCE_BITS + Meta::MACHINE_ID_BITS);
$worker = $meta->machineId << Meta::SEQUENCE_BITS;
$timestamp = ($timestamp - $this->beginSecond) << $this->getTimestampShift();
$businessId = $meta->businessId << $this->getBusinessIdShift();
$dataCenterId = $meta->dataCenterId << $this->getDataCenterShift();
$machineId = $meta->machineId << $this->getMachineIdShift();
return $t | $b | $dc | $worker | $meta->sequence;
return $timestamp | $businessId | $dataCenterId | $machineId | $meta->sequence;
}
public function degenerate(int $id): Meta
{
$timestamp = $id >> $this->getTimestampShift();
$businessId = $id >> $this->getBusinessIdShift();
$dataCenterId = $id >> $this->getDataCenterShift();
$machineId = $id >> $this->getMachineIdShift();
return new Meta(
$timestamp << Meta::BUSINESS_ID_BITS ^ $businessId,
$businessId << Meta::DATA_CENTER_ID_BITS ^ $dataCenterId,
$dataCenterId << Meta::MACHINE_ID_BITS ^ $machineId,
$machineId << Meta::SEQUENCE_BITS ^ $id
);
}
protected function getTimestampShift()
{
return Meta::SEQUENCE_BITS + Meta::MACHINE_ID_BITS + Meta::DATA_CENTER_ID_BITS + Meta::BUSINESS_ID_BITS;
}
protected function getBusinessIdShift()
{
return Meta::SEQUENCE_BITS + Meta::MACHINE_ID_BITS + Meta::DATA_CENTER_ID_BITS;
}
protected function getDataCenterShift()
{
return Meta::SEQUENCE_BITS + Meta::MACHINE_ID_BITS;
}
protected function getMachineIdShift()
{
return Meta::SEQUENCE_BITS;
}
protected function getMaxNumber(int $shift)
{
return -1 ^ (-1 << $shift);
}
protected function getTimestamp(): int
@ -57,19 +98,6 @@ class Snowflake implements IdGeneratorInterface
return intval(microtime(true) * 1000);
}
protected function getBeginTimestamp(Meta $meta)
{
if (is_int($this->beginSecond)) {
return $this->beginSecond;
}
if ($this->level == self::LEVEL_SECOND) {
return $meta->beginSecond;
}
return $this->beginSecond = intval($meta->beginSecond * 1000);
}
protected function meta(?Meta $meta = null): Meta
{
if (is_null($meta)) {

View File

@ -12,6 +12,7 @@ declare(strict_types=1);
namespace HyperfTest\Snowflake;
use Hyperf\Snowflake\Meta;
use Hyperf\Snowflake\RandomMetaGenerator;
use Hyperf\Snowflake\Snowflake;
use PHPUnit\Framework\TestCase;
@ -27,4 +28,13 @@ class GeneratorTest extends TestCase
$generator = new Snowflake(new RandomMetaGenerator());
$this->assertTrue(is_int($generator->generate()));
}
public function testDegenerate()
{
$generator = new Snowflake(new RandomMetaGenerator());
$id = $generator->generate();
$this->assertInstanceOf(Meta::class, $generator->degenerate($id));
}
}