redis命令傳送格式:
*<引數數量> CRLF
$<引數 1 的位元組數量> CRLF
<引數 1 的資料> CRLF
…
$<引數 N 的位元組數量> CRLF
<引數 N 的資料> CRLF
其中CRLF表示 rn
舉個例子:set name wuzhc
格式化輸出:
*3
$3
set
$4
name
$5
wuzhc
說明:
-
*開頭,表示有多少個引數,例如*3表示有3個引數(set, name, wuzhc)
-
$開頭,表示引數的位元組長度,例如$3表示set有3個位元組,$4表示name有4個位元組
-
每行rn結尾
通訊協議為:
*3
$3
set
$4
name
$5
wuzhc
Redis 回覆
-
狀態回覆(status reply)的第一個位元組是 “+”,例如+OK
-
錯誤回覆(error reply)的第一個位元組是 “-“,例如-No such key
-
整數回覆(integer reply)的第一個位元組是 “:”,例如:1
-
批量回復(bulk reply)的第一個位元組是 “$”,例如 $5
wuzhc -
多條批量回復(multi bulk reply)的第一個位元組是 “*”,例如*2
$5
wuzhc
$3r
age
PHP 實現Redis客戶端
<?php
/**
* Created by PhpStorm.
* User: wuzhc2016@163.com
* Date: 2017年09月12日
* Time: 9:08
*/
class Client
{
private $_socket = null;
public function __construct($ip, $port)
{
$this->_socket = stream_socket_client(
"tcp://{$ip}:{$port}",
$errno,
$errstr,
1,
STREAM_CLIENT_CONNECT
);
if (!$this->_socket) {
exit($errstr);
}
}
/**
* 執行redis命令
* @param $command
* @return array|bool|string
*/
public function exec($command)
{
// 拼裝傳送命令格式
$command = $this->_execCommand($command);
// 傳送命令到redis
fwrite($this->_socket, $command);
// 解析redis響應內容
return $this->_parseResponse();
}
/**
* 將字元改為redis通訊協議格式
* 例如mget name age 格式化為 *3
$4
mget
$4
name
$3
age
* @param $command
* @return bool|string
*/
private function _execCommand($command)
{
$line = ``;
$crlf = "
";
$params = explode(` `, $command);
if (empty($params)) {
return $line;
}
// 引數個數
$line .= `*` . count($params) . $crlf;
// 各個引數拼裝
foreach ((array)$params as $param) {
$line .= `$` . mb_strlen($param, `8bit`) . $crlf;
$line .= $param . $crlf;
}
return $line;
}
/**
* 解析redis回覆
* @return array|bool|string
*/
private function _parseResponse()
{
$line = fgets($this->_socket);
$type = $line[0];
$msg = mb_substr($line, 1, -2, `8bit`);
switch ($type) {
// 狀態回覆
case `+`:
if ($msg == `OK` || $msg == `PONG`) {
return true;
} else {
return $msg;
}
// 錯誤回覆
case `-`:
exit($msg);
// 整數回覆
case `:`:
return $msg;
// 批量回復
case `$`: // $後面跟資料位元組數(長度)
$line = fread($this->_socket, (int)$msg + 2); // 資料位元組數 + (
)兩個位元組
return mb_substr($line, 0, -2, `8bit`); // 去除最後兩個位元組
// 多條批量回復
case `*`: // *表示後面有多少個引數
$data = [];
for ($i = 0; $i < $msg; $i++) {
$data[] = $this->_parseResponse();
}
return $data;
}
}
}
// demo
$client = new Client(`127.0.0.1`, 6379);
$client->exec(`set name wuzhc`);
$res = $client->exec(`get name`);
var_dump($res);