redis優(yōu)點主要是內(nèi)存讀取和本地持久化,但提供的數(shù)據(jù)類型太簡單,只能字符串和一維key的操作。所以做做簡單的存儲和并發(fā)檢索還是可以的,但是要想更復(fù)雜的功能,我們就要基于redis做封裝。
那么,如果用workerman來開發(fā)仿造一個redis,php-frm直接連接worker進程中的內(nèi)存變量,兩者都是常駐內(nèi)存,數(shù)據(jù)也都是在內(nèi)存中的,就像Gateway::bindUid一樣的原理,豈不是更爽。
暫且不管redis的其他特性,單就workerman替代redis方案的可能性和效率做比較,我做了個demo測試。
下面分別對workerman和redis做字符串set操作,為了公平,workerman代碼里做了key值不存在就設(shè)置,存在就覆蓋的操作。測試結(jié)果如下:100萬的set操作,workerman只需要7秒,redis需要32秒
下面截圖是redis的rpush和php的array_push對比,速度秒數(shù)reids。不過測試也發(fā)現(xiàn)一些缺點,php模擬rpush時很占用內(nèi)存,lpush無法實現(xiàn),主要是php的array_unshift性能不行。
下面是代碼,大家可以自行測試
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;
// 自動加載類
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;
}
};
// 如果不是在根目錄啟動,則運行runAll方法
if(!defined('GLOBAL_START'))
{
Worker::runAll();
}
array_unshift 慢是因為每次調(diào)用要重建索引。
數(shù)組元素越多越慢。
php 有splqueue https://www.php.net/manual/zh/class.splqueue.php ,專門做隊列的,而且比php數(shù)組省內(nèi)存。
按道理比array更快