2

Redisには私のプロジェクト (webapp のオートコンプリート バックエンド) に非常に優れた機能があることがわかりました。基本的に、それは私の全文検索エンジンです。データセット全体をメモリに保持できないため、Redis の代替品を探しています。

次のように Redis ストアを作成します (このアイデアのクレジットへのリンクが見つかりません)。

  1. 通常のデータベースからの(重み付けされた)アイテムを、各文字の後に3文字のチャンクにチャンクします(「単語」-> ['wor', 'ord', 'rds']
  2. すべてのチャンクは、そのようなチャンクを持つアイテムの id-s のソートされたリストを保持するためのキーになります。( ZADD chunk weight items_id)
  3. すべてのアイテム ID は、アイテムに関する単純な JSON ドキュメントを保持するためのキーでもあります ( SET items_id items_hash_in_json)

検索は次のように機能します。

  1. クエリ文字列は同じように 3 文字のチャンクに作成されます
  2. 私はそれらすべてのチャンクの交差を求め、items_id-s のリストを取得します ( と のZINTERSTORE組み合わせZRANGEBYSCORE)
  3. items_id-s ごとに JSON ドキュメントのリストを返す

簡潔でシンプル。非常に効果的で高速です。このようなフローにはまだいくつかの小さな短所がありますが、ほとんどの場合、自分のドメインに適切なツールと適切なデータ型があると感じています。

主な問題は、メモリが多すぎることです。データベースに約 600K のアイテムがあり、「インデックス作成」で 40 文字後にそれらを削減しましたが、それでも 2.5GB の RAM が必要です。タスクには少し多めです。そして、データセットは、多すぎず、速すぎず、成長し続けます。

現在、いくつかの NoSQL ストアを調べましたが、Redis と同様のアプローチやツールに出会っていません。多分それは私が今すべての仕事をハンマーで見ているからかもしれませんが、他のNoSQLストアでは、そのような機能を自分で実装する必要があると感じています(ソートされたリスト、それらの交差を見つける、バイナリ文字列としての単純なキー値、データの挿入は非常に単純、単純ですプロトコル/API および単純なクライアント)。

Perl バインディングも必要ですが、非常に単純なプロトコル (CoachDB の REST など) の場合は必須ではありません。

他の NoSQL 製品で私のソリューションを実装するためのそのようなツールを知っていますか?

他の目で、私はすでに完全に異なるソリューションも探しています ( couchdb-lucene のようなものですが、上記で説明したシステムの放棄は避けたいと思います。

4

2 に答える 2

1

HTTP キャッシュ 現在私のサイトで使用している解決策があります。Nginx を使用して、静的ファイルでオートコンプリート クエリをキャッシュします。Nginx は静的ファイルを非常に迅速に提供できます。これが私の設定にあるサンプル行です。

http {

    fastcgi_cache_path /var/cache/nginx levels=1:2
            keys_zone=tt:600m
            inactive=7d max_size=10g;

    fastcgi_temp_path /var/cache/nginx/tmp;

}

このブロックは、ファイルが保存されるパスを記述します。レベルはディレクトリの深さです。1:2 で十分です。ここでの私のゾーンは tt と呼ばれます。好きな名前を付けてください。有効期限が続きます。

location ~ /tt/(.+)\.php$ {
            try_files $uri /index.php?$args;
            fastcgi_index   index.php;
            fastcgi_pass    127.0.0.1:9000;
            include         fastcgi_params;
            fastcgi_param   SCRIPT_FILENAME    $document_root$fastcgi_script_name;
            fastcgi_param   SCRIPT_NAME        $fastcgi_script_name;

                #Caching parameters
                fastcgi_cache tt;

                fastcgi_cache_key "$scheme$request_method$host$request_uri";

                fastcgi_cache_valid  200 302 304 30m;
                fastcgi_cache_valid  301 1h;
                fastcgi_cache_valid  any 5m;
                fastcgi_cache_use_stale error timeout invalid_header updating http_500;
        }

キャッシュパラメータを含むロケーションブロックになります。したがって、URI /tt/.*.php を持つものはすべてキャッシュされます。URI + クエリ文字列がキャッシュ キーになります。

Nginx を使用しない場合、同じ概念が別の Web サーバーで機能する可能性があります。これが役立つことを願っています。

編集

コメントから: インデックスをプレーン ファイルとして使用すると、SQL クエリよりもかなり遅くなるようです。それでも、私はそれらをベンチマークしていません。

Nginx のキャッシュ ヒットは次のようになります。

-> Nginx -> ファイル

逃す:

-> Nginx -> php/python/ruby -> db(redis/mysql/whatever)

最初のパスは diskio を考えると遅く感じるかもしれませんが、そうではありません。OS は頻繁にアクセスされるファイルを自動的にキャッシュします。したがって、Nginx が熱くなると、PHP バックエンドに「Hello world」と言うだけでは、比較して遅くなります。静的ファイルを提供するようなものだからです。

実際のヒット/ミス率は、アプリケーション、データ、および構成によって異なります。私の経験では、人々は多くの同じ検索用語を使用するため、60 万個のファイルが存在することはないでしょう。やっても特に問題はありませんが、Nginx が管理してくれます。この方法は、データが頻繁に変更され、それらの変更をすばやく検索に反映させたい場合にはあまり適していません。有効期限を短く設定する必要があるため、ミスが増える可能性があります。

Redis Zip リスト/ハッシュ http://redis.io/topics/memory-optimization

それでもソートされたセットが必要な場合は、リンクからの構成設定がデータセットのニーズに対して十分に高く設定されていることを確認してください。ハッシュを使用できる場合は、そのページの下の方に示されているアルゴリズムを使用して大量のメモリを節約できます。json文字列にリンクしているitem_idを格納する場合に、間違いなく使用できると思います。

于 2013-01-31T03:43:26.430 に答える