分布式ID生成器PHP+Swoole实现(下) - 代码实现
上篇文章主要介绍《实现原理》,这篇看主要代码的编写。
实现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实现(下) - 代码实现的更多相关文章
- 分布式ID生成器PHP+Swoole实现(上) - 实现原理
1.发号器介绍 什么是发号器? 全局唯一ID生成器,主要用于分库分表唯一ID,分布式系统数据的唯一标识. 是否需要发号器? 1)是否需要全局唯一. 分布式系统应该不受单点递增ID限制,中心式的会涉及到 ...
- c#分布式ID生成器
c#分布式ID生成器 简介 这个是根据twitter的snowflake来写的.这里有中文的介绍. 如上图所示,一个64位ID,除了最左边的符号位不用(固定为0,以保证生成的ID都是正数),还剩余 ...
- 来吧,自己动手撸一个分布式ID生成器组件
在经过了众多轮的面试之后,小林终于进入到了一家互联网公司的基础架构组,小林目前在公司有使用到架构组研究到分布式id生成器,前一阵子大概看了下其内部的实现,发现还是存在一些架构设计不合理之处.但是又由于 ...
- 分布式ID生成器(CosId)的设计与实现
分布式ID生成器(CosId)设计与实现 CosId 简介 CosId 旨在提供通用.灵活.高性能的分布式 ID 生成器. 目前提供了俩类 ID 生成器: SnowflakeId : 单机 TPS 性 ...
- 分布式ID生成器及redis,etcd分布式锁
分布式id生成器 有时我们需要能够生成类似MySQL自增ID这样不断增大,同时又不会重复的id.以支持业务中的高并发场景.比较典型的,电商促销时,短时间内会有大量的订单涌入到系统,比如每秒10w+.明 ...
- 常用的分布式ID生成器
为何需要分布式ID生成器 **本人博客网站 **IT小神 www.itxiaoshen.com **拿我们系统常用Mysql数据库来说,在之前的单体架构基本是单库结构,每个业务表的ID一般从1增,通过 ...
- go语言实现分布式id生成器
本文:https://chai2010.cn/advanced-go-programming-book/ch6-cloud/ch6-01-dist-id.html 分布式id生成器 有时我们需要能够生 ...
- 分布式ID生成器的解决方案总结
在互联网的业务系统中,涉及到各种各样的ID,如在支付系统中就会有支付ID.退款ID等.那一般生成ID都有哪些解决方案呢?特别是在复杂的分布式系统业务场景中,我们应该采用哪种适合自己的解决方案是十分重要 ...
- CosId 通用、灵活、高性能的分布式 ID 生成器
CosId 通用.灵活.高性能的分布式 ID 生成器 介绍 CosId 旨在提供通用.灵活.高性能的分布式系统 ID 生成器. 目前提供了俩大类 ID 生成器:SnowflakeId (单机 TPS ...
随机推荐
- 原生JS实现JQuery的addClass和removeClass
代码如下: document.getElementById("btn").classList.add("active"); document.getElemen ...
- 转载文章 208 个最常见 Java 面试题全解析
最近正值春招,一直在给公司招聘 Java 程序员,我从 2015 年做 TeamLeader 开始就习惯性地收集平时遇到的 Java 技术问题或周围朋友见过的面试题,经过不断筛选,终于凝练成一套实用的 ...
- Struts2的优点与Struts1的区别:
单实例与多实例有状态就是有数据存储功能,比如购物车,买一件东西放进去,可以再次购买或者删减.无状态就是一次操作,不能保存数据. 有状态对象,就是有成员属性的对象,可以保存数据,是非线程安全的.无状态对 ...
- 【bug】—— H5页面在 ios 端滑动不流畅的问题
IOS系统的惯性滑动效果非常6,但是当我们对div加overflow-y:auto;后是不会出这个效果的,滑动的时候会感觉很生涩.怎么办? 方案一: 在滚动容器内加-webkit-overflow-s ...
- Chrome获取微信授权,调试公众号页面
1.目的 你可能遇到过这种情况,在微信中打开公众号是这样的. 复制链接,在chrome中打开是这样的. 博主今天要解决的就是,如果在chrome中加载需要微信授权的页面,至于加载成功后要干嘛,测试?抓 ...
- mono for android生成APK出现错误fatal error in gc 解决方案
laxknight 标签: mono for android,fatal error in gc mono for android生成APK出现这个错误fatal error in gc collec ...
- Windows Server 2008 R2 Enterprise 上用 SqlServer 2008 R2 创建发布出现异常
标题: 新建发布向导------------------------------ SQL Server 无法将“AC”配置为分发服务器. ------------------------------其 ...
- (转)MySQL高可用解决方案
MySQL高可用解决方案 原文:http://www.ywnds.com/?p=5565 有这么两个概念,数据库的可靠性和数据库的可用性,可靠性指的是数据可靠,而可用性指的是服务可用.但是不管是可靠性 ...
- linux MD5 SHA1 等 文件校验方法
为解决官方发布的软件包被别人更改或者软件在传输过程中出现传输错误等问题,软件官方在提供软件包的同时,还提供一个保存MD5校验码的文件. Linux/unix中可以使用 md5sum 文件名 sha1s ...
- ok6410 android driver(1)
target system : Android (OK6410) host system : Debian Wheezy AMD64 1.Set up android system in ok6410 ...