问题:在预期清除并重建特定的redis键之后,工作人员dynos不会分配内存(直到重新启动dyno)。
我遇到的问题是,我的Heroku worker-dynos在删除和重建 4000 键时,最大内存使用率达到 95%-100%。我有一个预定的重建,每天凌晨4点开始。基于日志我假设键的DEL +键的重建大约需要 ~1490 秒。
Jun 29 04:01:41 app app/worker.2: 4 TID-...io8w RedisWorker JID-...cd2a7 INFO: start
Jun 29 04:06:28 app app/worker.1: 4 TID-...mtks RedisWorker JID-...bf170 INFO: start
Jun 29 04:26:32 app app/worker.1: 4 TID-...mtks RedisWorker JID-...bf170 INFO: done: 1203.71 sec
Jun 29 04:26:33 app app/worker.2: 4 TID-...io8w RedisWorker JID-...cd2a7 INFO: done: 1490.938 sec
内存将占用最大使用量,直到dyno重新启动(已安排)或我们部署。示例图片:Heroku Memory Usage
这是凌晨4点触发的高级别:
def full_clear
RedisWorker.delete_keys("key1*")
RedisWorker.delete_keys("key2*")
RedisWorker.delete_keys("key3*")
self.build
return true
end
def build
... rebuilds keys based on models ...
return true
end
def self.delete_keys(regex)
$redis.scan_each(match: regex) do |key|
$redis.del(key)
end
end
到目前为止我研究的内容还是我的想法:
在调用redis DEL后,内存没有分配?
是否可以更好地找到匹配并执行批量删除的所有密钥?
我正在使用puma的默认值;配置puma + sidekiq以更好地匹配我们的资源有助于成为最好的开始行动吗? Deploying Rails Applications with the Puma Web Server。重新启动后,内存只有大约30%-40%,直到下一次完全重建(即使在hmsets的高使用率期间)。
我注意到,在dyno重启/休息一天到下一个预定的full_rebuild之后,我的ObjectSpace计数相对较低。
我有什么想法,试图弄清楚是什么导致dynos挂起记忆?似乎是旁边的/正在使用的工作人员dynos重建Redis。
答案 0 :(得分:0)
<强>解决方案:强>
我安装了New Relic以查看是否存在潜在的内存膨胀。我们最常用的函数调用之一是进行N + 1查询。修复了N + 1查询并观看我们在New Relic中的60k调用降至~5K。
GC也没有收集,因为它没有达到我们的门槛。稍后可能会有潜在的GC优化 - 但是现在我们的问题已经解决了。我也向Heroku伸出了他们的想法,这就是所讨论的内容:
Dyno上的内存使用将由Ruby VM管理,很可能在密钥重建期间您在内存中保留了太多信息。在重新添加数据之后,您应该考虑释放用于生成键值的内存。
花时间修复N + 1查询肯定有帮助!