mysql 连接池 pdo_Swoole 中使用 PDO 连接池、Redis 连接池、Mysqli 连接池

巢皓君
2023-12-01

连接池使用说明

所有连接池的实现均基于 ConnectionPool 原始连接池;

连接池的底层原理是基于 Channel 的自动调度;

开发者需要自己保证归还的连接是可重用的;

若连接不可重用,需要调用 $pool->put(null); 归还一个空连接;

归还空连接后,原始连接池会重新创建连接以保证连接池的数量一致。

PDO 连接池

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 连接池

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 连接池

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;

 类似资料: