我的模型TicketType
有大约500个实例。
每周只会改变几次。
但是如果它改变了,我需要使用旧TicketTypes的所有缓存值无效。
不幸的是,某些缓存键并未修复。它们包含计算数据。
我看到了这些解决方案:
使用version
参数并更新TicketType
的保存后信号处理程序的版本值。
对所有基于TicketType的缓存键使用公共前缀。 然后使后保存信号处理程序中的所有缓存键无效。
我想还有第三种,更好的方法......
示例:
TicketType是一棵树。 TicketTypes的可见性绑定到权限。如果树具有不同的权限,则两个用户可能会以不同的方式查看树。我们根据权限缓存它。用户的权限被序列化和散列。通过创建包含散列和固定部分的字符串来创建缓存键:
hash_key='ticket-type-tree--%s' % hashed_permissions
如果TicketType树发生更改,我们需要确保没有从缓存中加载旧数据。只要不使用旧数据,就不需要主动无效。
答案 0 :(得分:1)
您可以将故障单修改时间用作缓存密钥的一部分。
hash_key = 'ticket-type-tree--%s-%s' % (hashed_permissions, tree.lastmodified)
您可以使用DateTimeField
添加auto_now=True
。如果从db获取修改时间过于昂贵,您也可以缓存它。
通常,更新post_save
信号处理程序中的缓存很好。除非您希望始终拥有一致的数据,并希望为交易支付额外费用。
答案 1 :(得分:1)
使用redis缓存模型
我将缓存我的实例的方式如下:
1 - 确保您当时正在购买一件商品。例如:Model.objects.get(foo ='bar'),每次从数据库中获取模型时都使用属性foo
。这将用于确保数据在以后失效。
2-Override方法save()并确保使用foo属性将数据保存到缓存中。
E.g:
class Model(model.Model):
foo = models.CharField()
bar = models.CharField()
def save(self, *args, **kwargs):
redis.set(foo, serialize_model())
super(Model, self).save(*args, **kwargs)
def serialize_model():
return serilized_object
3-Override get方法在命中数据库之前获取序列化对象。
E.g:
class Model(model.Model):
...
def get(self, *args, **kwargs):
if redis.get(self.foo):
return redis.get(self.foo)
else:
return super(Model).get(*args, **kwargs)
4 - 如果删除或删除实例,则覆盖删除方法以删除缓存
E.g
class Model(model.Model):
...
def delete(self,*args, **kwargs):
redis.delete(self.foo)
super(Model, self).delete(*args, **kwargs)
将Model类替换为您的模型,在这种情况下,它将是Ticket Type
有一件事,我假设您不会在Django应用程序之外触摸数据库。如果你在任何其他地方使用原始sql,这将无效。
在他们的网站上查找redis功能,它们具有删除,设置和获取功能。如果你正在使用其他缓存方式。寻找如何设置,获取和删除。
答案 2 :(得分:0)
好吧,基本上你的问题只是缓存键的表现力。当你必须做一些像哈希一样复杂的东西来获取密钥时,它必须是一个暗示有缺失的东西。
在你的情况下,我相信缺少的只是一个"权限集"宾语。你可以把它称为一个组,一个角色(如在RBAC中)...那就是为什么我问你集合是否重复 - 实际上,你的哈希键只是一种重新创建设置对象的ID的方法不存在。
所以解决方案是:
两个最后的评论:
答案 3 :(得分:0)
在TicketType保存信号处理程序中:
a)根据所有用户的权限生成密钥并使密钥无效
b)为每个排列(许可)生成密钥(如果可以计算它们)并使密钥无效
c)使用第二个memcached实例仅存储这些缓存并清除它(最简单)
P.S。:专业提示将刷新缓存而不是使它们无效。然而,django信号中未被捕获的异常可能会有麻烦,所以要疲倦