RESPの課題と現状についてskonno2022-07-31Redisは、インメモリのキーバリューストアとして2009年に登場し、現在でも活発に機能拡張が継続されているプロダクトです。3[2]として刷新され、大幅な機能拡張が実現されました。本家のRedis自信も進化を続けていますが、最近ではRedisと互換性のあるRESPプロトコルに対応した大規模なRedis互換プロダクトが相次いで登場しています[4][5]。Protocol)[1]の通信プロトコルを中心に、実装上の利点などや課題を踏まえて解説してみます。Protocol)の概要RESPは「実装が簡単」「解析が高速」「ヒューマンリーダブル」を設計思想[1]とする通信プロトコル仕様です。通信パケットの起点となる共通ヘッダは、メッセージ種別を示す1バイトのみで、CRLFをメッセージの終端とする、非常に単純な仕様です。(省略化)例えば、Redisコマンドが正常に実行されたことを示す応答は、文字列のメッセージ種別を示す「+」から開始され、成功を示すメッセージ文字列である「OK」がCRLFで終端されたものが送信されます。+OK\r\nRESPのデータ型は、文字列表現が基本です。RESPでは、数値においても文字列として表現されているため、「ヒューマンリーダブル」の設計思想[1]通りに、簡単に目視できるデバッグしやすい通信プロトコルです。RESPの課題RESPは、本家のRedisや近年の相次いで登場している大規模なRedis互換プロダクトの基盤となる通信プロトコルです。3設計の動機となった課題[3]と合わせて説明します。2仕様[1]では、以下の5種類のデータ型の規定しかありません。そのため、任意のプリミティブ型やコレクション型を表現するには、実装上、暗黙的な変換や規定が必要となります。浮動小数点を表現するには文字列型との、連想配列(マップ)型を表現するには配列型との、暗黙的は変換の規定が必要となります。"World"以下のRESPメッセージに変換されたものが、クライアントからサーバーへ送信されています。*5\r\n$4\r\mset\r\n$4\r\nkey1\r\n$7\r\n"HELLO"\r\n$4\r\nkey2\r\n$7\r\n"World"\r\nMSETコマンドは、連想配列(マップ)型をキー値、バリュー値が交互に現れる配列として変換され、クライアントからサーバーへ送信されています。3仕様[2]では、以下に示す新しいプリミティブ型やコレクション型が仕様として規定されています。2の上位互換性を意識した設計となっています。2のMSETの事例でで暗黙的に配列データ型に変換されたものと同一の表現です。2で用いられていた配列型によるMap型の書式が踏襲されています。2仕様[1]の暗黙的な仕様を明確化した側面があります。2仕様[1]の欠点も引き継がれています。2仕様[1]には、RESP仕様の実装の簡単さと、高速性を示す事例として、以下のC言語によるパース処理の実装例が掲載されています。0;}上記事例は、文字列のメッセージ種別を示す「$」から開始された10進数文字列メッセージを、整数に変換する処理を示しています。パース開始時にはメッセージ部のバイト数が不明なため、1バイトずつ取得して解釈せざる負えず、実行効率や速度面では効率的とは言えません。実際に、RESPをベースとするRedisサーバーのコマンドは、パース開始時にメッセージ部のバイト数や個数が認識できる、バルク文字列($)や配列(*)を主体として実装されています。value以下のRESPメッセージに変換されたものが、クライアントからサーバーへ送信されています。*3\r\n$3\r\nset\r\n$3\r\nkey\r\n$5\r\nvalue\r\n上記の、C言語での実装例にあった文字列ライクなCRLRを終端とする通常文字列($)と異なり、バルク文字列($)はPascal文字列ライクに最初に文字列バイト数が把握できるため一括しての読み込みが可能です。バルク文字列($)や配列(*)メッセージ共に、最初の個数を示す数値はCRLFを終端する不定型な文字列表現です。2仕様[1]には「バイナリプロトコルと同等の性能」との主張もありますが、数値を例えば4バイトで表現するような、純粋なバイナリプロトコルと比較すると、非効率な面は残ります。最後に近年、Redisと互換性のあるRESPプロトコルに対応した大規模なRedis互換プロダクトが相次いで登場しています[4][5]。今回の記事も、その登場の背景を調査しながら、Redis互換サーバーをgo-redis[6]として試験的に実装して気がついた点を、いったん整理してまとめて見ました。調査や実装を進める中で気がついた点があれば、あらためて整理してみようと思います。Redis互換で25倍高速とする「Dragonfly」が登場。