2011-10-05 83 views
7

我正在嘗試編寫一個函數,嘗試使用默認TCP設置連接到Redis,如果失敗,則嘗試通過unix套接字連接到Redis。我的意圖是在我的所有系統上都有一個連接腳本,其中一些使用TCP和其他使用套接字的連接腳本。無法從Redis拒絕連接救援

但是,我似乎無法從失敗的TCP連接中解救出來。這是我的測試腳本。

require "redis" 

def r 
    begin 
    $redis ||= Redis.new 
    rescue 
    $redis = Redis.new(:path => "/tmp/redis.sock") 
    end 
end 

puts "You have #{r.keys.count} redis keys" 

rescue塊永遠不會執行,而是引發異常。這是這個腳本的輸出。

 
/usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:236:in `rescue in establish_connection': Connection refused - Unable to connect to Redis on 127.0.0.1:6379 (Errno::ECONNREFUSED) 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:222:in `establish_connection' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:23:in `connect' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:247:in `ensure_connected' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:137:in `block in process' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:206:in `logging' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:136:in `process' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis/client.rb:46:in `call' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis.rb:246:in `block in keys' 
    from /usr/local/rvm/rubies/ruby-1.9.2-p290/lib/ruby/1.9.1/monitor.rb:201:in `mon_synchronize' 
    from /usr/local/rvm/gems/ruby-1.9.2-p290/gems/redis-2.2.2/lib/redis.rb:245:in `keys' 
    from scripts/redis.rb:11:in `<main>' 

我已驗證Redis.new(:path => "/tmp/redis.sock")按預期工作。我試圖通過使用rescue Errno::ECONNREFUSED來解決我的救援塊問題,但無濟於事。我不知道爲什麼我無法捕捉到這個例外。

任何想法?

回答

5

事實證明,撥打Redis.new時不會引發異常。在連接對象上的某些方法(在本例中爲Redis#keys)被調用之前,異常不會被拋出。這個修改後的連接函數似乎有竅門。

require "redis" 

def r 
    begin 
    $redis ||= Redis.new 
    $redis.inspect # needed to know if connection failed 
    rescue 
    $redis = Redis.new(:path => "/tmp/redis.sock") 
    end 
    $redis 
end 
+4

我知道這是一個古老的答案,但只是爲了能夠解釋爲什麼發生這種情況略顯清淡的。 Redis連接延遲加載,因此只有在發出第一個命令後才能連接。 –

+0

看起來你可以做的最好的事情就是調用'$ redis.ping'。正如在另一個答案中指出的那樣,'.inspect'不夠好,'.keys'會檢索redis中的所有項目,這會讓你等待很長時間(取決於redis中的條目數)並佔用大量內存不能被垃圾收集(因爲它沒有分配給任何變量)。 – lucke84

2

我發現$redis.inspect實際上並沒有行使REDIS連接。我用$redis.keys替換它,並正確拋出異常。請注意,我在Heroko上運行,它傳入環境變量。然後我在整個應用程序中使用一個常量REDIS

在我的配置/初始化/ redis.rb:

uri = URI.parse(ENV['REDISTOGO_URL']) 
begin 
    redis ||= Redis.new(:host => uri.host, :port => uri.port, :password => uri.password) 
    redis.keys # needed to know if connection failed 
    REDIS = redis 
rescue 
    puts("Redis not loaded on #{uri.port}") 
    REDIS = nil 
end 
+0

'$ redis.inspect'可能不是一個好辦法,因爲並非所有的redis gems都會連接到這個調用。 '$ redis.keys'雖然會嘗試檢索所有的redis鍵,如果你有一個非常大的數據庫,它將會窒息。我會改用'$ redis.info'或'$ redis.get(「some-key-that-does-or-doesn't-exist」)''。這些命令仍然會傳遞給redis服務器,而不會試圖挽回世界。 –