惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

有赞技术团队
有赞技术团队
Martin Fowler
Martin Fowler
N
Netflix TechBlog - Medium
WordPress大学
WordPress大学
罗磊的独立博客
H
Help Net Security
MongoDB | Blog
MongoDB | Blog
A
About on SuperTechFans
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
D
Docker
云风的 BLOG
云风的 BLOG
Microsoft Security Blog
Microsoft Security Blog
Blog — PlanetScale
Blog — PlanetScale
P
Proofpoint News Feed
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
I
InfoQ
J
Java Code Geeks
博客园 - 聂微东
大猫的无限游戏
大猫的无限游戏
Engineering at Meta
Engineering at Meta
美团技术团队
小众软件
小众软件
Stack Overflow Blog
Stack Overflow Blog
C
Check Point Blog

希仁之拥

领克900半年使用体验 | 希仁之拥的博客 Ubuntu 26.04 Desktop使用体验 | 希仁之拥的博客 【转载】谈谈不受欢迎的博客技术特征 | 希仁之拥的博客 【转载】ClaudeCode 你想知道的所有秘密,源码深度研究报告 | 希仁之拥的博客 2025年年终总结 | 希仁之拥的博客 集成和使用Openclaw后的思考 | 希仁之拥的博客 我买了领克900 | 希仁之拥的博客 服务器性能优化之io拷贝 | 希仁之拥的博客 Go-Sail导航站上线啦 | 希仁之拥的博客 今年国庆的一些感受 [2025] | 希仁之拥的博客 在Deepin 25上配置forticlient | 希仁之拥的博客 分享一些酷酷的站点 [20250908] | 希仁之拥的博客 Go-Sail发布v3.0.6版本了 | 希仁之拥的博客 我对V2EX发布$V2EX讨论的一些感受 | 希仁之拥的博客 如何让Stripe支持支付宝和微信支付 | 希仁之拥的博客 2025上半年里程碑 | 希仁之拥的博客 GitLab+Drone使用体验 | 希仁之拥的博客 四姑娘山之旅 | 希仁之拥的博客 近来帮同事做性能优化的过程回顾 | 希仁之拥的博客 聊聊接口的返回数据结构 | 希仁之拥的博客 由GORM的Updates语法糖 我把 Go-Sail 的文档站更新了 | 希仁之拥的博客 这就是我为什么讨厌拼多多 | 希仁之拥的博客 元旦快乐~ | 希仁之拥的博客 致敬还在写博客的我们 | 希仁之拥的博客 逐步的把图片资源迁移到星光图床上 | 希仁之拥的博客 帮弟弟配了一台mini主机 | 希仁之拥的博客 国庆的一些碎碎念 | 希仁之拥的博客 就这一刻而言,我觉得科技冷冰冰的。 | 希仁之拥的博客 如何使用acme.sh自动续签证书 | 希仁之拥的博客
php使用mysqlnd扩展进行mysql异步并行查询 | 希仁之拥的博客
希仁之拥 · 2018-06-27 · via 希仁之拥

吃水不忘挖井人,thanks to Eric Don

示例代码如下:

class AnsycQuery
{
    public $connection_timout = 3;

    public function __construct($worlds)
    {
        $this->_batch_connections = ['logdb'=>collect()];
        //初始化连接实例
        foreach ($worlds as $world) {
            if (!$world->status)
            {
                //未启用的world不允许实时查询
                continue;
            }
            $logdb_connection = $world->getLogDBConnection()->getDB();
            $logdb_config = [
                'host' => $logdb_connection->getConfig('host'),
                'port' => $logdb_connection->getConfig('port'),
                'user' => $logdb_connection->getConfig('username'),
                'password' => $logdb_connection->getConfig('password'),
                'dbname' => $logdb_connection->getConfig('database')
            ];
            $retry=0;
            while(++$retry)
            {
                try {
                    $logdb = mysqli_init();
                    $logdb->options(MYSQLI_OPT_CONNECT_TIMEOUT, $this->connection_timout);
                    $logdb->real_connect($logdb_config['host'], $logdb_config['user'], $logdb_config['password'], $logdb_config['dbname'], $logdb_config['port']);
                    $logdb->query("set names utf8");
                    $this->_batch_connections['logdb']->put($world->id,$logdb);
                    break;
                }catch (\Exception $e)
                {
                    if($retry>5)
                    {
                        \App::abort(500,"服务器:".$world->id."的logdb数据库连接超时({$this->connection_timout}秒*5次尝试)");
                    }
                }
            }

        }
        return $this->_batch_connections;
    }

    public function query($from="gamedb", $sql)
    {
        switch ($from)
        {
            case "logdb":
                $connections = $this->_batch_connections['logdb'];
                break;
            default:
                return false;
                break;
        }

        foreach ($connections as $world_id=>$connection)
        {
            $replaced_sql = str_replace('{world_id}', $world_id, $sql);
            //文档地址:http://php.net/manual/zh/mysqli.query.php
            $connection->query($replaced_sql, MYSQLI_ASYNC);
        }

        $processed = 0;
        $ret = collect();
        //开始执行并行查询
        do {
            $links = $errors = $reject = array();
            foreach ($connections as $link) {
                $links[] = $errors[] = $reject[] = $link;
            }
            if (!mysqli_poll($links, $errors, $reject, 1)) {
                continue;
            }
            foreach ($links as $link) {
                if($result = $link->reap_async_query()) {
                    if(is_object($result)){
                        while($row = $result->fetch_object())
                        {
                            $ret->push($row);
                        }
                        mysqli_free_result($result);
                    }else if (false !== $result) {
                        //据文档说,insert, delete之类的,会在这里返回
                        $ret->push($result);
                    } else {
                        throw new \mysqli_sql_exception(mysqli_error($link));
                    }
                }
                $processed++;
            }
        } while ($processed < $connections->count());
        return $ret;
    }
}

注意:并行批量查询,需要服务器的php安装mysqlnd扩展,ubuntu下执行apt-get install php5-mysqlnd,然后执行php5enmod mysqlnd,mysqli也是需要开启的

由于是并行查询,每次返回结果顺序可能都会有差异。