Last active
August 29, 2015 14:27
-
-
Save guweigang/03563379a5c34f54ed85 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class Seq | |
{ | |
const CACHE_PREFIX = 'id-sequcence:'; | |
const STEP = 500; | |
private $dbConf = array(); | |
private $cacheConf = array(); | |
private $cacheClient = null; | |
private $dbClient = null; | |
/** | |
* Config Sample | |
<code> | |
$dbConf = array( | |
'host' => '127.0.0.1', | |
'port' => '3306', | |
'username' => 'root', | |
'password' => '', | |
'dbname' => 'test', | |
'charset' => 'utf8', | |
); | |
$cacheConf = array( | |
'host' => '127.0.0.1', | |
'port' => 6379, | |
'db' => 1, | |
'timeout' => 1, | |
); | |
</code> | |
* | |
*/ | |
public function __construct(array $dbConf, array $cacheConf) | |
{ | |
$this->dbConf = $dbConf; | |
$this->cacheConf = $cacheConf; | |
} | |
private function initCacheClient() | |
{ | |
if($this->cacheClient !== null) { | |
return ; | |
} | |
$this->cacheClient = new \Redis(); | |
try { | |
$this->cacheClient->connect($this->cacheConf['host'], $this->cacheConf['port'], $this->cacheConf['timeout']); | |
$this->cacheClient->select($this->cacheConf['db']); | |
} catch(\Exception $e) { | |
// @TODO ... | |
echo "redis: Connection failed: " . $e->getMessage(); | |
} | |
} | |
private function initDbClient() | |
{ | |
if($this->dbClient !== null) { | |
return ; | |
} | |
$dsn = "mysql:dbname=".$this->dbConf["dbname"].";host=".$this->dbConf['host'].";port=".$this->dbConf['port']; | |
try { | |
$this->dbClient = new \PDO( | |
$dsn, | |
$this->dbConf['username'], | |
$this->dbConf['password'], | |
array( | |
\PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES '{$this->dbConf['charset']}'", | |
) | |
); | |
} catch (PDOException $e) { | |
// @TODO ... | |
echo 'mysql: Connection failed: ' . $e->getMessage(); | |
} | |
} | |
/** | |
* 初始化序列 | |
*/ | |
public function create($app, $bucket, $start = 0) | |
{ | |
$this->initDbClient(); | |
$sql = "SET @maxId = (SELECT MAX(`id`) FROM `generation`); " . | |
"INSERT INTO `generation` (`id`, `app`, `bucket`, `seq`) VALUES " . | |
"(@maxId+1, '{$app}', '{$bucket}', '{$start}');"; | |
$rows = $this->dbClient->exec($sql); | |
if($rows <= 0) { | |
throw new \Exception("初始化ID序列失败"); | |
} | |
return true; | |
} | |
/** | |
* 序列发生器 | |
*/ | |
public function generate($app, $bucket, $step = 0) | |
{ | |
$this->initCacheClient(); | |
$cacheKey = self::CACHE_PREFIX . $app . ":" . $bucket; | |
if($step <= 500) { | |
$step = self::STEP; | |
} | |
if($pk = $this->cacheClient->lPop($cacheKey)) { | |
return $pk; | |
} else { | |
$this->initDbClient(); | |
$sql = "UPDATE `generation` SET `seq` = LAST_INSERT_ID(`seq` + {$step}) WHERE `app`='{$app}' AND `bucket`='{$bucket}'"; | |
$rows = $this->dbClient->exec($sql); | |
if($rows <= 0) { | |
throw new \Exception("网络繁忙"); | |
} | |
$sequence = $this->dbClient->lastInsertId(); | |
$this->push($cacheKey, $sequence, $step); | |
$pk = $this->generate($app, $bucket, $step); | |
return $pk; | |
} | |
} | |
/** | |
* Redis事务,向Redis中插入序列 | |
*/ | |
private function push($cacheKey, $sequence, $step) | |
{ | |
$this->initCacheClient(); | |
$this->cacheClient->watch($cacheKey); | |
$this->cacheClient->multi(); | |
for ($i = $step; $i > 0; $i--) { | |
$this->cacheClient->rPush($cacheKey, $sequence - $i + 1); | |
} | |
$this->cacheClient->exec(); | |
} | |
public function getList($app = "") | |
{ | |
$this->initDbClient(); | |
$sql = "SELECT * FROM `generation`"; | |
if($app != "") { | |
$sql .= " WHERE `app` = '{$app}'"; | |
} | |
$rows = $this->dbClient->query($sql); | |
return $rows->fetchAll(\PDO::FETCH_ASSOC); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
CREATE TABLE `generation` ( | |
`id` bigint(31) unsigned NOT NULL AUTO_INCREMENT, | |
`app` varchar(31) NOT NULL DEFAULT '', | |
`bucket` varchar(31) NOT NULL DEFAULT '', | |
`seq` bigint(20) NOT NULL, | |
`ctime` timestamp NOT NULL DEFAULT '2014-01-01 00:00:00', | |
`mtime` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, | |
PRIMARY KEY (`id`), | |
UNIQUE KEY `uk_app_bucket` (`app`,`bucket`) | |
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
require __DIR__."/Seq.php"; | |
$dbConf = array( | |
'host' => '127.0.0.1', | |
'port' => '3306', | |
'username' => 'p2pdev', | |
'password' => 'devdev', | |
'dbname' => 'test', | |
'charset' => 'utf8', | |
); | |
$cacheConf = array( | |
'host' => '127.0.0.1', | |
'port' => 6379, | |
'db' => 1, | |
'timeout' => 1, | |
); | |
$seq = new \Seq($dbConf, $cacheConf); | |
// 创建序列 | |
// $seq->create("stock", "orderId", 0); | |
echo $seq->generate("stock", "orderId"); | |
echo PHP_EOL; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment