パフォーマンスのボトルネックは、多くの場合、データベースへのアクセスです。
この問題はさまざまな方法で解決できます。
キャッシュを使用するとパフォーマンスの問題は解決しますが、プログラムのアーキテクチャが大幅に複雑になります。 グラフデータベースは、このタスクに最適なアルゴリズムのために状況から抜け出します。 別のタイプのソリューションは、高速メディアを使用して高性能を実現するストレージです。
最近、データをメモリに完全に保存する多くのNoSQLストレージが登場しました。 しかし、メモリは依然として高価であり、そのサイズは限られています。 シャーディングによるメモリの増加は再びコストになります。
論理的な解決策は、SSDドライブを使用することです。 それらは比較的低コストであると同時に非常に短い応答時間です。
残念ながら、SSDは数年前から存在しているにもかかわらず、多くのデータベースがSSDと連携するように最適化されていません。 SSDドライブをデータベースのメディアとして使用する場合の主な問題は、同じブロックの複数の書き換えです。 T.N. 「凍結。」
RocksDBは、柔軟で生産的な組み込みNoSQLリポジトリです。 SSDドライブなどの高速メディアで使用するように設計されています。 Facebookで作成されており、GoogleのLevelDBに基づいています。
詳細を説明しない場合、LevelDBとの主な違いは、フラッシュドライブを使用するために最適化されたエンジンです。 大量のデータを扱うための最適化。 優れた柔軟性と拡張性、そしてその結果、LevelDBにはないおいしいパンがたくさんあります。
先ほど言ったように、RocksDBは組み込みソリューションです。 そして、それを使用するには、アプリケーションに組み込むか、サーバーにラップする必要があります。 Webアプリケーションで使用するために必要でした。 また、特定の理由により、1つのプロセス(スレッドではない)のみがアクセスできるため、サーバーが必要でした。
私は約1年前にRocksDBを知り、誰かがそのためのサーバーを書き始めるのを辛抱強く待っていました。 この間に出てきたものはすべて、私には完全には合いませんでした。 そこで、RocksDBに独自のサーバーラッパーを書くことにしました。
RocksServerは、 RocksDBへのアクセスを提供するシングルスレッドHTTPサーバーです。
サーバーはC ++で書かれています。 http層を実装するために、 Libeventが使用されました。
LibeventとRocksDB以外に、コードには他の依存関係は含まれていません。
RocksDBには非常に豊富な機能があります。 現時点で必要な基本機能のみを実装しました。 もちろん、将来的には、可能な限り、サーバーの機能を拡張する予定です。
私は大規模なベンチマークを実施しませんでしたが、予備的なパフォーマンス測定はかなりまともな結果を示しました。
現在サポートされている操作:
ゲット | キーで1つの値を取得します |
マルチゲット | キーのセットから複数の値をアトミックに取得する |
セット | キーで1つの値を設定します |
マルチセット | キーセットに複数の値をアトミックに設定する |
削除キー | データベースからキーを削除します |
マルチ削除 | 複数のキーをアトミックに削除します |
チェックキーが存在します | データベース内のキーのクイックチェック(値をすばやく取得する機能を備えています) |
増分 | 指定された値による原子の増加/減少 |
必要に応じて、操作のリストを簡単に拡張できます。 これを行うには、インターフェイスを実装するだけです。
struct RequestBase { virtual ~RequestBase() {} /** * Runs request listener * @param event request object * @param event buffer object */ virtual void run(const EvRequest &, const EvBuffer &) = 0; };
たとえば、データスキーマによっては、アトミックな挿入/更新キーセットの実装が必要になる場合があります。
ハンドラーをサーバーに接続することも難しくありません。 これは1行で行われます。
server.onRequest("/castom_handler", new Requestastom());
コンパイル/インストール
前述したように、 RocksServerには2つの依存関係があります。RocksDB自体と、Libeventの形式のhttpレイヤーです。 これらは個別にインストールすることも、インストールせずにコンパイルに限定することもできます(静的リンクのため)。 個人的には、後者の方法は、次の方法でRocksServerを実行できるため、望ましい方法です。 必要なサブ依存関係をすべて備えていない古いサーバー上。
だから。
リポジトリのクローンを作成します。
git clone --recursive git@github.com:valmat/RocksServer.git cd RocksServer
または
git clone git@github.com:valmat/RocksServer.git cd RocksServer git submodule update
クローン作成後、LibeventとRocksDBはdepsディレクトリに配置されます。
次に、依存関係をコンパイルします。
./deps/make.sh
このステップの後、必要に応じて、テストを実行するか、LibeventとRocksDBをシステムにインストールできます。
そして、すぐにRocksServerをコンパイルすることができます
cd src make
コンパイラは
C++11
標準をサポートする必要があります
コンパイル後、最初に構成ファイルを編集してRocksServerを起動できます。
./RocksServer.bin config.ini
そして、あなたはそれをインストールすることができます。
make install
後者の場合、開始/再起動/停止するには、
init.d
スクリプトを使用する必要があります。
/etc/init.d/rocksserver start
ほとんどの場合、自分用にサーバーを構成する必要があります。 利用可能な設定はすべて
config.ini
ファイルに記録されます。
テストのために、単純なドライバーをphpに入れました( そう、書き換える必要があることは知っています )か、 プロトコルを直接使用できます 。
Curl
や
Wget
などのプログラムの使用を含みます。
プロトコルは非常に簡単です。 RPCとHTTPを選択する場合、交換プロトコルのシンプルさが決定的なポイントの1つでした。
現時点では、機能はそれほど豊富ではありませんが、RocksServerは完全に機能します。 いずれにせよ、現在取り組んでいるプロジェクトの本番環境で使用する予定です(このために書きました)。
私に加えて、ValgrindとCppCheckはコードレビューを実施しませんでした。 したがって、何かがうまくいかないかもしれないという恐れは非常に普通です。
この場合、RocksServerをログに記録する可能性があり、人間が読める形式でバックアップを作成する機能があります。
構成ファイルのログを有効にするには、ログファイルを指定するだけです。
; Error log file name ; default value: /var/log/rocksserver/error.log ; ; error_log =
ログの詳細レベルを示します。
; Error level ; Possible values: debug | msg | warn | error | fatal | none ; default value: none ; ; log_level =
バックアップの場合、バックアップを追加するディレクトリを指定する必要があります。
; RocksDB backup path ; The directory in which a backup will be stored ; default value: /var/rocksserver/backup ; ; backup_path =
127.0.0.1:5577/backup
への
POST
リクエストを実行します
バックアップからデータベースを復元するには、次のコマンドを使用します
restore -f/path/to/backup -t/path/to/db
データベースを人間が読める形式に変換するには:
human_readable -f/path/to/db -t/path/to/restore_file
私は自分で次のバックアップスキームを計画しています。
wget "http://localhost:5577/backup" --post-data="" -O - restore -f/path/to/backup -t/path/to/db_on_hdd human_readable -f/path/to/db_on_hdd -t/path/to/restore_file
建設的な批判に感謝します。
インストールと設定を支援します。
もちろん、プルリクエストも歓迎します。
ご清聴ありがとうございました。