注:的 这是一个详细的问题,询问如何使用memcached在我的Web应用程序中实现和管理数据库缓存。这个问题使用Python / Django来说明数据模型和用法,但语言并不那么相关。我真的更感兴趣的是学习维持缓存一致性的最佳策略。 Python / Django恰好是我用来说明这个问题的语言。
我的申请规则:
(value * Y-Coord)
来计算。(value * X-Coord)
求和来计算。memcached
来最小化我的数据库访问。下图显示了我的网格状态示例。
我的代码:
import memcache
mc = memcache.Client(['127.0.0.1:11211'], debug=0)
class Cell(models.Model):
x = models.IntegerField(editable=False)
y = models.IntegerField(editable=False)
# Whenever this value is updated, the keys for the row and column need to be
# invalidated. But not sure exactly how I should manage that.
value = models.IntegerField()
class Row(models.Model):
y = models.IntegerField()
@property
def cummulative_score(self):
# I need to do some memcaching here.
# But not sure the smartest way to do it.
return sum(map(lambda p: p.x * p.value, Cell.objects.filter(y=self.y)))
class Column(models.Model):
x = models.IntegerField()
@property
def cummulative_score(self):
# I need to do some memcaching here.
# But not sure the smartest way to do it.
return sum(map(lambda p: p.y * p.value, Cell.objects.filter(x=self.x)))
这就是我的问题:
您可以看到我已设置memcached
个实例。当然我知道如何在memcached
中插入/删除/更新键和值。但鉴于上面的代码,我应该如何恰当地命名密钥?如果修改了键名,它将无法工作,因为每个行和列必须存在单独的键。而且关键是如何在更新单元格中的值时确保相应的键(以及仅适当的键)无效?
每当有人更新Cell.values以便最小化数据库访问时,如何管理缓存失效?难道没有一些django中间件可以为我处理这本书吗?我见过的documents不会这样做。
答案 0 :(得分:1)
如果要缓存单个行/列组合,则应将对象ID附加到键名称。
给出x,y变量:
key = 'x={}_y={}'.format(x, y)
我会使用表名并只附加id,行id可能只是表PK,列id可能只是列名,就像这样
key = '{}_{}_{}'.format(table_name, obj.id, column_name)
无论如何,我建议考虑缓存整行而不是单个细胞
答案 1 :(得分:1)
# your client, be it memcache or redis, assign to client variable
# I think both of them use set without TTL for permanent values.
class Cell(models.Model):
x = models.IntegerField(editable=False)
y = models.IntegerField(editable=False)
value = models.IntegerField()
def save(self, *args, **kwargs):
Cell.cache("row",self.y)
Cell.cache("column",self.x)
super(Cell, self).save(*args, **kwargs)
@staticmethod
def score(dimension, number):
return client.get(dimension+str(number), False) or Cell.cache(number)
@staticmethod
def cache(dimension, number):
if dimension == "row":
val = sum([c.y * c.value for c in Cell.objects.filter(y=number)])
client.set(dimension+str(self.y),val)
return val
if dimension == "column":
val = sum([c.x * c.value for c in Cell.objects.filter(x=number)])
client.set(dimension+str(self.x),val)
return val
raise Exception("No such dimension:"+str(dimension))
答案 2 :(得分:1)
保存模型对象时,Cell
对象可以使其Row
和Column
的缓存值无效。
(Row
和Column
在这里是普通对象,而不是Django模型,但当然,如果由于某种原因需要将它们存储在数据库中,您可以更改它。)
import memcache
mc = memcache.Client(['127.0.0.1:11211'], debug=0)
class Cell(models.Model):
x = models.IntegerField(editable=False)
y = models.IntegerField(editable=False)
# Whenever this value is updated, the keys for the row and column need to be
# invalidated. But not sure exactly how I should manage that.
value = models.IntegerField()
def invalidate_cache(self):
Row(self.y).invalidate_cache()
Column(self.x).invalidate_cache()
def save(self, *args, **kwargs):
super(Cell, self).save(*args, **kwargs)
self.invalidate_cache()
class Row(object):
def __init__(self, y):
self.y = y
@property
def cache_key(self):
return "row_{}".format(self.y)
@property
def cumulative_score(self):
score = mc.get(self.cache_key)
if not score:
score = sum(map(lambda p: p.x * p.value, Cell.objects.filter(y=self.y)))
mc.set(self.cache_key, score)
return score
def invalidate_cache(self):
mc.delete(self.cache_key)
class Column(object):
def __init__(self, x):
self.x = x
@property
def cache_key(self):
return "column_{}".format(self.x)
@property
def cumulative_score(self):
score = mc.get(self.cache_key)
if not score:
score = sum(map(lambda p: p.y * p.value, Cell.objects.filter(x=self.x)))
mc.set(self.cache_key, score)
return score
def invalidate_cache(self):
mc.delete(self.cache_key)