【问题标题】:Sliding window reports caching滑动窗口报告缓存
【发布时间】:2020-08-23 23:17:21
【问题描述】:

我有一个 api 端点,它将一些带有“date_from”和“date_to”字段的数据作为输入。

发出请求时,它会启动报告的生成。这些“date_from”和“date_to”字段用于生成(date_to - date_from).days 的子请求数量。基于这些子请求中的每一个,生成散列,用于通过散列从redis数据库中获取子响应,或者制作一些方程式,然后将这个子响应保存到redis。最后,所有子响应都会汇总并作为实际响应返回。

我有一个用例,其中所有数据都已存储在 redis 中,但在 date_to 和 date_from 的长范围内,它仍然是 (date_to - date_from).days 对缓存数据库的请求量。 所以我决定也以同样的方式通过生成哈希将请求的最终响应存储在redis中。

我的问题是这些报告是通过 date_from 和 date_to 的滑动窗口定期生成的。例如,昨天是date_from = "2017-03-08" date_to = "2020-05-07",但今天是date_from = "2017-03-09" date_to = "2020-05-08"。这意味着

  1. 大部分报告都被缓存了,但是天数大大减慢了这个过程
  2. 昨天准备好非常相似的报告,可以在几秒钟内访问,但它不完整,无法知道它们是否相似。

这是我的代码

def generate_report(self, serialized_data):
    result = {
            'deviation' : []
             }
    total_hash = hashlib.sha256(str(serialized_data).encode()).hexdigest()
    total_target = self.redis.get(total_hash)
    if not total_target:
        for date_from, date_to in self.date_range:
            serialized_data['media_company']['date_from'] = \
                                                date_from.strftime("%Y-%m-%d")
            serialized_data['media_company']['date_to'] = \
                                                date_to.strftime("%Y-%m-%d")
            hash = hashlib.sha256(str(serialized_data).encode()).hexdigest()
            target = self.redis.get(hash)
            media_company, context, validator = \
                                    self.prepare_for_validation(serialized_data)
            if not target:
                target = validator.check({'media_company': media_company, **context})
                self.redis.setex(hash, timedelta(days=180), json.dumps(target))
            else:
                self.redis.expire(hash, timedelta(days=180))
                target = json.loads(target)

            result['deviation'].append(target['deviation'])
            result['date'] = [str(date_to) for date_from, date_to in self.date_range]
        total_target = result
        self.redis.setex(total_hash, timedelta(days=180), json.dumps(total_target))
    else:
        total_target = json.loads(total_target)
    return total_target

total_hash表示初始数据的哈希值,

self.date_range 表示子请求的日期范围数组,

hash 表示子查询的哈希

您能否推荐一种更好的缓存数据方式或可以加快该算法的速度?

【问题讨论】:

    标签: python flask caching redis


    【解决方案1】:

    您可以考虑在循环中使用 redis 管道而不是单独的 get 命令,我不确定如何执行此操作的 python 代码,但遵循原型可能会对您有所帮助

    p1 = self.redis.pipeline()
    if not total_target:
      for date_from, date_to in self.date_range:
         #use pipeline here to get target for each day.
         hash = hashlib.sha256(str(serialized_data).encode()).hexdigest()
         p1.get(hash)
    
    #use other pipeline here to set values and expires base on result
    #also compute target_toal
    p2 = self.redis.pipeline()
    for result in p1.execute():
       if not result:
          -- p2 set value with expiry
       else
          -- p2 set expiry
    

    【讨论】:

    • 这是一个巨大的加速!谢谢
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-06-11
    • 2012-03-05
    • 2012-08-08
    • 2012-10-20
    • 1970-01-01
    • 1970-01-01
    • 2010-10-23
    相关资源
    最近更新 更多