sonic - 🦔 高速、軽量、スキーマレスの検索バックエンド。数MBのRAM上で動作するElasticsearchの代替手段。

(🦔 Fast, lightweight & schema-less search backend. An alternative to Elasticsearch that runs on a few MBs of RAM.)

Created at: 2019-02-26 21:16:58
Language: Rust
License: MPL-2.0

ソニック

テストとビルド ビルドとリリース 依存関係の状態 私にコーヒーを買って

ソニックは、高速で軽量でスキーマレスの検索バックエンドです。検索テキストと識別子タプルを取り込み、マイクロ秒の時間で照会できます。

ソニックは、一部のユースケースでは、Elasticsearchなどの超重くてフル機能の検索バックエンドの簡単な代替手段として使用できます。自然言語検索クエリを正規化し、検索クエリを自動補完し、クエリに最も関連性の高い結果を提供することができます。Sonic は、ドキュメント インデックスではなく識別子インデックスです。照会されると、外部データベース内の一致した文書を参照するために使用できる ID が返されます。

Sonicを設計する際には、パフォーマンスとコードのクリーンさに強い注意が払われています。クラッシュフリー、超高速を目指し、サーバーリソースに最小限の負担をかけます(私たちの測定では、ソニックは負荷がかかっているときにμs範囲の検索クエリに応答し、〜30MBのRAMを消費し、CPUフットプリントが低いことが示されています。私たちのベンチマークを参照してください)。

Rustバージョンでテスト済み: rustc 1.62.0 (a8314ef7d 2022-06-27)

🇫🇷フランスのナントで製造。

📰ソニックのプロジェクトは、私の個人的な日記の投稿で最初に発表されました。

ソニック

«ソニック»はソニックプロジェクトのマスコットです。サイケデリックなヒップスターのハリネズミのように見えるように描きました。

誰がそれを使用しますか?

シャッキシャッキ スクランピー

👋あなたはソニックを使用していて、そこにリストされたいですか?私に連絡してください。

デモ

ソニックは、クリスププラットフォーム上のすべてのクリスプ検索製品に統合されています。これは、$ 5 / mth 1-vCPU SSDクラウドサーバー上の5億個のオブジェクトのインデックスを作成するために使用されます(2019年現在)。鮮明なユーザーは、メッセージ、会話、連絡先、ヘルプデスクの記事などを検索するためにそれを使用します。

Crispヘルプデスクでソニックをライブでテストし、ソニックの検索結果のスピードと関連性を知ることができます。また、そこから検索候補をテストすることもできます:単語に少なくとも2文字の入力を開始し、完全な単語を提案します(Tabキーを押すと候補が展開されます)。検索と提案の両方がソニックによって供給されています。

クリスプヘルプデスク検索のデモ

最高の状態でヘルプデスクの記事でソニックファジー検索。任意の単語や用語のグループを検索し、即座に結果を取得します。

顔立ち

  • 検索語はコレクションに格納され、バケットに編成されます。プラットフォーム上で 1 つのバケットを使用するか、個別のインデックスで検索する必要がある場合は、ユーザーごとに 1 つのバケットを使用できます。
  • 検索結果にはオブジェクト識別子が返されます。この識別子は、検索結果を充実させる必要がある場合に外部データベースから解決できます。これにより、ソニックは識別子の結果を指す単純な単語インデックスになります。ソニックはインデックスに直接テキストデータを格納しませんが、オートコンプリートやタイプミスの修正のための単語グラフを保持しています。
  • 検索クエリの誤字脱字は、検索クエリ内の特定の単語に対して十分な完全一致結果がない場合に修正され、Sonic はその単語の修正を試み、代替単語に対して試行します。検索時に間違いを犯すことは許されています。
  • インデックス内のアイテムを挿入および削除します。インデックス変更操作は軽く、サーバーの実行中にサーバーにコミットできます。バックグラウンド タスカーは、プッシュまたはポップしたエントリがすぐに検索に使用できるように、インデックスを統合するジョブを処理します。
  • 提案操作を介してリアルタイムで任意の単語をオートコンプリートします。これは、エンドユーザーの検索インターフェイスできびきびとした単語の提案機能を構築するのに役立ちます。
  • 世界で最も話されている80以上の言語での完全なUnicode互換性。ソニックは、任意のテキストから役に立たないストップワードを削除します(例えば、英語の 'the')、テキスト言語を推測した後。これにより、検索または取り込まれたテキストがインデックスにヒットする前にクリーンになります。言語を参照してください。
  • シンプルなプロトコル(Sonic Channel)を使用すると、インデックスの検索、データ取り込みの管理(インデックスのプッシュ、インデックスからのポップ、コレクションのフラッシュ、バケットのフラッシュなど)、管理アクションを実行できます。ソニックチャンネルは、リソースが軽量で、統合が簡単であるように設計されています。プロトコル仕様を読み取ります。
  • 使いやすいライブラリ, あなたのアプリからソニックに接続できます;ライブラリを参照してください。

それを使用する方法?

取り付け

ソニックはRustに組み込まれています。インストールするには、ソース コードを使用するか、 からソース コードを取得します。

cargo install
master

👉ソースからインストール:

Gitからソースコードをプルした場合は、次のようにしてビルドできます。

cargo

cargo build --release

ビルドされたバイナリはディレクトリにあります。

./target/release

build-essential、clang、libclang-dev、libc6-dev、g++、llvm-dev をインストールして、必要な RocksDB 依存関係をコンパイルできるようにします。

👉貨物からインストール:

ソニックは次のように直接インストールできます。

cargo install

cargo install sonic-server

Cratesバイナリをソースにするようが正しく設定されていることを確認し、コマンドを使用してSonic を実行します。

$PATH
sonic

build-essential、clang、libclang-dev、libc6-dev、g++、llvm-dev をインストールして、必要な RocksDB 依存関係をコンパイルできるようにします。

👉ドッカーハブからインストールする:

Docker経由でソニックを実行すると便利かもしれません。Docker Hub で事前に構築された Sonic イメージは、valeriansaliou/sonic として見つけることができます。

まず、画像をプルします。

valeriansaliou/sonic

docker pull valeriansaliou/sonic:v1.4.0

次に、構成ファイルをシードして実行します (構成ファイルへのパスに置き換えます)。

/path/to/your/sonic/config.cfg

docker run -p 1491:1491 -v /path/to/your/sonic/config.cfg:/etc/sonic.cfg -v /path/to/your/sonic/store/:/var/lib/sonic/store/ valeriansaliou/sonic:v1.4.0

構成ファイルで、次のことを確認します。

  • channel.inet
    に設定されています (これにより、コンテナの外部からソニックに到達できます)
    0.0.0.0:1491
  • store.kv.path
    に設定されています (これにより、Sonic が外部 KV ストアディレクトリに到達できます)。
    /var/lib/sonic/store/kv/
  • store.fst.path
    に設定されています (これにより、Sonic が外部 FST ストアディレクトリに到達できます)
    /var/lib/sonic/store/fst/

ソニックは から到達可能です。

tcp://localhost:1491

👉別のソースからインストールする(非公式):

その他のインストールソースが利用可能です:

これらのソースは非公式であり、ソニックのプロジェクト所有者によって所有または維持されていないことに注意してください。これらのソースで利用可能な最新のソニックバージョンは、ソニックプロジェクトを通じて利用可能な最新バージョンと比較して、古くなっている可能性があります。

構成

サンプルの config.cfg 構成ファイルを使用して、独自の環境に合わせて調整します。

設定を微調整したい場合は、詳細な設定ドキュメントを参照してください。

ランソニック

ソニックは次のように実行できます。

./sonic -c /path/to/config.cfg

検索の実行とオブジェクトの管理

検索とオブジェクト管理(つまり、データ取り込み)はどちらも、ソニックチャンネルプロトコルを介してのみ処理されます。ソニックでは物事をシンプルに保ちたいので(Redisがそれを行う方法と同様に)、ソニックはHTTPエンドポイントなどを提供していません。ソニックチャンネル経由で接続することは、ソニック検索データベースと対話する必要がある場合の方法です。

ソニックは公式ライブラリを配布しており、ソニックをアプリに簡単に統合できます。下のライブラリをクリックすると、ライブラリ統合のドキュメントとコードが表示されます。

生のソニックチャンネルTCPベースのプロトコルの詳細をお探しの場合は、詳細なプロトコルのドキュメントを読むことができます。独自のソニックチャンネルライブラリをコーディングする場合に便利です。

📦ソニックチャンネルライブラリ

1️⃣公式図書館

Sonic は、プログラミング言語用の公式の Sonic 統合ライブラリを配布しています (公式とは、これらのライブラリがコアメンテナによってレビューおよび検証されていることを意味します)。

2️⃣コミュニティライブラリ

コミュニティが提供するソニック統合のリストを以下に示します(彼らに感謝します!

ℹ️プログラミング言語のライブラリが見つかりませんか?あなた自身のものを構築し、ここで参照してください!(私に連絡してください)

どのテキスト言語がサポートされていますか?

ソニックは、その字句解析システムで言語の広い範囲をサポートしています。言語がこのリストにない場合でも、この言語を検索インデックスにプッシュすることはできますが、ストップワードは回避されず、検索結果の品質が低下する可能性があります。

字句解析システムでサポートされている言語は次のとおりです。

  • 🇿🇦アフリカーンス語
  • 🇸🇦アラビア語
  • 🇦🇲アルメニア語
  • 🇦🇿アゼルバイジャン語
  • 🇧🇩ベンガル語
  • 🇧🇬ブルガリア語
  • 🇲🇲ビルマ語
  • 🏳カタロニア語
  • 🇨🇳中国語 (簡体字)
  • 🇹🇼中国語 (繁体字)
  • 🇭🇷クロアチア語
  • 🇨🇿チェコ語
  • 🇩🇰デンマーク語
  • 🇳🇱オランダ語
  • 🇬🇧英語
  • 🏳エスペラント
  • 🇪🇪エストニア語
  • 🇫🇮フィンランド語
  • 🇫🇷フランス語
  • 🇬🇪グルジア語
  • 🇩🇪ドイツ語
  • 🇬🇷ギリシャ語
  • 🇮🇳グジャラート語
  • 🇮🇱ヘブライ語
  • 🇮🇳ヒンディー語
  • 🇭🇺ハンガリー語
  • 🇮🇩インドネシア語
  • 🇮🇹イタリア語
  • 🇯🇵日本語
  • 🇮🇳カナラ語
  • 🇰🇭クメール語
  • 🇰🇷韓国語
  • 🏳ラテン語
  • 🇱🇻ラトビア語
  • 🇱🇹リトアニア語
  • 🇮🇳マラーティー語
  • 🇳🇵ネパール語
  • 🇮🇷ペルシャ語
  • 🇵🇱ポーランド語
  • 🇵🇹ポルトガル語
  • 🇮🇳パンジャブ語
  • 🇷🇺ロシア語
  • 🇸🇰スロバキア語
  • 🇸🇮スロベニア語
  • 🇪🇸スペイン語
  • 🇸🇪スウェーデン語
  • 🇵🇭タガログ語
  • 🇮🇳タミール語
  • 🇹🇭タイ語
  • 🇹🇷トルコ語
  • 🇺🇦ウクライナ語
  • 🇵🇰ウルドゥ語
  • 🇻🇳ベトナム語
  • 🇮🇱イディッシュ語
  • 🇿🇦ズールー語

どのくらい速くて軽量ですか?

ソニックは最初からクリスプのために作られました。Crisp が成長し、ますます多くの検索データをフルテキスト検索 SQL データベースにインデックス付けするにつれて、適切な検索バックエンド システムに切り替える時が来たと判断しました。Elasticsearch(ELS)などを検討したところ、これらはフル機能のヘビー級システムであり、Crispのフリーミアムベースのコスト構造ではうまく拡張できないことがわかりました。

最後に、リソースに対してシンプルで軽量なように設計された独自の検索バックエンドを構築することに決めました。

関数レベルのベンチマークは、次のコマンドで実行できます。

cargo bench --features benchmark

👩‍🔬ベンチマーク#1

➡️シナリオ

We performed an extract of all messages from the Crisp team used for Crisp own customer support.

We want to import all those messages into a clean Sonic instance, and then perform searches on the index we built. We will measure the time that Sonic spent executing each operation (ie. each and commands over Sonic Channel), and group results per 1,000 operations (this outputs a mean time per 1,000 operations).

PUSH
QUERY

➡️ Context

Our benchmark is ran on the following computer:

  • Device: MacBook Pro (Retina, 15-inch, Mid 2014)
  • OS: MacOS 10.14.3
  • Disk: 512GB SSD (formatted under the AFS file system)
  • CPU: 2.5 GHz Intel Core i7
  • RAM: 16 GB 1600 MHz DDR3

Sonic is compiled as following:

  • Sonic version: 1.0.1
  • Rustc version:
    rustc 1.35.0-nightly (719b0d984 2019-03-13)
  • Compiler flags: profile ( with
    release
    -03
    lto
    )

Our dataset is as such:

  • Number of objects: ~1,000,000 messages
  • Total size: ~100MB of raw message text (this does not account for identifiers and other metas)

➡️ Scripts

The scripts we used to perform the benchmark are:

  1. PUSH script: sonic-benchmark_batch-push.js
  2. QUERY script: sonic-benchmark_batch-query.js

⏬ Results

Our findings:

  • We imported ~1,000,000 messages of dynamic length (some very long, eg. emails);
  • Once imported, the search index weights 20MB (KV) + 1.4MB (FST) on disk;
  • CPU usage during import averaged 75% of a single CPU core;
  • RAM usage for the Sonic process peaked at 28MB during our benchmark;
  • We used a single Sonic Channel TCP connection, which limits the import to a single thread (we could have load-balanced this across as many Sonic Channel connections as there are CPUs);
  • We get an import RPS approaching 4,000 operations per second (per thread);
  • We get a search query RPS approaching 1,000 operations per second (per thread);
  • On the hyper-threaded 4-cores CPU used, we could have parallelized operations to 8 virtual cores, thus theoretically increasing the import RPS to 32,000 operations / second, while the search query RPS would be increased to 8,000 operations / second (we may be SSD-bound at some point though);

Compared results per operation (on a single object):

We took a sample of 8 results from our batched operations, which produced a total of 1,000 results (1,000,000 items, with 1,000 items batched per measurement report).

This is not very scientific, but it should give you a clear idea of Sonic performances.

Time spent per operation:

Operation Average Best Worst
PUSH 275μs 190μs 363μs
QUERY 880μs 852μs 1ms

Batch PUSH results as seen from our terminal (from initial index of: 0 objects):

Batch PUSH benchmark

Batch QUERY results as seen from our terminal (on index of: 1,000,000 objects):

Batch QUERY benchmark

Limitations

  • インデックス付きデータ制限: Sonic は、コレクションごとに数千の検索バケットに分割された大規模な検索インデックス用に設計されています。IID (すなわち、内部ID)は、32ビット数としてインデックスに格納され、理論的には最大42億個のオブジェクトをインデックス化することができます(すなわち、OID) バケットあたり。ストレージが30%から40%節約され、大規模なデータベースでのトレードオフが正当化されます(ソニックが64ビットIIDを使用するのとは対照的に)。また、ソニックは、特定の単語のN個の最後にプッシュされた結果をスライディングウィンドウの方法でのみ保持します(スライディングウィンドウの幅は設定できます)。
  • 検索クエリの制限: Sonic Natural Language Processing System (NLP) は、ストレージのコンパクトさの理由から、文レベルでは機能しません (時間と空間の複雑さを軽減するために、FST グラフは浅く保ちます)。単語レベルで動作し、単語ごとに検索することができ、文中の次の単語を予測することはできませんが、ユーザー入力に基づいて単語を予測できます。
  • リアルタイム制限:単語がバケットグラフからプッシュまたはポップされるたびに、FSTを再構築する必要があります。これは非常に重いので、ソニックバッチはサイクルを再構築します。新しい単語をインデックスにプッシュしたばかりで、コマンドにまだ表示されない場合は、次の再構築サイクルが始まるのを待つか、チャネルで強制的に実行します。
    SUGGEST
    TRIGGER consolidate
    control
  • 相互運用性の制限: ソニック チャネル プロトコルは、ソニック検索インデックスに対して検索エントリを読み書きする唯一の方法です。ソニックはHTTP APIを公開していません。ソニックチャンネルは、パフォーマンスと最小限のネットワークフットプリントを念頭に置いて設計されています。サポートされていないプログラミング言語から Sonic にアクセスする必要がある場合は、問題を開くか、参照ノード - ソニック - チャネルの実装を見て、ターゲットプログラミング言語でビルドすることができます。
  • ハードウェアの制限: Sonic はファイルシステム上で直接検索を実行します。すなわち。RAMのインデックスに収まりません。検索クエリはディスク上で多くのランダムアクセスをもたらすため、古い学校のHDDでは非常に遅く、新しいSSDでは超高速になります。ソニックデータベースは、SSDでバックアップされたファイルシステムにのみ保存してください。

🔥脆弱性の報告

Sonicに脆弱性が見つかった場合は、暗号化された電子メールを@valeriansaliouに送信して、valerian@valeriansaliou.name に直接報告してください。公開されている GitHub の問題の脆弱性は、パッチが適用されていない Sonic インスタンスを実行している運用サーバーを標的にするために悪意のあるユーザーによって悪用される可能性があるため、報告しないでください。

⚠️GPG 公開鍵 🔑valeriansaliou.gpg.pub.asc を使用して電子メール@valeriansaliou暗号化する必要があります。