Ruby Unicorn 多进程下单例类的数据同步问题?

lissdy · 2016年07月27日 · 最后由 martin91 回复于 2016年08月25日 · 2607 次阅读

问题是这样的,在项目中有一个方法我使用了单例来动态的写入读取数据,在使用 Unicorn 部署的时候,当 worker_processes 数目大于 1 时,即多个 Unicorn 进程,因为进程之间内存不共享,当对该值进行写入操作之后,写入操作只在处理此次请求的进程中生效,而其他进程中的数据仍然为写入操作之前的旧值。 为了确保 Unicorn 多进程下数据的一致性,目前想到的解决方案是:

  1. 持久化数据
  2. 锁机制,数据在一个进程下被更新后,加入锁;其他进程读到锁后重新刷入新数据

但是以上两种都没有很好的解决问题,想麻烦问下各位 Unicorn 或者 Ruby 可否进行进程之间的通信,解决单例类在多进程中不一致的问题。

附 Unicorn 配置信息:

worker_processes 2
working_directory "/var/lib/jenkins/workspace/XXX/" 
listen "/var/tmp/.XXX.sock", :backlog => 512
listen 3002, :tcp_nopush => true
timeout 180

pid "/var/tmp/XXX.pid"    
stderr_path "/var/tmp/XXX.stderr.log"   
stdout_path "/var/tmp/XXX.stdout.log"   

preload_app true

GC.respond_to?(:copy_on_write_friendly=) and
  GC.copy_on_write_friendly = true
check_client_connection false

before_fork do |server, worker|
  ENV["LOG_LEVEL"]="debug"
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.connection.disconnect!
end

after_fork do |server, worker|
  defined?(ActiveRecord::Base) and
    ActiveRecord::Base.establish_connection
end

一般直接用 redis 来共享多进程数据。redis 可保证原子读与写。

native extension

使用进程外的内存作为交换器,例如 Memcached, Redis 等

他们都是 Atomic(原子性操作,也就是你想要的锁机制)或有 Atomic 的功能:

然后,Redis 是可以持久化的,你还可以用 redis-objects 更简单的使用。

redis 或者 memcached 都是正解,没必要自己再去折腾进程间通信的问题。

需要 登录 后方可回复, 如果你还没有账号请 注册新账号