在保存到缓存之前压缩Python对象

问题描述 投票:0回答:3

在将Python对象(列表、字典、字符串等)保存到缓存之前对其进行压缩并从缓存中读取后进行解压缩的快速方法是什么?

我正在使用 Django,我希望直接在 Django 的缓存后端添加压缩/解压缩支持,这使其可用于我的所有 Django 应用程序。

我查看了 django/core/cache/backends/memcached.py

import cmemcache as memcache

class CacheClass(BaseCache):

    def __init__(self, server, params):
        BaseCache.__init__(self, params)
        self._cache = memcache.Client(server.split(';'))

    def get(self, key, default=None):
        val = self._cache.get(smart_str(key))
        if val is None:
            return default
        return val

    def set(self, key, value, timeout=0):
        self._cache.set(smart_str(key), value, self._get_memcache_timeout(timeout))

看起来 pickle/unpickle 是由 cmemcache 库完成的。我不知道把压缩/解压缩代码放在哪里。

django caching memcached compression
3个回答
5
投票

首先 - 您确定需要它吗?您的数据结构是否太大而无法在缓存中容纳未压缩的内容?压缩/解压缩会产生开销,这可能会抵消您通过缓存获得的任何收益。

如果你确实需要压缩,那么你可能想使用zlib

如果您要使用 zlib,您可能需要尝试

compress
方法中可用的不同压缩级别,以平衡 CPU 时间与压缩级别:

zlib.compress(string[, level])

压缩字符串中的数据,返回包含压缩数据的字符串。
level
是从1到9的整数,控制压缩级别; 1 最快,产生的压缩最少,9 最慢,产生最多的压缩。默认值为 6。如果发生任何错误,则会引发
error
异常。


5
投票

我进一步研究了 python-memcache 的源代码。

它已经支持在将值发送到 memcached 之前通过 zlib 压缩值。

lv = len(val)
# We should try to compress if min_compress_len > 0 and we could
# import zlib and this string is longer than our min threshold.
if min_compress_len and _supports_compress and lv > min_compress_len:
    comp_val = compress(val)
    # Only retain the result if the compression result is smaller
    # than the original.
    if len(comp_val) < lv:
        flags |= Client._FLAG_COMPRESSED
        val = comp_val

def _set(self, cmd, key, val, time, min_compress_len = 0):

这是 Django 在其 memcache 后端中对“set”命令的实现:

def set(self, key, value, timeout=0):
    self._cache.set(smart_str(key), value, self._get_memcache_timeout(timeout))

显然它没有“min_compress_len”参数。


0
投票

如果您是因为将 django 从 Django3 升级到 Django5(或 4)而到达这里,并且 PyMemcachedCache 存储的对象高于 Memcached 默认对象大小限制 1mb,这在 Django 3 中的 MemcachedCache 之前没有发生过,您可以添加 PyMemcachedCache 的选项以使用 OPTIONS 键进行压缩,如下面的示例所示

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.PyMemcacheCache',
        'LOCATION': '127.0.0.1:11211',
         "OPTIONS": {
            "serde": pymemcache.serde.compressed_serde,
        }
    }
}

当然,记得在 django 设置文件中导入 pymemcache。这足以满足我的特定情况,但是有一些方法可以提高压缩级别,但这需要修改 django 的 memcached 源代码。

来源:PyMemcache 文档

澄清一下:

  • Django 3,内存中的Python对象为3.5 mb,在memcache中保存得很好 使用 MemcachedCache
  • Django 5,内存中的Python对象为3.5 mb, 使用 PyMemcachedCache 保存在内存缓存中时引发“对象太大”错误

对于这种情况,请将上面给出的选项添加到 django 设置文件中的 CACHE 设置中

© www.soinside.com 2019 - 2024. All rights reserved.