RESP プロトコル#
Redis は CS アーキテクチャのソフトウェアで、通信は一般的に二段階に分かれます(パイプラインや PubSub を除く)
- クライアント client がサーバー server にコマンドを送信します
- サーバーがコマンドを解析し実行し、応答結果をクライアントに返します
したがって、クライアントがコマンドを送信する形式、サーバーが応答結果を返す形式には規格が必要であり、この規格が通信プロトコルです
RESP:redis シリアライゼーションプロトコル
RESP2 プロトコルを学び、2.0 バージョンで導入され、6.0 で RESP3 にアップグレードされましたが、変更が大きいため、依然として RESP2 プロトコルがデフォルトで使用されています
RESP プロトコルデータ型#
単一行の文字列、エラー、データはすべてバイナリ不安全であり、内容に \r\n が挿入されると誤解される可能性があります
配列タイプは実際には AOF ファイルに似ています
Redis クライアントのシミュレーション#
実行しても reader が情報を受け取れない?
public class Main {
static Socket s;
static PrintWriter out;
static BufferedReader in;
public static void main(String[] args) {
try {
// 1. 接続を確立
String host = "redis.orb.local";
int port = 6379;
s = new Socket(host, port);
// 2. 入力、出力ストリームを取得
out = new PrintWriter(
new OutputStreamWriter(s.getOutputStream(), StandardCharsets.UTF_8));
in = new BufferedReader(new InputStreamReader(s.getInputStream()));
// 3. リクエストを送信し解析
// 認証を取得 auth TheBestWorkLoanapp1 sendRequest("auth", "TheBestWorkLoanapp1");
Object obj = handleResponse();
System.out.println(obj.toString());
// キーと値のペアを設定 set name Chanler sendRequest("set", "name", "Chanler");
obj = handleResponse();
System.out.println(obj.toString());
// キーと値のペアを取得 get name sendRequest("get", "name");
obj = handleResponse();
System.out.println(obj.toString());
} catch (IOException e) {
e.printStackTrace();
} finally {
// 5. 接続を解放
try {
if (s != null) {s.close();}
} catch (IOException e) {
e.printStackTrace();
}
try {
if (out != null) {out.close();}
} catch (Exception e) {
e.printStackTrace();
}
try {
if (in != null) {in.close();}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private static Object handleResponse() throws IOException {
// 最初のバイトを読み取りデータタイプを判断
int prefix = in.read();
switch (prefix) {
case '+':
return in.readLine();
case '-':
throw new RuntimeException(in.readLine());
case ':':
return Long.parseLong(in.readLine());
case '$':
int len = Integer.parseInt(in.readLine());
if (len == -1) {
return null;
}
if (len == 0) {
return "";
}
// ここでは len バイトを読み取る必要がありますが、すでに文字ストリームに変換されているため、特殊文字は存在しないと仮定します
return in.readLine();
case '*':
return readBulkString();
default:
throw new RuntimeException("無効なプレフィックス");
}
}
private static Object readBulkString() throws IOException {
int len = Integer.parseInt(in.readLine());
if (len == 0) {
return null;
}
List<Object> list = new ArrayList<>();
for (int i=0; i<len; i++) {
list.add(handleResponse());
}
return list;
}
// set name Chanler を送信
private static void sendRequest(String ... args) {
// \r\n は改行文字で、ここでは println を使用して直接付加されています
out.println("*" + args.length);
for (String arg : args) {
out.println("$" + arg.getBytes(StandardCharsets.UTF_8).length);
out.println(arg);
}
out.flush();
}
}
この記事は Mix Space によって xLog に同期更新されました
元のリンクは https://blog.0xling.cyou/posts/redis/redis-5