PostAlerter 作业最近卡住/OOM

自从 FEATURE: new watched_precedence_over_muted setting (#22252) · discourse/discourse@9cf981f · GitHub (推测!) 以来,我们的 Sidekiq 队列一直在被卡住的 PostAlert 作业填满/OOM:

鉴于此提交已出现类似的回归 (FIX: error when CategoryList tried to find relevant topics by lis2 · Pull Request #22339 · discourse/discourse · GitHub),这相当可疑——我们现在将尝试降级到上述提交之前的某个提交,并会报告结果。

2 个赞

确实,将版本降至 4f7f9ef87cbcd574144f657dd43b7e705d98ff8e 解决了卡住的 PostAlert sidekiq 工作进程和内存不足(OOM)的担忧:现在少数能够排队的 PostAlert 作业能在几秒钟内完成,而不是几分钟。

2 个赞

Ping @kris.kotlarek

1 个赞

我刚看到 FIX: improve performance of post alerter job (#22378) · discourse/discourse@7a204e7 · GitHub 被推送了——如果这是为了修复此问题,我稍后会尝试一下。

2 个赞

是的,这有望解决此问题。我在 3 个论坛上测试了此解决方案,新的查询速度总是快得多,并且不会堵塞服务器。
感谢您报告此问题,如果您仍然遇到问题,请告知我。

4 个赞

遗憾的是,即使进行了这些更改,我们仍然看到 PostAlert 作业花费的时间比以前长得多,并且在处理过程中完全挂起 Sidekiq 工作进程。 :frowning:

(我们有 1000 万多行用户数据,并且默认静音了一些类别,因此设置了大量的静音!)

与此同时,回滚最近修改此作业的三个提交并重新启动容器,作业就可以正常完成。

3 个赞

谢谢,我会再看看

我刚刚合并了另一个尝试改进此作业性能的请求:

我在几个实例上进行了测试,它们运行正常,但这些实例比你的要小。

如果此提交仍然导致失败,你能否提供 EXPLAIN ANALYSE 报告?生成它的脚本:

topic = Topic.last
user_option_sql_fragment =
  if SiteSetting.watched_precedence_over_muted
    <<~SQL
    INTERSECT
    SELECT user_id FROM user_options WHERE user_options.watched_precedence_over_muted IS false
    SQL
  else
    <<~SQL
    EXCEPT
    SELECT user_id FROM user_options WHERE user_options.watched_precedence_over_muted IS true
    SQL
  end
user_ids_sql = <<~SQL
  (
    SELECT user_id FROM category_users WHERE category_id = #{topic.category_id.to_i} AND notification_level = #{CategoryUser.notification_levels[:muted]}
    UNION
    SELECT user_id FROM tag_users tu JOIN topic_tags tt ON tt.tag_id = tu.tag_id AND tt.topic_id = #{topic.id} WHERE tu.notification_level = #{TagUser.notification_levels[:muted]}
    EXCEPT
    SELECT user_id FROM topic_users tus WHERE tus.topic_id = #{topic.id} AND tus.notification_level = #{TopicUser.notification_levels[:watching]}
  )
  #{user_option_sql_fragment}
SQL
sql = User.where("id IN (#{user_ids_sql})").to_sql

sql_with_index = <<~SQL
EXPLAIN ANALYZE #{sql};
SQL
result = ActiveRecord::Base.connection.execute("#{sql_with_index}")
puts sql_with_index
result.each do |r|
  puts r.values
end

这将帮助我找到缺失的索引或此查询的哪个部分如此缓慢。

3 个赞

此更改似乎已将 PostAlert 作业恢复到正常持续时间,并且_不会_挂起 Sidekiq 实例。太棒了!

3 个赞

此主题已在 3 天后自动关闭。不再允许回复。