【问题标题】:Django caching a large listDjango缓存一个大列表
【发布时间】:2012-08-06 03:28:51
【问题描述】:

我的 django 应用程序处理 25MB 的二进制文件。它们每个都有大约 100,000 条“记录”,每条 256 字节。

从磁盘读取二进制文件并使用 python 的 struct 模块对其进行解码大约需要 7 秒。我将数据转换成一个包含大约 100,000 个项目的列表,其中每个项目都是一个包含各种类型(浮点数、字符串等)值的字典。

我的 django 视图需要搜索这个列表。显然 7 秒太长了。

我尝试使用 django 的低级缓存 API 来缓存整个列表,但这不起作用,因为任何单个缓存项的最大大小限制为 1MB。我尝试单独缓存 100,000 个列表项,但这需要超过 7 秒的时间 - 大部分时间都花在解开这些项上。

有没有一种方便的方法可以在请求之间将大列表存储在内存中?你能想出另一种方法来缓存对象以供我的 django 应用使用吗?

【问题讨论】:

  • 是否可以使用 numpy.array?
  • 你考虑过使用数据库吗?
  • James R:我看不到 numpy.array 和我的缓存问题之间的联系。 Ignacio:是的,这可行——我将 100,000 个项目中的每一个存储为 django 模型实例,并使用 ORM 来调用后续请求的数据......但我希望找到一个更简单的基于内存的解决方案。
  • numpy.array 在存储大型数字数组时往往很有效。如果您不存储数字,那么它就没有用处
  • 另外,如果是平的,你可以考虑使用 mongo 或 casandra。

标签: django caching memcached deserialization pickle


【解决方案1】:

编辑item大小限制为10m(大于1m),添加

-I 10m

到 /etc/memcached.conf 并重启 memcached

还可以在位于 /usr/lib/python2.7/dist-packages/django/core/cache/backends 的 memcached.py 中编辑此类,使其如下所示:

class MemcachedCache(BaseMemcachedCache):
"An implementation of a cache binding using python-memcached"
def __init__(self, server, params):
    import memcache
    memcache.SERVER_MAX_VALUE_LENGTH = 1024*1024*10 #added limit to accept 10mb
    super(MemcachedCache, self).__init__(server, params,
                                         library=memcache,
                                         value_not_found_exception=ValueError)

【讨论】:

  • 这当然是在 Ubuntu 12.04 LTS 上...文件位置可能因您的发行版而异。
  • 只是浪费了几个小时试图解决这个问题......无法弄清楚是memcache还是Django应该受到指责,然后意识到两者都是!干杯
  • 实际上,由于我刚刚报告的 python-memcache 的意外行为,这对我不起作用。见github.com/linsomniac/python-memcached/issues/13
  • 这对我也不起作用。我使用 pylibmc 修复了它,而不是 python-memcache。
【解决方案2】:

我还不能添加 cmets,但我想分享一下我对这个问题的快速修复,因为当您在导入时更改 SERVER_MAX_VALUE_LENGTH 时,python-memcached 的行为也很奇怪。

好吧,除了 FizxMike 建议的 __init__ 编辑之外,您还可以编辑同一类中的 _cache 属性。这样做您可以实例化 python-memcached 客户端显式传递server_max_value_length,如下所示:

from django.core.cache.backends.memcached import BaseMemcachedCache

DEFAULT_MAX_VALUE_LENGTH = 1024 * 1024

class MemcachedCache(BaseMemcachedCache):
    def __init__(self, server, params):
        #options from the settings['CACHE'][connection]
        self._options = params.get("OPTIONS", {})
        import memcache
        memcache.SERVER_MAX_VALUE_LENGTH = self._options.get('SERVER_MAX_VALUE_LENGTH', DEFAULT_MAX_VALUE_LENGTH)

        super(MemcachedCache, self).__init__(server, params,
                                             library=memcache,
                                             value_not_found_exception=ValueError)

    @property
    def _cache(self):
        if getattr(self, '_client', None) is None:
            server_max_value_length = self._options.get("SERVER_MAX_VALUE_LENGTH", DEFAULT_MAX_VALUE_LENGTH)
            #one could optionally send more parameters here through the options settings,
            #I simplified here for brevity
            self._client = self._lib.Client(self._servers,
                server_max_value_length=server_max_value_length)

        return self._client

我也更喜欢创建另一个继承自 BaseMemcachedCache 的后端并使用它而不是编辑 django 代码。

这是 django memcached 后端模块供参考: https://github.com/django/django/blob/master/django/core/cache/backends/memcached.py

感谢您对本主题的所有帮助!

【讨论】:

    猜你喜欢
    • 2011-02-21
    • 2014-03-29
    • 2011-11-11
    • 2013-08-16
    • 2012-02-21
    • 2022-01-18
    • 2014-11-11
    • 2015-08-07
    • 2017-11-28
    相关资源
    最近更新 更多