Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/django/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何使用派生数据在Django中进行DB memcaching?_Python_Django_Caching_Memcached_Database Caching - Fatal编程技术网

Python 如何使用派生数据在Django中进行DB memcaching?

Python 如何使用派生数据在Django中进行DB memcaching?,python,django,caching,memcached,database-caching,Python,Django,Caching,Memcached,Database Caching,注意: 这是一个详细的问题,询问如何在使用memcached的web应用程序中最好地实现和管理数据库缓存。这个问题使用Python/Django来说明数据模型和用法,但是语言并没有那么重要。我更感兴趣的是学习维护缓存一致性的最佳策略是什么。Python/Django恰好是我用来说明这个问题的语言 我的申请规则: import memcache mc = memcache.Client(['127.0.0.1:11211'], debug=0) class Cell(models.Model):

注意: 这是一个详细的问题,询问如何在使用memcached的web应用程序中最好地实现和管理数据库缓存。这个问题使用Python/Django来说明数据模型和用法,但是语言并没有那么重要。我更感兴趣的是学习维护缓存一致性的最佳策略是什么。Python/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()


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)))
  • 我有一个3×3的整数网格
  • 该网格的大小将来可能会增加或减少。我们的解决方案必须扩大规模
  • 它们是每行的累积分数,通过对该行中每个单元格的
    (value*Y-Coord)
    求和来计算
  • 它们是每列的累积分数,通过对该列中每个单元格的
    (value*X-Coord)
    求和来计算
  • 单元格中的值很少更改。但是这些值和分数经常被读取
  • 我想使用
    memcached
    最小化对数据库的访问
  • 我希望尽量减少/消除在数据库中存储重复或派生的信息
  • 下图显示了my grid状态的示例

    我的代码:

    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)))
    
    所以我的问题是:

    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中间件可以帮我处理这个簿记?我看到的没有这样做。

    如果要缓存单个行/列组合,应该将对象id附加到键名

    给定一个x,y变量:

    key = 'x={}_y={}'.format(x, y)
    
    我将使用表名并只附加id,行id可以是表PK,列id可以是列名,如下所示

    key = '{}_{}_{}'.format(table_name, obj.id, column_name)
    

    在任何情况下,我建议考虑缓存整行而不是单个单元格

    保存模型对象时,
    单元格
    对象可以使其
    的缓存值无效

    # 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))
    
    在这里是普通对象,而不是Django模型,但是如果出于某种原因需要将它们存储在数据库中,当然可以更改。)


    但是更新Cell.values时,如何管理缓存失效?是否有一些django中间件可以为我处理这个簿记?仅供参考,我看到的关于将Django与memcached结合使用的文档似乎都在谈论如何为我缓存动态页面的输出。我不想那样。我实际上不提供任何页面。我的应用程序只是一系列可调用的RESTAPI。但我希望这些API能够最小化数据库访问。因此,我希望我的django模型缓存对DB的调用。要使其无效,您可以使用时间,例如,将缓存有效时间设置为1秒,这样您的数据库每秒的命中率不会超过1。您可以从上面的问题中提取我的代码,并实际插入语句以使其工作吗?我还没有得到一个清晰的例子,说明如何以干净和原子的方式管理缓存失效。修改上面的代码对我帮助最大。你不需要行或列模型,它们只是在Cell.Ok中重复数据。这很有帮助。谢谢但是,该代码是否包含潜在的竞争条件?我不是100%肯定。但我认为可能。如果我将字典存储为缓存中的一个值(如
    client.set(“myKey”,“a”:1”,“B”:2})
    ),并且我的应用程序希望将B的值从2增加到3,那么如何防止竞争条件?如果两个不同的web用户及时触发相同的增量操作,我认为B中的值可能会损坏。我怎么能避免呢?我使用的操作是原子级的。对于模型的任何给定快照,您永远不会得到错误的答案,但您可能会遇到这样的情况:如果两个增量操作在时间上足够接近(您确实说过更改值的频率很低),两个线程可能会得出不同的结论,并且具有较旧结果的线程可能是后一个存储该结果的线程。考虑到你的限制,几率相对较低。您可以在客户端中为keyvalue分配一个sentinel值,该值指示正在进行设置操作。有关使用memcached sentinel的示例,请参阅