Swoole 中使用 PDO 連接池、Redis 連接池、Mysqli 連接池


連接池使用說明

  • 所有連接池的實現均基於 ConnectionPool 原始連接池;
  • 連接池的底層原理是基於 Channel 的自動調度;
  • 開發者需要自己保證歸還的連接是可重用的;
  • 若連接不可重用,需要調用 $pool->put(null); 歸還一個空連接;
  • 歸還空連接后,原始連接池會重新創建連接以保證連接池的數量一致。

PDO 連接池

<?php
declare(strict_types=1);

use Swoole\Coroutine;
use Swoole\Database\PDOConfig;
use Swoole\Database\PDOPool;
use Swoole\Runtime;

Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]);
$s = microtime(true);
const N = 1024;

Coroutine\run(function () {
    $config = (new PDOConfig)
        ->withHost('127.0.0.1')
        ->withPort(3306)
        // ->withUnixSocket('/tmp/mysql.sock')
        ->withDbName('test')
        ->withCharset('utf8mb4')
        ->withUsername('root')
        ->withPassword('root');
    // 創建連接池對象,默認創建64個連接
    $pool = new PDOPool($config);
    
    for ($n = N; $n--;) {
        Coroutine::create(function () use ($pool) {
            // 獲取連接
            $pdo = $pool->get();
            $statement = $pdo->prepare('SELECT ? + ?');
            if (!$statement) {
                throw new RuntimeException('Prepare failed');
            }
            $a = mt_rand(1, 100);
            $b = mt_rand(1, 100);
            $result = $statement->execute([$a, $b]);
            if (!$result) {
                throw new RuntimeException('Execute failed');
            }
            $result = $statement->fetchAll();
            if ($a + $b !== (int)$result[0][0]) {
                throw new RuntimeException('Bad result');
            }
            // 回收連接
            $pool->put($pdo);
        });
    }
});

$s = microtime(true) - $s;
echo 'Use ' . $s . 's for ' . N . ' queries' . PHP_EOL;

Redis 連接池

<?php
declare(strict_types=1);

use Swoole\Coroutine;
use Swoole\Database\RedisConfig;
use Swoole\Database\RedisPool;
use Swoole\Runtime;

Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]);
$s = microtime(true);
const N = 1024;

Coroutine\run(function () {
    $config = (new RedisConfig)
        ->withHost('127.0.0.1')
        ->withPort(6379)
        ->withAuth('')
        ->withDbIndex(0)
        ->withTimeout(1);
    // 創建連接池對象,默認創建64個連接
    $pool = new RedisPool($config);
    
    for ($n = N; $n--;) {
        Coroutine::create(function () use ($pool) {
            // 獲取連接
            $redis = $pool->get();
            $result = $redis->set('foo', 'bar');
            if (!$result) {
                throw new RuntimeException('Set failed');
            }
            $result = $redis->get('foo');
            if ($result !== 'bar') {
                throw new RuntimeException('Get failed');
            }
            // 回收連接
            $pool->put($redis);
        });
    }
});

$s = microtime(true) - $s;
echo 'Use ' . $s . 's for ' . (N * 2) . ' queries' . PHP_EOL;

Mysqli 連接池

<?php
declare(strict_types=1);

use Swoole\Coroutine;
use Swoole\Database\MysqliConfig;
use Swoole\Database\MysqliPool;
use Swoole\Runtime;

Co::set(['hook_flags'=> SWOOLE_HOOK_ALL]);
$s = microtime(true);
const N = 1024;

Coroutine\run(function () {
    $config = (new MysqliConfig)
        ->withHost('127.0.0.1')
        ->withPort(3306)
        // ->withUnixSocket('/tmp/mysql.sock')
        ->withDbName('test')
        ->withCharset('utf8mb4')
        ->withUsername('root')
        ->withPassword('root');
    // 創建連接池對象,默認創建64個連接
    $pool = new MysqliPool($config);
    for ($n = N; $n--;) {
        Coroutine::create(function () use ($pool) {
            // 獲取連接
            $mysqli = $pool->get();
            $statement = $mysqli->prepare('SELECT ? + ?');
            if (!$statement) {
                throw new RuntimeException('Prepare failed');
            }
            $a = mt_rand(1, 100);
            $b = mt_rand(1, 100);
            if (!$statement->bind_param('dd', $a, $b)) {
                throw new RuntimeException('Bind param failed');
            }
            if (!$statement->execute()) {
                throw new RuntimeException('Execute failed');
            }
            if (!$statement->bind_result($result)) {
                throw new RuntimeException('Bind result failed');
            }
            if (!$statement->fetch()) {
                throw new RuntimeException('Fetch failed');
            }
            if ($a + $b !== (int)$result) {
                throw new RuntimeException('Bad result');
            }
            while ($statement->fetch()) {
                continue;
            }
            // 回收連接
            $pool->put($mysqli);
        });
    }
});

$s = microtime(true) - $s;
echo 'Use ' . $s . 's for ' . N . ' queries' . PHP_EOL;


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM