分布式ID生成器PHP+Swoole实现(下) - 代码实现
2018-10-30 15:00
411 查看
上篇文章主要介绍《实现原理》,这篇看主要代码的编写。
实现IDGenerator类
- 64位ID由以下元素组成:固定位占2位,时间戳占41位,服务实例数字编号占4位,业务编号占10位,自增id占7位
const BITS_FULL = 64; const BITS_PRE = 2; // 固定位01 const BITS_TIME = 41; // 可支持69年 const BITS_SERVER = 4; // 可支持16台集群服务 const BITS_WORKER = 10; // 可支持业务数1024个 const BITS_SEQUENCE = 7; // 一毫秒内支持生成128个id
- 定义好三个变量: $sequence_id: 自增序列id,在同一毫秒内产生的ID由此变量进行递增区分
- $last_timestamp: 最后一次产生ID时的毫秒级时间戳,与下一次生成ID时的时间进行比较,如果时间相同则进行$sequence_id++,如果不同$sequence_id置0从新开始计算。
- $server_id: 服务器id编号,代表不同的分布式服务实例,服务启动时指定。
private $sequence_id = 0; private $last_timestamp = 0; private $server_id = 0;
- EPOCH_TIME,由过去最近的一个时间值作为比较基数,如下值为2018-10-30 00:00:00
const EPOCH_TIME = 1540828800000; //时间基数
- 获取一个64位ID主要由以下位运算完成
/** * 获取id */ function get($worker_id = 0) { //初始化id位 $id = pow(2, 62); /* 1. 时间戳 41位 */ $time = $this->timeGen(); $diff_time = $time - self::EPOCH_TIME; $shift = self::BITS_FULL - self::BITS_PRE - self::BITS_TIME; $id |= $diff_time << $shift; /* 2. 服务器id */ $shift -= self::BITS_SERVER; $id |= ($this->server_id & (pow(2, self::BITS_SERVER) - 1)) << $shift; /* 3. 业务id */ $shift -= self::BITS_WORKER; $id |= ($worker_id & (pow(2, self::BITS_WORKER) - 1)) << $shift; /* 4. 自增id */ $id |= ($this->sequence_id % (pow(2, self::BITS_SEQUENCE) - 1)); $this->sequence_id++; return $id; } /** * 获取当前时间 */ function timeGen() { $wait_next_ms = 0; do { if($wait_next_ms > 0) { usleep(100); //等待下一毫秒,休眠0.1毫秒 } $timestamp = microtime(true) * 1000; $timestamp = (int) $timestamp; if($this->last_timestamp < $timestamp) { $this->sequence_id = 0; } $wait_next_ms++; } while ($this->last_timestamp == $timestamp && $this->sequence_id >= (pow(2, self::BITS_SEQUENCE) - 1) || $this->last_timestamp > $timestamp); $this->last_timestamp = $timestamp; return $timestamp; }
实现Swoole redis服务
$shortopts = 's:p'; // s服务ID编号, p绑定端口 $options = getopt($shortopts); // 由swoole_table存储最后一次产生数据的相关值 $table = new swoole_table(2048); $table->column('sequence_id', swoole_table::TYPE_INT); $table->column('last_timestamp', swoole_table::TYPE_FLOAT); $table->column('server_id', swoole_table::TYPE_INT); $table->create(); // atomic分业务加锁 for ($i = 0; $i <= 1023; $i++) { $atomics[$i] = new swoole_atomic(0); } $serv = new Server("0.0.0.0", $options['p']); $serv->table = $table; $serv->atomics = $atomics; $IDGen_config = array( 'server_id' => $options['s'], 'last_timestamp' => 0, 'sequence_id' => 0, ); $serv->table->set('key:idgen_config', $IDGen_config); $serv->on('start', function ($serv) use($options) { // 启动事件 }); //监听redis get指令 $serv->setHandler('GET', function ($fd, $data) use ($serv) { $data = trim($data[0]); $IDGen = new IDGen(); $id = $IDGen->get(); return Server::format(Server::STRING, $id); }); $serv->start();
Redis-cli连接测试
redis-cli -h 172.19.19.21 -p 9500 172.19.19.21:9500> get 1 "4747443928557682816" 172.19.19.21:9500> get 2 "4747443933230137600"
相关文章推荐
- 分布式ID生成器PHP+Swoole实现(上) - 实现原理
- Twitter的分布式自增ID算法Snowflake实现分析及其Java、Php和Python版
- php下获取Discuz论坛登录用户名、用户组、用户ID等信息的实现代码
- PHP通过session id 实现session共享和登录验证的代码
- Twitter的分布式自增ID算法Snowflake的PHP实现,Snowflake PHP版本,高并发唯一id,全局唯一id,不重复id
- [转] Twitter的分布式自增ID算法Snowflake实现分析及其Java、Php和Python版
- php生成SessionID和图片校验码的思路和实现代码
- php+redis+lua+id生成器,分布式id生成器
- php下获取Discuz论坛登录用户名、用户组、用户ID等信息的实现代码
- PHP通过session id 实现session共享和登录验证的代码
- Twitter的分布式自增ID算法Snowflake实现分析及其Java、Php和Python版
- php下获取Discuz论坛登录用户名、用户组、用户ID等信息的实现代码
- PHP通过session id 实现session共享和登录验证的代码
- Golang实现snowflake算法(分布式唯一id生成器)
- ZooKeeper 实现命名服务(分布式的ID生成器)
- php生成SessionID和图片校验码的思路和实现代码
- 细聊分布式ID生成方法的实现(一个可以使用10年的序列生成器)
- PHP通过session id 实现session共享和登录验证的代码
- PHP通过session id 实现session共享和登录验证的代码
- php视频拍照上传头像功能实现代码分享