mirror of
https://gitee.com/hyperf/hyperf.git
synced 2024-12-02 11:48:08 +08:00
Added degenerate.
This commit is contained in:
parent
5cff71a2c6
commit
2b3d4cb6f9
@ -19,4 +19,6 @@ interface IdGeneratorInterface
|
||||
const LEVEL_MILLISECOND = 2;
|
||||
|
||||
public function generate(?Meta $meta = null): int;
|
||||
|
||||
public function degenerate(int $id): Meta;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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)) {
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user