2013-03-20 40 views
8

要求: 具有2-3級嵌套的Python對象,其中包含整數,字符串,列表和字典等基本數據類型。 (沒有日期等),需要在redis中針對一個密鑰存儲爲json。 什麼是可用於壓縮json作爲低內存佔用字符串的最佳方法。 目標對象不是很大,平均有1000個小元素, 或轉換爲JSON時的大約15000個字符。這是最好的方式來壓縮JSON以存儲在基於內存的商店,如redis或memcache?

例如。

>>> my_dict 
{'details': {'1': {'age': 13, 'name': 'dhruv'}, '2': {'age': 15, 'name': 'Matt'}}, 'members': ['1', '2']} 
>>> json.dumps(my_dict) 
'{"details": {"1": {"age": 13, "name": "dhruv"}, "2": {"age": 15, "name": "Matt"}}, "members": ["1", "2"]}' 
### SOME BASIC COMPACTION ### 
>>> json.dumps(my_dict, separators=(',',':')) 
'{"details":{"1":{"age":13,"name":"dhruv"},"2":{"age":15,"name":"Matt"}},"members":["1","2"]}' 

1 /是否有任何其他更好的方法來壓縮JSON來節省存儲器中redis的(也確保重量輕事後進行解碼)。

2 /候選人應該有多好msgpack [http://msgpack.org/]?

3 /我應該考慮像醃菜一樣的選擇嗎?

+1

你的應用程序有什麼要求?你需要表現嗎?可靠性,一致性等?你會考慮redis的替代方案嗎? – drekyn 2013-03-20 14:18:25

回答

8

我們只是使用gzip作爲壓縮機。

import gzip 
import cStringIO 

def decompressStringToFile(value, outputFile): 
    """ 
    decompress the given string value (which must be valid compressed gzip 
    data) and write the result in the given open file. 
    """ 
    stream = cStringIO.StringIO(value) 
    decompressor = gzip.GzipFile(fileobj=stream, mode='r') 
    while True: # until EOF 
    chunk = decompressor.read(8192) 
    if not chunk: 
     decompressor.close() 
     outputFile.close() 
     return 
    outputFile.write(chunk) 

def compressFileToString(inputFile): 
    """ 
    read the given open file, compress the data and return it as string. 
    """ 
    stream = cStringIO.StringIO() 
    compressor = gzip.GzipFile(fileobj=stream, mode='w') 
    while True: # until EOF 
    chunk = inputFile.read(8192) 
    if not chunk: # EOF? 
     compressor.close() 
     return stream.getvalue() 
    compressor.write(chunk) 

在我們的用例中,我們將結果存儲爲文件,如您所想。要僅使用內存字符串,也可以使用cStringIO.StringIO()對象替代該文件。

0

另一種可能性是使用MongoDB的存儲格式BSON

您可以在該站點的實現頁面中找到兩個python實現。

編輯:爲什麼不只是保存字典,並在檢索時轉換爲json?

+0

我不認爲BSON可以作爲redis中的密鑰的值添加。 – DhruvPathak 2013-03-20 14:11:35

+0

@DhruvPathak看到我的編輯 – Ivo 2013-03-20 15:23:40

+2

@DhruvPathak確定它可以,爲什麼不呢? Redis對您存儲在密鑰中的內容沒有任何意見。 – 2013-03-20 22:04:36

2

一個簡單的「後處理」方法是構建一個「short key name」映射,並在存儲之前運行生成的json,並在反序列化爲對象之前再次運行(反轉)。例如:

Before: {"details":{"1":{"age":13,"name":"dhruv"},"2":{"age":15,"name":"Matt"}},"members":["1","2"]} 
Map: details:d, age:a, name:n, members:m 
Result: {"d":{"1":{"a":13,"n":"dhruv"},"2":{"a":15,"n":"Matt"}},"m":["1","2"]} 

只需經過JSON和替換鍵 - >值的方式到數據庫,並在途中對應用值 - >鍵。

你也可以gzip的額外善良(不會是一個字符串之後,雖然)。

1

如果你想要它快,try lz4。 如果你想壓縮更好,go for lzma

是否有其他更好的方法來壓縮JSON來節省內存在 Redis的(也保證重量輕事後解碼)?

候選人應該有多好msgpack [http://msgpack.org/]

Msgpack相對較快,並具有較小的內存佔用量。但ujson通常對我來說更快。 您應該對您的數據進行比較,測量壓縮率和解壓縮率以及壓縮比。

我應該考慮像醃菜一樣的選擇嗎?

考慮兩個泡菜(cPickle在有限)和元帥。他們很快。但請記住,它們不安全或可擴展,您需要爲增加的責任支付速度。

相關問題