php实现redis的服务端的示例
发布:smiling 来源: PHP粉丝网 添加日期:2018-09-18 09:24:16 浏览: 评论:0
大家都知道redis是用C来实现的,现在我用php来实现一个简单的仅支持SET和GET命令的redis服务端,主要是为了更好的了解redis的服务端和php的网络编程.代码如下:
- /**
- * 多进程阻塞式
- */
- class Xtgxiso_server
- {
- private $socket = false;
- private $process_num = 100;
- public $redis_kv_data = array();
- public $onMessage = null;
- function __construct($host="0.0.0.0",$port=1215)
- {
- $this->socket = stream_socket_server("tcp://".$host.":".$port,$errno, $errstr);
- if (!$this->socket) die($errstr."--".$errno);
- echo "listen $host $port \r\n";
- ini_set("memory_limit", "128M");
- }
- private function parseRESP(&$conn){
- $line = fgets($conn);
- if($line === '' || $line === false)
- {
- return null;
- }
- $type = $line[0];
- $line = mb_substr($line,1,-2);
- switch ( $type ){
- case "*":
- $count = (int) $line;
- $data = array();
- for ($i = 1; $i <= $count; $i++) {
- $data[] = $this->parseRESP($conn);
- }
- return $data;
- case "$":
- if ($line == '-1') {
- return null;
- }
- $length = $line + 2;
- $data = '';
- while ($length > 0) {
- $block = fread($conn, $length);
- if ($length !== strlen($block)) {
- throw new Exception('RECEIVING');
- }
- $data .= $block;
- $length -= mb_strlen($block);
- }
- return mb_substr($data, 0, -2);
- }
- return $line;
- }
- private function start_worker_process(){
- $pid = pcntl_fork();
- switch ($pid) {
- case -1:
- echo "fork error : {$i} \r\n";
- exit;
- case 0:
- while ( 1 ) {
- echo "waiting...\n";
- $conn = stream_socket_accept($this->socket, -1);
- if ( !$conn ){
- continue;
- }
- //"*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$7\r\nmyvalue\r\n"
- while(1){
- $arr = $this->parseRESP($conn);
- if ( is_array($arr) ) {
- if ($this->onMessage) {
- call_user_func($this->onMessage, $conn, $arr);
- }
- }else if ( $arr ){
- if ($this->onMessage) {
- call_user_func($this->onMessage, $conn, $arr);
- }
- }else{
- fclose($conn);
- break;
- }
- }
- }
- default:
- $this->pids[$pid] = $pid;
- break;
- }
- }
- public function run(){
- for($i = 1; $i <= $this->process_num; $i++){
- $this->start_worker_process();
- }
- while(1){
- foreach ($this->pids as $i => $pid) {
- if($pid) {
- $res = pcntl_waitpid($pid, $status,WNOHANG);
- if ( $res == -1 || $res > 0 ){
- $this->start_worker_process();
- unset($this->pids[$pid]);
- }
- }
- }
- sleep(1);
- }
- }
- }
- $server = new Xtgxiso_server();
- $server->onMessage = function($conn,$info) use($server){
- if ( is_array($info) ){
- if ( $info["0"] == "SET" ) {
- $key = $info[1];
- $val = $info[2];
- $server->redis_kv_data[$key] = $val;
- fwrite($conn, "+OK\r\n");
- }else if ( $info["0"] == "GET" ){
- $key = $info[1];
- fwrite($conn, "$".strlen($server->redis_kv_data[$key])."\r\n".$server->redis_kv_data[$key]."\r\n");
- }else{
- fwrite($conn,"+OK\r\n");
- }
- }else{
- fwrite($conn,"+OK\r\n");
- } //phpfensi.com
- };
- $server->run();
通过如下命令来测试PHP实现的性能:
redis-benchmark -h 10.170.233.221 -p 1215 -t set -n 80000 -q
看来还是不错的,大家有兴趣可以再实现其他命令!
Tags: php示例 redis服务端
相关文章
- ·php实现基于PDO的预处理示例(2018-08-31)
推荐文章
热门文章
最新评论文章
- 写给考虑创业的年轻程序员(10)
- PHP新手上路(一)(7)
- 惹恼程序员的十件事(5)
- PHP邮件发送例子,已测试成功(5)
- 致初学者:PHP比ASP优秀的七个理由(4)
- PHP会被淘汰吗?(4)
- PHP新手上路(四)(4)
- 如何去学习PHP?(2)
- 简单入门级php分页代码(2)
- php中邮箱email 电话等格式的验证(2)