Skip to content

Commit

Permalink
Merge pull request #2 from dekuan/dev
Browse files Browse the repository at this point in the history
upgrade readme.md
  • Loading branch information
dekuan committed Aug 4, 2017
2 parents cc3d994 + 5bbae15 commit ddfcda8
Show file tree
Hide file tree
Showing 4 changed files with 212 additions and 57 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
/.idea/
/vendor/
composer.lock
test-result.json
test-unique.json
128 changes: 126 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,126 @@
# dedid
An unique id generator for distributed database
# dekuan/dedid
An unique id generator for primary key of distributed database



# ALGORITHM

### Bit structure
It's a 64 bits bigint.

~~~
0 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx x xxxxxx xxxxxx xx xxxxxxxx
~~~

### Details

Bits | Usage | Remark
----------|---------|--------
0 | Reserved| Always be 0
41 | Escaped Time (in millisecond)|0~69 years
6 | Data center|0~63
6 | Data node in the data center |0~63
10 | Random|0~1023




# Mark bits

### Center
~~~
0 00000000 00000000 00000000 00000000 00000000 0 111111 000000 00 00000000
00000000 00000000 00000000 00000000 00000000 00111111 00000000 00000000
00 00 00 00 00 3F 00 00
~~~

### Node
~~~
0 00000000 00000000 00000000 00000000 00000000 0 000000 111111 00 00000000
00000000 00000000 00000000 00000000 00000000 00000000 11111100 00000000
00 00 00 00 00 00 FC 00
~~~


### Escaped Time
~~~
0 11111111 11111111 11111111 11111111 11111111 1 000000 000000 00 00000000
01111111 11111111 11111111 11111111 11111111 11000000 00000000 00000000
7F FF FF FF FF C0 00 00
~~~


### Random
~~~
0 00000000 00000000 00000000 00000000 00000000 0 000000 000000 11 11111111
00000000 00000000 00000000 00000000 00000000 00000000 00000011 11111111
00 00 00 00 00 00 03 FF
~~~


# HOW TO USE

### Create an new id

~~~
$cDId = CDId::getInstance();
$nCenter = 61;
$nNode = 37;
$arrD = [];
$nNewId = $cDId->createId( $nCenter, $nNode, $arrD );
echo "new id = " . $nNewId . "\r\n";
print_r( $arrD );
~~~

##### output

~~~
new id = 98037672957548006
Array
(
[center] => 61
[node] => 37
[time] => 23374002684
[rand] => 486
)
~~~


### Parse an id for getting the details

~~~
$cDId = CDId::getInstance();
$arrId = $cDId->parseId( 98037672957548006 );
print_r( $arrId );
~~~

##### output

~~~
Array
(
[center] => 61
[node] => 37
[time] => 23374002684
[rand] => 486
)
~~~


# INSTALL
~~~
# composer require dekuan/dedid
~~~
For more information, please visit [https://packagist.org/packages/dekuan/dedid](https://packagist.org/packages/dekuan/dedid)
93 changes: 49 additions & 44 deletions src/CDId.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,33 +7,39 @@
// ================================================================================
//
//
// 0 xxxxxx xxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xx xxxxxxxx
// - ------ ------- -------------------------------------------- -----------
// Host Table Escaped Time (in millisecond) Random
// 1 6 7 40 bits 10 bits
// 0~63 0~127 0~34 (years) 0~1023
// 0 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx x xxxxxx xxxxxx xx xxxxxxxx
// - ---------------------------------------------- ------ ------ -----------
// Escaped Time (in millisecond) Center Node Random
// 1 41 bits 6 6 10 bits
// 0~69 (years) 0~63 0~63 0~1023
//
//
// host
// 01111110 00000000 00000000 00000000 00000000 00000000 00000000 00000000
// 7E 00 00 00 00 00 00 00
// Center
// 0 00000000 00000000 00000000 00000000 00000000 0 111111 000000 00 00000000
// 00000000 00000000 00000000 00000000 00000000 00111111 00000000 00000000
// 00 00 00 00 00 3F 00 00
//
// table
// 00000001 11111100 00000000 00000000 00000000 00000000 00000000 00000000
// 01 FC 00 00 00 00 00 00
// Node
// 0 00000000 00000000 00000000 00000000 00000000 0 000000 111111 00 00000000
// 00000000 00000000 00000000 00000000 00000000 00000000 11111100 00000000
// 00 00 00 00 00 00 FC 00
//
// escaped time
// 00000000 00000011 11111111 11111111 11111111 11111111 11111100 00000000
// 00 03 FF FF FF FF FC 00
//
// random
// Escaped Time
// 0 11111111 11111111 11111111 11111111 11111111 1 000000 000000 00 00000000
// 01111111 11111111 11111111 11111111 11111111 11000000 00000000 00000000
// 7F FF FF FF FF C0 00 00
//
// Random
// 0 00000000 00000000 00000000 00000000 00000000 0 000000 000000 11 11111111
// 00000000 00000000 00000000 00000000 00000000 00000000 00000011 11111111
// 00 00 00 00 00 00 03 FF
//



/**
* CDId
* An unique id generator for primary key of distributed database
* class CDId
*/
class CDId
{
Expand All @@ -47,8 +53,6 @@ class CDId
*/
CONST EPOCH_OFFSET = 1478476800000;





public function __construct()
Expand All @@ -70,18 +74,18 @@ static function getInstance()
/**
* Generate an unique id
*
* @param $nHost int host id ( 0 ~ 63 )
* @param $nTable int table id ( 0 ~ 127 )
* @param $nCenter int data center id ( 0 ~ 63 )
* @param $nNode int data node id ( 0 ~ 63 )
* @param $arrData &array details about the id
* @return int(64) id
*/
public function createId( $nHost, $nTable, & $arrData = null )
public function createId( $nCenter, $nNode, & $arrData = null )
{
if ( ! $this->isValidHostId( $nHost ) )
if ( ! $this->isValidCenterId( $nCenter ) )
{
return null;
}
if ( ! $this->isValidTableId( $nTable ) )
if ( ! $this->isValidNodeId( $nNode ) )
{
return null;
}
Expand All @@ -91,22 +95,22 @@ public function createId( $nHost, $nTable, & $arrData = null )
$nTime = $this->getEscapedTime();
$nRand = rand( 0, 0x3FF );

$nHostV = ( ( $nHost << 57 ) & 0x7E00000000000000 );
$nTabV = ( ( $nTable << 50 ) & 0x01FC000000000000 );
$nTimeV = ( ( $nTime << 10 ) & 0x0003FFFFFFFFFC00 );
$nRandV = ( ( $nRand << 0 ) & 0x00000000000003FF );
$nCenterV = ( ( $nCenter << 16 ) & 0x00000000003F0000 );
$nNodeV = ( ( $nNode << 10 ) & 0x000000000000FC00 );
$nTimeV = ( ( $nTime << 22 ) & 0x7FFFFFFFFFC00000 );
$nRandV = ( ( $nRand << 0 ) & 0x00000000000003FF );

$nRet = ( $nHostV + $nTabV + $nTimeV + $nRandV );
$nRet = ( $nCenterV + $nNodeV + $nTimeV + $nRandV );

// ...
if ( ! is_null( $arrData ) )
{
$arrData =
[
'host' => $nHost,
'table' => $nTable,
'time' => $nTime,
'rand' => $nRand,
'center' => $nCenter,
'node' => $nNode,
'time' => $nTime,
'rand' => $nRand,
];
}

Expand All @@ -126,27 +130,28 @@ public function parseId( $nId )
return null;
}

$nHost = ( ( $nId & 0x7E00000000000000 ) >> 57 );
$nTable = ( ( $nId & 0x01FC000000000000 ) >> 50 );
$nTime = ( ( $nId & 0x0003FFFFFFFFFC00 ) >> 10 );
$nRand = ( ( $nId & 0x00000000000003FF ) >> 0 );
// ...
$nCenter = ( ( $nId & 0x00000000003F0000 ) >> 16 );
$nNode = ( ( $nId & 0x000000000000FC00 ) >> 10 );
$nTime = ( ( $nId & 0x7FFFFFFFFFC00000 ) >> 22 );
$nRand = ( ( $nId & 0x00000000000003FF ) >> 0 );

return
[
'host' => $nHost,
'table' => $nTable,
'time' => $nTime,
'rand' => $nRand,
'center' => $nCenter,
'node' => $nNode,
'time' => $nTime,
'rand' => $nRand,
];
}

public function isValidHostId( $nVal )
public function isValidCenterId( $nVal )
{
return is_numeric( $nVal ) && ( $nVal >= 0 ) && ( $nVal <= 63 );
}
public function isValidTableId( $nVal )
public function isValidNodeId( $nVal )
{
return is_numeric( $nVal ) && ( $nVal >= 0 ) && ( $nVal <= 127 );
return is_numeric( $nVal ) && ( $nVal >= 0 ) && ( $nVal <= 63 );
}


Expand Down
46 changes: 35 additions & 11 deletions tests/TestIdGenerator.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,47 @@
*/
class TestIdGenerator extends PHPUnit_Framework_TestCase
{
public function testCreateNew()
public function testCreateNewMore()
{
$cDId = CDId::getInstance();
$nHostMax = 63;
$nTableMax = 63;

for ( $nCenter = 0; $nCenter <= $nHostMax; $nCenter ++ )
{
for ( $nNode = 0; $nNode <= $nTableMax; $nNode ++ )
{
$arrD = [];
$nNewId = $cDId->createId( $nCenter, $nNode, $arrD );
$arrId = $cDId->parseId( $nNewId );

$this->assertSame( $arrId, $arrD );

echo __FUNCTION__ . " :: createId = " . $nNewId . "\r\n";
echo __FUNCTION__ . " :: parseId\r\n";
print_r( $arrId );
}
}

}

public function testCreateNewBatch()
{
$cDId = CDId::getInstance();

$arrResult = [];
$arrUnique = [];
$nHostMax = 63;
$nTableMax = 127;
$nTableMax = 63;

for ( $i = 0; $i < 1; $i ++ )
{
for ( $nHost = 0; $nHost <= $nHostMax; $nHost ++ )
for ( $nCenter = 0; $nCenter <= $nHostMax; $nCenter ++ )
{
for ( $nTable = 0; $nTable <= $nTableMax; $nTable ++ )
for ( $nNode = 0; $nNode <= $nTableMax; $nNode ++ )
{
$arrD = [];
$nNewId = $cDId->createId( $nHost, $nTable, $arrD );
$nNewId = $cDId->createId( $nCenter, $nNode, $arrD );
$arrId = $cDId->parseId( $nNewId );

$sHexId = dechex( $nNewId );
Expand All @@ -58,8 +82,8 @@ public function testCreateNew()

$arrItem =
[
'h' => $nHost,
't' => $nTable,
'h' => $nCenter,
't' => $nNode,
'id' => $nNewId,
'r' => $arrId,
];
Expand All @@ -68,14 +92,14 @@ public function testCreateNew()
$arrResult[] = $arrItem;
$arrUnique[ $nNewId ] = $arrItem;
}
}
}
}


var_dump( count( $arrResult ), count( $arrUnique ) );
//
// file_put_contents( 'result.json', json_encode( $arrResult ) );
// file_put_contents( 'unique.json', json_encode( $arrUnique ) );

file_put_contents( 'test-result.json', json_encode( $arrResult ) );
file_put_contents( 'test-unique.json', json_encode( $arrUnique ) );

}

Expand Down

0 comments on commit ddfcda8

Please sign in to comment.