Rails Redis 命令超时请求

Rails Redis commands timing out requests

我们的应用程序偶尔会出现超时,这似乎是由于 Redis 造成的,但我并不完全确定。我们在一些工作中包含一个模块,以减少较重工作的重复:

module UniqueEnqueable

  require 'sidekiq/api'
  extend ActiveSupport::Concern

  included do
    before_enqueue do |job|
      throw(:abort) if already_queued_or_scheduled?(job.queue_name, job.arguments)
    end
  end

private

  def already_queued_or_scheduled?(queue_name, arguments)
    serialized_args = ActiveJob::Arguments.serialize(arguments)

    queued_jobs(queue_name).any? { |job| matches?(job, serialized_args) } ||
      scheduled_jobs.any? { |job| matches?(job, serialized_args) }
  end

  def matches?(job, serialized_args)
    active_job?(job) && class_and_args(job) == [self.class.to_s, serialized_args]
  end

  def active_job?(job)
    job.item['class'] == 'ActiveJob::QueueAdapters::SidekiqAdapter::JobWrapper'
  end

  def class_and_args(job)
    job.args[0].slice('job_class', 'arguments').values
  end

  def queued_jobs(queue_name)
    Sidekiq::Queue.new(queue_name)
  end

  def scheduled_jobs
    Sidekiq::ScheduledSet.new
  end

end

并且我们看到来自 redis 内部的超时错误似乎需要很长时间同步请求:

 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/connection/ruby.rb:68 :in `select`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/connection/ruby.rb:68 :in `rescue in _read_from_socket`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/connection/ruby.rb:64 :in `_read_from_socket`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/connection/ruby.rb:56 :in `gets`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/connection/ruby.rb:363 :in `read`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:265 :in `block in read`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:253 :in `io`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:264 :in `read`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:123 :in `block in call`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:234 :in `block (2 levels) in process`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:372 :in `ensure_connected`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:224 :in `block in process`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:309 :in `logging`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:223 :in `process`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis/client.rb:123 :in `call`
 [GEM_ROOT]/gems/scout_apm-2.4.20/lib/scout_apm/instruments/redis.rb:32 :in `block in call_with_scout_instruments`
 [GEM_ROOT]/gems/scout_apm-2.4.20/lib/scout_apm/tracer.rb:34 :in `instrument`
 [GEM_ROOT]/gems/scout_apm-2.4.20/lib/scout_apm/tracer.rb:44 :in `instrument`
 [GEM_ROOT]/gems/scout_apm-2.4.20/lib/scout_apm/instruments/redis.rb:31 :in `call_with_scout_instruments`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis.rb:1075 :in `block in llen`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis.rb:50 :in `block in synchronize`
 [PROJECT_ROOT]/vendor/ruby-2.5.1/lib/ruby/2.5.0/monitor.rb:226 :in `mon_synchronize`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis.rb:50 :in `synchronize`
 [GEM_ROOT]/gems/redis-4.0.3/lib/redis.rb:1074 :in `llen`
 [GEM_ROOT]/gems/sidekiq-5.2.3/lib/sidekiq/api.rb:242 :in `block in size`
 [GEM_ROOT]/gems/sidekiq-5.2.3/lib/sidekiq.rb:95 :in `block in redis`
 [GEM_ROOT]/gems/connection_pool-2.2.2/lib/connection_pool.rb:65 :in `block (2 levels) in with`
 [GEM_ROOT]/gems/connection_pool-2.2.2/lib/connection_pool.rb:64 :in `handle_interrupt`
 [GEM_ROOT]/gems/connection_pool-2.2.2/lib/connection_pool.rb:64 :in `block in with`
 [GEM_ROOT]/gems/connection_pool-2.2.2/lib/connection_pool.rb:61 :in `handle_interrupt`
 [GEM_ROOT]/gems/connection_pool-2.2.2/lib/connection_pool.rb:61 :in `with`
 [GEM_ROOT]/gems/sidekiq-5.2.3/lib/sidekiq.rb:92 :in `redis`
 [GEM_ROOT]/gems/sidekiq-5.2.3/lib/sidekiq/api.rb:242 :in `size`
 [GEM_ROOT]/gems/sidekiq-5.2.3/lib/sidekiq/api.rb:283 :in `each`
 [PROJECT_ROOT]/app/jobs/concerns/unique_enqueable.rb:17 :in `any?`
 [PROJECT_ROOT]/app/jobs/concerns/unique_enqueable.rb:17 :in `already_queued_or_scheduled?`
 [PROJECT_ROOT]/app/jobs/concerns/unique_enqueable.rb:8 :in `block (2 levels) in <module:UniqueEnqueable>`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:413 :in `instance_exec`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:413 :in `block in make_lambda`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:197 :in `block (2 levels) in halting`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:601 :in `block (2 levels) in default_terminator`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:600 :in `catch`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:600 :in `block in default_terminator`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:198 :in `block in halting`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:507 :in `block in invoke_before`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:507 :in `each`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:507 :in `invoke_before`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:106 :in `block in run_callbacks`
 [GEM_ROOT]/gems/activejob-5.1.6/lib/active_job/logging.rb:15 :in `block (3 levels) in <module:Logging>`
 [GEM_ROOT]/gems/activejob-5.1.6/lib/active_job/logging.rb:44 :in `block in tag_logger`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/tagged_logging.rb:69 :in `block in tagged`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/tagged_logging.rb:26 :in `tagged`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/tagged_logging.rb:69 :in `tagged`
 [GEM_ROOT]/gems/activejob-5.1.6/lib/active_job/logging.rb:44 :in `tag_logger`
 [GEM_ROOT]/gems/activejob-5.1.6/lib/active_job/logging.rb:14 :in `block (2 levels) in <module:Logging>`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:117 :in `instance_exec`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:117 :in `block in run_callbacks`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:135 :in `run_callbacks`
 [GEM_ROOT]/gems/activejob-5.1.6/lib/active_job/enqueuing.rb:47 :in `enqueue`
 [GEM_ROOT]/gems/activejob-5.1.6/lib/active_job/enqueuing.rb:18 :in `perform_later`
 [PROJECT_ROOT]/app/domains/responses/creator.rb:66 :in `call`
 [PROJECT_ROOT]/app/controllers/responses_controller.rb:68 :in `create`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_controller/metal/basic_implicit_render.rb:4 :in `send_action`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/abstract_controller/base.rb:186 :in `process_action`
 [GEM_ROOT]/gems/scout_apm-2.4.20/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb:72 :in `process_action`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_controller/metal/rendering.rb:30 :in `process_action`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/abstract_controller/callbacks.rb:20 :in `block in process_action`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:108 :in `block in run_callbacks`
 [GEM_ROOT]/gems/react-rails-2.4.7/lib/react/rails/controller_lifecycle.rb:31 :in `use_react_component_helper`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:117 :in `block in run_callbacks`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:135 :in `run_callbacks`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/abstract_controller/callbacks.rb:19 :in `process_action`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_controller/metal/rescue.rb:20 :in `process_action`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_controller/metal/instrumentation.rb:32 :in `block in process_action`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/notifications.rb:166 :in `block in instrument`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/notifications/instrumenter.rb:21 :in `instrument`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/notifications.rb:166 :in `instrument`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_controller/metal/instrumentation.rb:30 :in `process_action`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_controller/metal/params_wrapper.rb:252 :in `process_action`
 [GEM_ROOT]/gems/activerecord-5.1.6/lib/active_record/railties/controller_runtime.rb:22 :in `process_action`
 [GEM_ROOT]/gems/scout_apm-2.4.20/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb:83 :in `process_action`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/abstract_controller/base.rb:124 :in `process`
 [GEM_ROOT]/gems/actionview-5.1.6/lib/action_view/rendering.rb:30 :in `process`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_controller/metal.rb:189 :in `dispatch`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_controller/metal.rb:253 :in `dispatch`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/routing/route_set.rb:49 :in `dispatch`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/routing/route_set.rb:31 :in `serve`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/journey/router.rb:50 :in `block in serve`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/journey/router.rb:33 :in `each`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/journey/router.rb:33 :in `serve`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/routing/route_set.rb:844 :in `call`
 [GEM_ROOT]/gems/scout_apm-2.4.20/lib/scout_apm/instruments/rails_router.rb:29 :in `call_with_scout_instruments`
 [GEM_ROOT]/gems/scout_apm-2.4.20/lib/scout_apm/middleware.rb:17 :in `call`
 [GEM_ROOT]/gems/rack-attack-5.4.2/lib/rack/attack.rb:182 :in `call`
 [GEM_ROOT]/gems/rack-2.0.6/lib/rack/etag.rb:25 :in `call`
 [GEM_ROOT]/gems/rack-2.0.6/lib/rack/conditional_get.rb:38 :in `call`
 [GEM_ROOT]/gems/rack-2.0.6/lib/rack/head.rb:12 :in `call`
 [GEM_ROOT]/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:232 :in `context`
 [GEM_ROOT]/gems/rack-2.0.6/lib/rack/session/abstract/id.rb:226 :in `call`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/cookies.rb:613 :in `call`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/callbacks.rb:26 :in `block in call`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/callbacks.rb:97 :in `run_callbacks`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/callbacks.rb:24 :in `call`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/debug_exceptions.rb:59 :in `call`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/show_exceptions.rb:31 :in `call`
 [GEM_ROOT]/gems/railties-5.1.6/lib/rails/rack/logger.rb:36 :in `call_app`
 [GEM_ROOT]/gems/railties-5.1.6/lib/rails/rack/logger.rb:24 :in `block in call`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/tagged_logging.rb:69 :in `block in tagged`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/tagged_logging.rb:26 :in `tagged`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/tagged_logging.rb:69 :in `tagged`
 [GEM_ROOT]/gems/railties-5.1.6/lib/rails/rack/logger.rb:24 :in `call`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/remote_ip.rb:79 :in `call`
 [GEM_ROOT]/gems/request_store-1.4.1/lib/request_store/middleware.rb:19 :in `call`
 [GEM_ROOT]/gems/rack-timeout-0.5.1/lib/rack/timeout/core.rb:123 :in `block in call`
 [GEM_ROOT]/gems/rack-timeout-0.5.1/lib/rack/timeout/support/timeout.rb:19 :in `timeout`
 [GEM_ROOT]/gems/rack-timeout-0.5.1/lib/rack/timeout/core.rb:122 :in `call`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/request_id.rb:25 :in `call`
 [GEM_ROOT]/gems/rack-2.0.6/lib/rack/method_override.rb:22 :in `call`
 [GEM_ROOT]/gems/rack-2.0.6/lib/rack/runtime.rb:22 :in `call`
 [GEM_ROOT]/gems/activesupport-5.1.6/lib/active_support/cache/strategy/local_cache_middleware.rb:27 :in `call`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/executor.rb:12 :in `call`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/static.rb:125 :in `call`
 [GEM_ROOT]/gems/font_assets-0.1.14/lib/font_assets/middleware.rb:17 :in `block in call`
 [GEM_ROOT]/gems/font_assets-0.1.14/lib/font_assets/middleware.rb:40 :in `do_request`
 [GEM_ROOT]/gems/font_assets-0.1.14/lib/font_assets/middleware.rb:16 :in `call`
 [GEM_ROOT]/gems/rack-2.0.6/lib/rack/sendfile.rb:111 :in `call`
 [GEM_ROOT]/gems/actionpack-5.1.6/lib/action_dispatch/middleware/ssl.rb:68 :in `call`
 [PROJECT_ROOT]/config/middleware/null_byte_sanitizer.rb:9 :in `call`
 [GEM_ROOT]/gems/rack-utf8_sanitizer-1.6.0/lib/rack/utf8_sanitizer.rb:22 :in `call`
 [GEM_ROOT]/gems/scout_apm-2.4.20/lib/scout_apm/instruments/middleware_summary.rb:58 :in `call`
 [GEM_ROOT]/gems/railties-5.1.6/lib/rails/engine.rb:522 :in `call`
 [GEM_ROOT]/gems/railties-5.1.6/lib/rails/railtie.rb:185 :in `public_send`
 [GEM_ROOT]/gems/railties-5.1.6/lib/rails/railtie.rb:185 :in `method_missing`
 [GEM_ROOT]/gems/rack-2.0.6/lib/rack/static.rb:149 :in `call`
 [GEM_ROOT]/gems/puma-3.12.0/lib/puma/configuration.rb:225 :in `call`
 [GEM_ROOT]/gems/puma-3.12.0/lib/puma/server.rb:658 :in `handle_request`
 [GEM_ROOT]/gems/puma-3.12.0/lib/puma/server.rb:472 :in `process_client`
 [GEM_ROOT]/gems/puma-3.12.0/lib/puma/server.rb:332 :in `block in run`
 [GEM_ROOT]/gems/puma-3.12.0/lib/puma/thread_pool.rb:133 :in `block in spawn_thread`

关于为什么会发生这种情况的任何提示?很高兴根据需要添加更多信息。

API 页面是这样说的:

WARNING the API exposes some operations which are not scalable and should not be used in an automated fashion or in bulk as part of your application functionality. You should not be scanning through queues/sets and deleting jobs unless something has gone wrong and you need to repair data manually.

你想要这个:https://github.com/mperham/sidekiq/wiki/Ent-Unique-Jobs