进程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\])

猜你喜欢

转载自my.oschina.net/u/855913/blog/2243446
今日推荐