程序fork情況下使用redis的問題
阿新 • • 發佈:2018-12-12
在專案中碰到一個問題,以前一直好的程式,增加了些程式碼,突然爆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\])