首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当Redis正在执行大规模DEL+SET时,如何处理路由超时?

当Redis正在执行大规模DEL+SET时,如何处理路由超时?
EN

Stack Overflow用户
提问于 2017-08-10 14:17:13
回答 1查看 257关注 0票数 0

我的路由之一(overview_route)正在调用大量模型操作,这些操作通常由我在Redis中的方法缓存处理。但是,当一个新的/更新的记录保存到PG中时,我有一个SideKiq作业,它将通过删除需要更新的Redis键来处理数据中的更改,然后调用我们的方法将其缓存回Redis。在Redis的重建过程中,如果有人试图到达overview_route,它将达到30秒的超时终止(可能需要1-3分钟才能运行)。

例如,通常发生的情况:

代码语言:javascript
复制
User A will go to route `overview_route` when everything in redis is 
cached -- which will allow the page to be served quickly.

User A will add 2 new records that will change a lot of the 
computations on `overview_route`. User B submit those records and a 
background process fires to go and delete the records that need to be 
changed and and then gets rebuilt.

User A will go check `overview_route` to see the updated date, 
however can not even load the page and gets an application error.

User A can check back in 3-5 minutes (hopefully) and the page can be 
served again.

正在使用的重构逻辑示例:

代码语言:javascript
复制
def update(id)
  delete_keys("example:#{id}:current")
  delete_keys("example:#{id}:last_week")
  delete_keys("example:#{id}:start_of_week")
  ...
  rebuild(id)
end

def delete_keys(regex)
  $redis.scan_each(match: regex) do |key|
    $redis.del(key)
  end
end

#Basically loop through all records on a given model. If models 
#methods come across anything that isn't currently chached -- it will 
#set it back in redis
def rebuild(id)
  records = ModelExample.find(id)
  records.all.each do |a|
    a.rebuild
  end
  ...
end

如何通过多次调用未处理的方法(通常为性能而缓存的方法)来处理此问题?

我试过/想过:

  • 修正了模型方法中最大的N+1查询。这在很大程度上有所帮助,但仍然没有解决超时问题。
  • 考虑到现有的,在Redis键上添加某种指示,其中一个是旧数据,然后添加新的(在键中添加一个is_stale )。在完全添加了new之后,删除旧数据。模型方法可以同时引用两个键,并检查两个Redis键?
  • 我能在Redis上做点什么然后失败吗?不知道如果我一次有一堆背景工作,这会如何处理。
  • 我知道雷迪斯要过期了。我能用这样的东西吗?我怎么会在新钥匙上失败呢?
  • 不知何故,不要删除任何一个密钥,只需更新它们?
EN

回答 1

Stack Overflow用户

发布于 2017-08-10 17:13:29

可能有很多方法可以做到这一点,但是当我有需要一段时间才能完成的代码时,我就会在后台运行这些任务。我推荐Sidekiq http://sidekiq.org/。免费版本应足以满足这一要求。

看起来你已经有了逻辑,所以我只需要把id传递过来,然后把逻辑移到一个工作人员身上。有点像

代码语言:javascript
复制
# app/worker/redis_worker.rb
class RedisWorker
  include Sidekiq::Worker
  def perform(id)
    update(id)
  end
 ... Your logic
 def update(id)
   delete_keys("example:#{id}:current")
   delete_keys("example:#{id}:last_week")
   delete_keys("example:#{id}:start_of_week")
   ...
   rebuild(id)
 end

 def delete_keys(regex)
   $redis.scan_each(match: regex) do |key|
      $redis.del(key)
    end
  end

 def rebuild(id)
   records = ModelExample.find(id)
   records.all.each do |a|
     a.rebuild
   end
   ...
 end
end

要叫它,你只需要叫RedisWorker.perform_async(id)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/45616292

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档