We all know that Redis is implemented in C, now I use PHP to implement a simple only support set and get command of the Redis server, mainly to better understand the Redis server and PHP network programming.
The code is as follows:
<?php
/**
* Multi-process blocking
*/
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) {
&nbs p; $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");
}
};
$server->run ();
Test the performance of your PHP implementation with the following command:
Redis-benchmark-h 10.170.233.221-p 1215-t set-n 80000-q
It seems to be good, we are interested to be able to implement other orders!