Work with two separate redis instances with sidekiq?

前端 未结 3 501
借酒劲吻你
借酒劲吻你 2021-02-04 13:09

Good afternoon,

I have two separate, but related apps. They should both have their own background queues (read: separate Sidekiq & Redis processes). Howev

3条回答
  •  不要未来只要你来
    2021-02-04 13:32

    So one thing is that According to the FAQ, "The Sidekiq message format is quite simple and stable: it's just a Hash in JSON format." Emphasis mine-- I don't think sending JSON to sidekiq is too brittle to do. Especially when you want fine-grained control around which Redis instance you send the jobs to, as in the OP's situation, I'd probably just write a little wrapper that would let me indicate a Redis instance along with the job being enqueued.

    For Kevin Bedell's more general situation to round-robin jobs into Redis instances, I'd imagine you don't want to have the control of which Redis instance is used-- you just want to enqueue and have the distribution be managed automatically. It looks like only one person has requested this so far, and they came up with a solution that uses Redis::Distributed:

    datastore_config = YAML.load(ERB.new(File.read(File.join(Rails.root, "config", "redis.yml"))).result)
    
    datastore_config = datastore_config["defaults"].merge(datastore_config[::Rails.env])
    
    if datastore_config[:host].is_a?(Array)
      if datastore_config[:host].length == 1
        datastore_config[:host] = datastore_config[:host].first
      else
        datastore_config = datastore_config[:host].map do |host|
          host_has_port = host =~ /:\d+\z/
    
          if host_has_port
            "redis://#{host}/#{datastore_config[:db] || 0}"
          else
            "redis://#{host}:#{datastore_config[:port] || 6379}/#{datastore_config[:db] || 0}"
          end
        end
      end
    end
    
    Sidekiq.configure_server do |config|
      config.redis = ::ConnectionPool.new(:size => Sidekiq.options[:concurrency] + 2, :timeout => 2) do
        redis = if datastore_config.is_a? Array
          Redis::Distributed.new(datastore_config)
        else
          Redis.new(datastore_config)
        end
    
        Redis::Namespace.new('resque', :redis => redis)
      end
    end
    

    Another thing to consider in your quest to get high-availability and fail-over is to get Sidekiq Pro which includes reliability features: "The Sidekiq Pro client can withstand transient Redis outages. It will enqueue jobs locally upon error and attempt to deliver those jobs once connectivity is restored." Since sidekiq is for background processes anyway, a short delay if a Redis instance goes down should not affect your application. If one of your two Redis instances goes down and you're using round robin, you've still lost some jobs unless you're using this feature.

提交回复
热议问题