当前位置:   LINUX > 正文

PHP实现Snowflake生成分布式唯一ID

php,swoole,go,分布式,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具,前端开发工具,开发人员工具,站长工具
生成的数值是 64 位,分成 4 个部分:

  • 第一个 bit 为符号位,最高位为 0 表示正数
  • 第二部分 41 个 bit 用于记录生成 ID 时候的时间戳,单位为毫秒,所以该部分表示的数值范围为 2^41 - 1(69 年),它是相对于某一时间的偏移量
  • 第三部分的 10 个 bit 表示工作节点的 ID,表示数值范围为 2^10 - 1,相当于支持 1024 个节点
  • 第四部分 12 个 bit 表示每个工作节点没毫秒生成的循环自增 id,最多可以生成 2^12 -1 个 id,超出归零等待下一毫秒重新自增

先贴下代码:

 self::WORKER_MAX) {
            trigger_error("Worker ID 超出范围");
            exit(0);
        }

        $this->timestamp = 0;
        $this->workerId = $workerId;
        $this->sequence = 0;
        $this->lock = new swoole_lock(SWOOLE_MUTEX);
    }

    /**
     * 生成ID
     * @return int
     */
    public function getId()
    {
        $this->lock->lock();    // 这里一定要记得加锁
        $now = $this->now();
        if ($this->timestamp == $now) {
            $this->sequence++;

            if ($this->sequence > self::SEQUENCE_MAX) {
                // 当前毫秒内生成的序号已经超出最大范围,等待下一毫秒重新生成
                while ($now <= $this->timestamp) {
                    $now = $this->now();
                }
            }
        } else {
            $this->sequence = 0;
        }

        $this->timestamp = $now;    // 更新ID生时间戳

        $id = (($now - self::EPOCH) << self::TIME_SHIFT) | ($this->workerId << self::WORKER_SHIFT) | $this->sequence;
        $this->lock->unlock();  //解锁

        return $id;
    }

    /**
     * 获取当前毫秒
     * @return string
     */
    public function now()
    {
        return sprintf("%.0f", microtime(true) * 1000);
    }

}

其实逻辑并不复杂,解释一下代码中的位运算:

-1 ^ (-1 << self::SEQUENCE_BITS)
就是-1的二进制表示为1的补码,其实等同于 :
2**self::SEQUENCE_BITS - 1

最后部分左移后或运算:

(($now - self::EPOCH) << self::TIME_SHIFT) | ($this->workerId << self::WORKER_SHIFT) | $this->sequence;

这里主要是对除了第一位符号位以外的三个部分进行左移相应的偏移量使其归位,并通过或运算重新整合成上面 snowflake 的结构,比如我们用 3 部分 4 位来演示一下该归并操作:

0000 0000 0010  --左移0位--> 0000 0000 0010
0000 0000 0100  --左移4位--> 0000 0100 0000 --或操作-->1000 0100 0010
0000 0000 1000  --左移8位--> 1000 0000 0000

下面借助 Swoole 的协程和 channel 来暴力测试一下,看看生成的 ID 是否会出现重复的状况:

$snowflake = new Snowflake(1);

$chan = new chan(100000);
$n = 100000;

for ($i = 0; $i < $n; $i++) {
    go(function () use ($snowflake, $chan) {
        $id = $snowflake->getId();
        $chan->push($id);
    });
}

go(function () use ($chan, $n) {
    $arr = [];
    for ($i = 0; $i < $n; $i++) {
        $id = $chan->pop();  // PHP Swoole的channel一定要写在go(func)的协程里面!?
        if (in_array($id, $arr)) {
            exit("ID 已存在");
        }
        array_push($arr, $id);
    }
});

$chan->close();

echo "ok";

跑了一下,确实不会出现重复的 ID,对了,我用 Golang 同样实现了 snowflake 并协程序方式跑了同样的测试,PHP 的执行时间是大约 12 秒左右,Golang 只需要 1 秒。文章有什么错误还请指正,谢谢。

以上就是PHP实现Snowflake生成分布式唯一ID的详细内容,更多请关注 第一PHP社区 其它相关文章!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/blog/LINUX/detail/17618
推荐阅读
  • 最近需要使用一个外部接口,开始没有想到用curl_multi_init,就用了多进程,尝试了pcntl和swoole_process,效果都很好。但是外部接口有一个限制,一秒内不能超过5个请求,这种情况在多进程下要怎么控制呢?需要考php,... [详细]

  • 如何解决《在Windows和Linux中使用fscanf时,行尾不同的字符》经验,为你挑选了1个好方法。c,linux,windows,newline,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二... [详细]

  • 如何解决《如何生成在AndroidStudio或Intellij-Idea中返回Object(self)的setter》经验,为你挑选了1个好方法。java,android,intellij-idea,android-studio,wind... [详细]

  • 做php已经5年多了,想往架构级phper发展。请问,架构级需要掌握哪些知识,循序渐进的过程怎么走?麻烦说的细一点phper,php,linux,nginx,mysql,程序员,swoole,分布式,算法,redis,sql,服务器,百度,... [详细]

  • canal是主要用途是基于MySQL数据库增量日志解析,提供增量数据订阅和消费,本栏目详细介绍基于canal实现mysql的数据同步。canal,mysql数据同步,mysql,docker,容器,vim,编辑器,服务器,https,git... [详细]

  • 本文给大家推荐的是一款PHP的中文分词工具类,功能包括支持汉字转拼音、拼音分词、简繁互转。非常不错,有需要的小伙伴可以参考下PHP中文转拼音工具,将汉字转成拼音的工具类,汉字转拼音工具类,php,swoole,go,DevBox,在线流程图... [详细]

  • 每日一搏|100行PHP代码实现socks5代理服务器每日一搏|100行PHP代码实现socks5代理服务器,php,swoole,https,git,go,服务器,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,j... [详细]

  • php编写网络爬虫php编写网络爬虫,swoole,html,php,爬虫,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具,前端开发工具,开发人员工具,站长工具... [详细]

  • 基于swoole扩展的phpwebsocket基于swoole扩展的phpwebsocket,php,websocket,swoole,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,uni... [详细]

  • php的事件处理机制(回调函数)php的事件处理机制(回调函数),php,swoole,mvc,百度,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具,前端开发工... [详细]

  • 如何解决《在Solaris和Linux上确定进程位数的最简单方法》经验,为你挑选了1个好方法。unix,linux,shell,solaris,process,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json... [详细]

  • 如何解决《互斥锁如何在低级别等待解锁?》经验,为你挑选了1个好方法。c++,multithreading,mutex,locking,linux,算法,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二... [详细]

  • 如何解决《我的剧本有什么问题,请告诉我》经验,为你挑选了1个好方法。linux,perl,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具,前端开发工具,开发人员... [详细]

  • 如何解决《如何在QtCmake项目中使用QML_IMPORT_PATH?》经验,为你挑选了1个好方法。c++,qt,linux,bash,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,un... [详细]

  • 小编也是刚接触swoole,官方文档给swooledemo信息量也非常的少,有些地方也没有说清楚,折腾了一,两天websocket终于握手成功,写下我的心得,希望能给有需要的人一些帮助。首先我先介绍我的运行环境是直接放在外网服务器的,程序运... [详细]

  • 比如现在有个需求,就是给大量用户发送邮件:{代码}对于以上事例代码的用户体验就很差,实际上也没人会这么干,那么怎样使用程序后台异步执行,而又不影响用户的体验呢?求思路php,异步,html,redis,swoole,linux,DevBox... [详细]

  • 想利用swoole做一个消息通知,比如有未读的评论,私信就像官网这样,在顶部提示你有几个未采纳答案这样子的需求。然后我就看了下swoole。可以利用html5最新的WebSocket特性来做,倒是简单,就是考虑到WebSockswoole,... [详细]

  • 这篇文章主要介绍了centos7环境下swoole1.9的安装与HttpServer的使用方法,结合实例形式分析了centos7环境下swoole1.9的安装、配置方法以及HttpServer的相关使用技巧,需要的朋友可以参考下centos... [详细]

  • 如何解决《跨不同的tmux版本启用鼠标支持》经验,为你挑选了1个好方法。tmux,linux,DevBox,在线流程图,编程,编程问答,程序员,开发者工具,开发工具,json解析,二维码生成,unix时间戳,在线开发工具,前端开发工具,开发... [详细]

  • 1.查看swoole文档只看到异步mysql的实现,但是没有看到具体应用,也可能是我没看到,就想问下在一个请求中我使用异步查询mysql,异步查询会调用callback,请问我应该怎么在这个请求里获取到这个callback的查询结果php,... [详细]

相关标签
  

闽ICP备14008679号