1. 程式人生 > >程序fork情況下使用redis的問題

程序fork情況下使用redis的問題

在專案中碰到一個問題,以前一直好的程式,增加了些程式碼,突然爆redis異常:


Tried to use a connection from a child process without reconnecting. You need to reconnect to Redis after forking.

意思很明確,就是你fork了程序,子程序中的redis連線沒法用了,要重連。但是為什麼呢。  

專案是rails的,一直沒有問題,有獨立跑的程序,這個程序會先載入rails環境,然後執行sneaker worker,錯誤就是在從sneaker worker裡面爆出來的,在裡面會使用配置在rails initializer裡處使用的快取工具。  

快取工具是同事寫的第三方的gem包app_cache,在initializer裡面初始化。

分析了前因後果,原因找到了,這個快取工具初始化的時候就會連線redis,獨立程序跑的時候就會載入並連線redis,然後這個程序fork子程序,子程序中如果繼續使用這個連線就報錯了。  

但是我直接在sneaker worker裡面重新設定快取工具的redis連線,依然報錯,這是為何,開啟app_cache的原始碼,發現其連線建立的程式碼是:


redis = Redis.current.nil? ? Redis.new(:url => options\[:url\]) : Redis.current

問題就出在Redis.current上面,因為是程序fork,子程序的Redis.current並不為nil,此時就會使用這個連線,但是很顯然這個連線是父程序建立的,這裡是無效的,如果要去使用,就會報開始那個異常。  

解決起來很簡單,改下app_cache,把連結建立程式碼改為如下:


redis = Redis.new(:url => options\[:url\])