将json压缩到基于内存的存储(如redis或memcache)中的最佳方法是什么?

2024-05-13 19:41:16 发布

您现在位置:Python中文网/ 问答频道 /正文

要求: 具有2-3层嵌套的Python对象,包含基本数据类型,如整数、字符串、列表和dict。 (没有日期等),需要作为json存储在redis中的一个键上。 对于将json压缩为低内存占用的字符串,有哪些最佳方法可用。 目标物体不是很大,平均有1000个小元素, 或者转换为JSON时大约15000个字符。

例如

>>> 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/我也应该考虑泡菜之类的选择吗?


Tags: 方法内存字符串nameredisjsonagemy
3条回答

我们只是用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()对象作为文件的替换。

如果你想快点,try lz4。 如果你想压缩得更好,go for lzma

Are there any other better ways to compress json to save memory in redis(also ensuring light weight decoding afterwards)?

How good a candidate would be msgpack [http://msgpack.org/]?

Msgpack速度相对较快,内存占用较小。但是ujson对我来说通常更快。 您应该在数据上比较它们,测量压缩和解压缩速率以及压缩比。

Shall I consider options like pickle as well?

考虑pickle(cPickle在partucular中)和marshal。他们很快。但请记住,它们不是安全的或可扩展的,您需要为速度付出额外的责任。

基于@Alfe的answer,这里有一个版本,它将内容保存在内存中(用于网络I/O任务)。我还做了一些更改来支持Python 3。

import gzip
from io import StringIO, BytesIO

def decompressBytesToString(inputBytes):
  """
  decompress the given byte array (which must be valid 
  compressed gzip data) and return the decoded text (utf-8).
  """
  bio = BytesIO()
  stream = BytesIO(inputBytes)
  decompressor = gzip.GzipFile(fileobj=stream, mode='r')
  while True:  # until EOF
    chunk = decompressor.read(8192)
    if not chunk:
      decompressor.close()
      bio.seek(0)
      return bio.read().decode("utf-8")
    bio.write(chunk)
  return None

def compressStringToBytes(inputString):
  """
  read the given string, encode it in utf-8,
  compress the data and return it as a byte array.
  """
  bio = BytesIO()
  bio.write(inputString.encode("utf-8"))
  bio.seek(0)
  stream = BytesIO()
  compressor = gzip.GzipFile(fileobj=stream, mode='w')
  while True:  # until EOF
    chunk = bio.read(8192)
    if not chunk:  # EOF?
      compressor.close()
      return stream.getvalue()
    compressor.write(chunk)

要测试压缩,请尝试:

inputString="asdf" * 1000
len(inputString)
len(compressStringToBytes(inputString))
decompressBytesToString(compressStringToBytes(inputString))

相关问题 更多 >