2012-02-03 1 views
18

私のモデルには、会社の社員のように一度だけ計算したいエンティティがあります。 Memcache(duration = 1day)に同じクエリを何度も繰り返さないようにするために、Memcacheに格納されるバイト数が許容範囲を超えているというエラーがアプリケーションから発生することがあります。Memcacheの長さを1000000バイトに制限することは避けてください

Values may not be more than 1000000 bytes in length; received 1071339 bytes 

Memcacheで行うべきオブジェクトのリストを格納していますか?もしそうなら、上記のエラーを避けるベストプラクティスは何ですか?私は現在1000のオブジェクトを引っ張っています。値を< 200に制限しますか? Memcacheに入る前に、おそらく処理されている(連載されているものなど)ので、オブジェクトのサイズをメモリでチェックするのはあまり良い考えではないようです。

+0

質問のタイトルを初めて読んだとき、私はMemcacheが100万の値の1Mしか保存できないと考えました。タイトルを「Memcache 1MB制限値の回避」に変更できますか? –

答えて

28

デビッド、あなたはどの言語を使っているのかは言いませんが、Pythonでは、イブラヒムがpickleを使うことと同じことをすることができます。大きなオブジェクトを読み書きする2つの小さなヘルパー関数をmemcacheに書き込むだけです。ここでは(未テスト)スケッチです:

def store(key, value, chunksize=950000): 
    serialized = pickle.dumps(value, 2) 
    values = {} 
    for i in xrange(0, len(serialized), chunksize): 
    values['%s.%s' % (key, i//chunksize)] = serialized[i : i+chunksize] 
    return memcache.set_multi(values) 

def retrieve(key): 
    result = memcache.get_multi(['%s.%s' % (key, i) for i in xrange(32)]) 
    serialized = ''.join([v for k, v in sorted(result.items()) if v is not None]) 
    return pickle.loads(serialized) 
+1

スケッチのためのGuidoさん、ありがとうございました。 –

+0

@Nikolayと同様の問題がありました。pickle.loads行は、値がピクルされた順序とは異なる順序で戻ってきたために失敗しました。私の問題を解決するために、私はserialized_data = [結果のキーと結果の[キー]が[なし]でない場合はキーのキーに[result [key]を使用しました。 – John

+0

このコードを完全に理解することができません。誰かにステップバイステップで何を説明するように頼むことができますか? – puoyaahhh

8

私は頻繁にmemcacheに数メガバイトのサイズのオブジェクトを格納します。これが良いかどうかについてはコメントできませんが、アプリエンジンインスタンス間でメガバイト単位のデータを転送するには比較的速い方法が必要な場合があります。

私はJavaを使用しているので、Javaのシリアライザを使用して生のオブジェクトをシリアライズし、シリアル化されたバイト配列を生成しています。シリアライズされたオブジェクトのサイズが分かっているので、800 KBのバイト配列のまとまりに分けることができます。次に、バイト配列をコンテナオブジェクトにカプセル化し、生のオブジェクトの代わりにそのオブジェクトを格納します。

各コンテナオブジェクトは、次のバイト配列チャンクをフェッチできる次のmemcacheキーへのポインタを持つことができます。また、memcacheからフェッチする必要のあるチャンクがない場合はnullを返します。 (リンクされたリストのように)バイト配列のチャンクを大きなバイト配列に再マージし、Javaのデシリアライザを使用してデシリアライズします。

+0

ありがとうイブラヒム、それは間違いなく創造的なソリューションです。私はmemcacheにオブジェクトリストを格納するためのより簡単な標準的なアプローチが何であるかを見たいと思っています。 –

5

保存したすべてのデータに常にアクセスする必要がありますか?そうでなければ、データセットを分割し、必要なデータの一部だけにアクセスすることで利益を得られます。

1000人の従業員のリストを表示すると、おそらくそれをページ設定します。あなたが改ページしたら、あなたは間違いなく分割することができます。

データセットの2つのリストを作成することができます。1つのライターは、1 MBに収めることができる最も重要な情報だけでなく、完全な情報で複数の部分に分割された他のリストです。ライトリストでは、従業員の名前またはページネーションによるフィルタリングなど、最も基本的な操作を適用できます。必要なときに重いデータセットをロードすると、本当に必要な部分だけを読み込むことができます。

しかし、これらの提案には実装に時間がかかります。あなたの現在のデザインと一緒に暮らすことができるならば、あなたのリストを〜300個のアイテムまたは何でも安全な数の塊に分け、それらをすべてロードしてマージしてください。

+1

アイデアのスポットSkirmantas!あなたは実装時間がかかるでしょうが、調べる価値があります。あなたのアドバイスを共有してくれてありがとう –

3

あなたはどのように大きなオブジェクトを使用すると、大きなオブジェクトを許可するmemcachedのオプションを使用することができることが分かっている場合:

memcached -I 10m 

これは10メガバイトまでのオブジェクトを許可します。

+2

ありがとうございます。知っておくと便利ですが、これはAppEngineのオプションではなく、元の質問のプラットフォームとしてタグ付けされています:https://cloud.google.com/appengine/docs/python/memcache/#Python_Limits – Michael

関連する問題