redis优点主要是内存读取和本地持久化,但提供的数据类型太简单,只能字符串和一维key的操作。所以做做简单的存储和并发检索还是可以的,但是要想更复杂的功能,我们就要基于redis做封装。
那么,如果用workerman来开发仿造一个redis,php-frm直接连接worker进程中的内存变量,两者都是常驻内存,数据也都是在内存中的,就像Gateway::bindUid一样的原理,岂不是更爽。
暂且不管redis的其他特性,单就workerman替代redis方案的可能性和效率做比较,我做了个demo测试。
下面分别对workerman和redis做字符串set操作,为了公平,workerman代码里做了key值不存在就设置,存在就覆盖的操作。测试结果如下:100万的set操作,workerman只需要7秒,redis需要32秒
下面截图是redis的rpush和php的array_push对比,速度秒数reids。不过测试也发现一些缺点,php模拟rpush时很占用内存,lpush无法实现,主要是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 慢是因为每次调用要重建索引。
数组元素越多越慢。
php 有splqueue https://www.php.net/manual/zh/class.splqueue.php ,专门做队列的,而且比php数组省内存。
按道理比array更快
谢谢大神,才发现php一系列牛逼的扩展库