编写操作永不过期列表的异步任务(在 Django 中)

Writing asynchronous task that manipulates a never-expiring list (in Django)

在我维护的一个Django项目中,用户上传照片供其他人查看和评论。我不想让任何人上传最近看到的照片,所以我将每张上传的照片与最近的 300 张照片进行比较。如果我发现重复,我会提醒用户尝试新的东西。我想优化这个过程——这就是这个问题的意思。

目前,每当用户尝试上传照片时,都会从负责照片上传的基于 class 的视图的 form_valid 方法内部处理此代码:

recent_photos = Photo.objects.order_by('-id')[:300]
recent_hashes = [photo.avg_hash for photo in recent_photos]
#some code to compare avg_hash values across images to flag duplication

我不想在每次用户上传照片时从客户端调用这个数据库,我想维护缓存中每个图像的最近 300 个平均哈希值的列表.这样,我消除了数据库调用。

现在每个图像的 average_hash 值在创建 photo 对象时保存在数据库中。我想编写一个异步任务,它基本上接收每个图像的 avg_hash 值,并将其插入到缓存的 avg_hash 值列表中,将列表保持在 300 长度和无限期满时间。

有人可以帮我编写这样的任务吗?我认为它应该是这样的:

@celery_app1.task(name='tasks.build_avg_hash_list')
def build_avg_has_list(latest_avg_hash):
    cache_mem = get_cache('django.core.cache.backends.memcached.MemcachedCache', **{
        'LOCATION': '127.0.0.1:11211', 'TIMEOUT': None,
    })
    try:    
        avg_hash_list = cache_mem.get('avg_hash_list')
        avg_hash_list.insert(0,latest_avg_hash)
        list_len = len(avg_hash_list)
        if list_len > 300:
            del avg_hash_list[301:list_len] 
    except:
        avg_hash_list = [latest_avg_hash]
    cache_mem.set('avg_hash_list', avg_hash_list)

我在这里遗漏了一些东西。例如:

1) 我使用的是 Django 1.5.1,Timeout:NONE 在设置无限到期时间时不起作用。

2) 我不确定我提出的逻辑是否可靠地将列表长度固定在 300 个条目或以下。我应该改用 MAX_ENTRIES 缓存参数吗?

3) 最后,:我也在使用 cache_mem = get_cache('django.core.cache.backends.memcached.MemcachedCache', **{ 'LOCATION': '127.0.0.1:11211', 'TIMEOUT': 120 }) 进行另一项异步任务。我想确认将此新任务的输出保存在同一位置不会 覆盖其他异步任务(也保存在同一位置)的输出

提前致谢。

看到这个问题并看到了您的其他一些问题,是时候投资 Redis 了。如果使用 redis sets.

,这个看似复杂的任务其实很简单

每次有人向 add a new entry 添加一张新图像到 avg_hashes 的 redis 集。您甚至不需要将自己限制在 300 个以内,集合中可以有数千个项目,并且由于它们在磁盘上持久存在,因此服务器重启不会导致数据丢失。

当您想查看用户是否正在上传副本时,您可以调用 sismember

如果你确实想限制集合中的成员数量,当长度超过之前选择的某个数量时,你可以使用 srem 将其清除。

额外功能:如果您适应了 redis,则不需要 celery 任务,但由于您已经在使用 celery,您可能已经安装了 redis,因为它是 celery 支持的代理之一。