redis優(yōu)點(diǎn)主要是內(nèi)存讀取和本地持久化,但提供的數(shù)據(jù)類型太簡(jiǎn)單,只能字符串和一維key的操作。所以做做簡(jiǎn)單的存儲(chǔ)和并發(fā)檢索還是可以的,但是要想更復(fù)雜的功能,我們就要基于redis做封裝。
那么,如果用workerman來(lái)開(kāi)發(fā)仿造一個(gè)redis,php-frm直接連接worker進(jìn)程中的內(nèi)存變量,兩者都是常駐內(nèi)存,數(shù)據(jù)也都是在內(nèi)存中的,就像Gateway::bindUid一樣的原理,豈不是更爽。
暫且不管redis的其他特性,單就workerman替代redis方案的可能性和效率做比較,我做了個(gè)demo測(cè)試。
下面分別對(duì)workerman和redis做字符串set操作,為了公平,workerman代碼里做了key值不存在就設(shè)置,存在就覆蓋的操作。測(cè)試結(jié)果如下:100萬(wàn)的set操作,workerman只需要7秒,redis需要32秒
下面截圖是redis的rpush和php的array_push對(duì)比,速度秒數(shù)reids。不過(guò)測(cè)試也發(fā)現(xiàn)一些缺點(diǎn),php模擬rpush時(shí)很占用內(nèi)存,lpush無(wú)法實(shí)現(xiàn),主要是php的array_unshift性能不行。
下面是代碼,大家可以自行測(cè)試
web代碼:
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$wm = stream_socket_client('tcp://127.0.0.1:8899');
$time = microtime(true);
$key = 0;
for ($i=0; $i < 10000; $i++)
{
$redis->set('key', ++$key);
}
echo 'redis 1w:'. (microtime(true) - $time) . '<br>';
$time = microtime(true);
for ($i=0; $i < 100000; $i++)
{
$redis->set('key', ++$key);
}
echo 'redis 10w:'. (microtime(true) - $time) . '<br>';
$time = microtime(true);
for ($i=0; $i < 1000000; $i++)
{
$redis->set('key', ++$key);
}
echo 'redis 100w:'. (microtime(true) - $time) . '<br>';
echo 'redis get:'. $redis->get('key') . '<br><br>';
$time = microtime(true);
for ($i=0; $i < 10000; $i++)
{
fwrite($wm, json_encode(['type' => 'set', 'key' => 'key', 'value' => ++$key])."\n");
}
echo 'worker 1w:'. (microtime(true) - $time) . '<br>';
$time = microtime(true);
for ($i=0; $i < 100000; $i++)
{
fwrite($wm, json_encode(['type' => 'set', 'key' => 'key', 'value' => ++$key])."\n");
}
echo 'worker 10w:'. (microtime(true) - $time) . '<br>';
$time = microtime(true);
for ($i=0; $i < 1000000; $i++)
{
fwrite($wm, json_encode(['type' => 'set', 'key' => 'key', 'value' => ++$key])."\n");
}
echo 'worker 100w:'. (microtime(true) - $time) . '<br>';
fwrite($wm, json_encode(['type' => 'get', 'key' => 'key'])."\n");
echo 'worker get:'. fgets($wm, 1024);
workerman代碼:
<?php
use \Workerman\Worker;
// 自動(dòng)加載類
require_once __DIR__ . '/../../vendor/autoload.php';
$worker = new Worker('text://127.0.0.1:8899');
$worker->name = 'workerman';
$worker->count = 1;
$_session = [];
$worker->onMessage = function($connection, $data)
{
global $_session;
$data = json_decode($data);
switch ($data->type) {
case 'get':
$connection->send($_session[$data->key]);
break;
case 'set':
$_session[$data->key] = $data->value;
break;
}
};
// 如果不是在根目錄啟動(dòng),則運(yùn)行runAll方法
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}
array_unshift 慢是因?yàn)槊看握{(diào)用要重建索引。
數(shù)組元素越多越慢。
php 有splqueue https://www.php.net/manual/zh/class.splqueue.php ,專門(mén)做隊(duì)列的,而且比php數(shù)組省內(nèi)存。
按道理比array更快