全局 + 1
# redis.rb
# redis conig
REDIS_CONFIG = YAML.load(File.open(Rails.root.join('config/redis.yml'))).symbolize_keys
default_config = REDIS_CONFIG[:default].symbolize_keys
redis_config = default_config.merge(REDIS_CONFIG[Rails.env.to_sym].symbolize_keys) if REDIS_CONFIG[Rails.env.to_sym]
$redis = Redis.new(redis_config)
# @see https://github.com/resque/redis-namespace
$namespaced_redis = Redis::Namespace.new(redis_config[:namespace], redis: $redis) if redis_config[:namespace]
# redis -> object
# @see https://github.com/nateware/redis-objects
# require 'connection_pool'
# Redis::Objects.redis = ConnectionPool.new(size: 5, timeout: 5) { $redis }
# To clear out the db before each test and development
begin
$redis.flushdb if Rails.env == 'test'
$redis.flushdb if Rails.env == 'development'
rescue Exception => e
p '-' * 20
p "Error trying with $redis.flushdb: #{e.message}"
p 'You may need to start the redis-server with `sudo service redis-server start`'
p 'If the redis-server is not installed, please `sudo apt-get install redis-server`.'
p 'You are not using linux? See you.'
p '-' * 20
rails_pid = Process.pid # thanks @rubyist518
cmd = "kill -SIGINT #{rails_pid}"
`#{cmd}`
end
# config/redis.yml
default:
host: localhost
port: 6379
driver: hiredis
development:
db: 0
namespace: app_development
test:
db: 1
namespace: app_test
production:
db: 2
host: 127.0.0.1
namespace: app_production
我的做法是全局变量
$redis = Redis.new
但是在使用多线程服务器的过程中,这样的做法出现了一些弊端。如果在多线程的服务器中使用 redis,并且用到了事务,那多个这种多个线程之间共享一个 client 的做法就出问题了。这时候就加上了ConnectionPool,每次使用 redis 都从连接池里拿独立的连接。
create_redis_proc = ->() {
Redis::Namespace.new("mtx_api/#{Mtx.env}", redis: Redis.new(url: Mtx::SETTINGS[:redis]))
}
$redis = ConnectionPool.new size: 16, timeout: 5, &create_redis_proc
当数据量大之后,redis 分布在多台机器上,这时候的 redis client 就采用 Redis::Distributed,内部提供一致性 hash 来处理负载,不过需要牺牲一些命令,例如 bitop。同样也是根据需求来决定是不是需要加上 connectionPool
redis_config = YAML.load_file(::Rails.root.to_s + '/config/redis.yml')
instances = Redis::Distributed.new(redis_config[Rails.env], driver: :hiredis)
$redis = Redis::Namespace.new("kecheng/#{Rails.env}", redis: instances)
#8 楼 @davidqhr Mike Perham 建议不要用 namespace http://www.mikeperham.com/2015/09/24/storing-data-with-redis/
#13 楼 @lanjingyu 如果你用多线程去执行 Class.instance,你会发现有锁等待的情况。你打开 ruby singleton 的代码,你会看到里面用了锁。