redis_hash_store
redis_hash_store copied to clipboard
RedisHashStore extends ActiveSupport's RedisCacheStore to provide the ability to easily use Redis hashes for caching.
RedisHashStore
RedisHashStore extends ActiveSupport's RedisCacheStore to provide the ability to easily use Redis hashes for caching.
We decided to create this gem because:
- We were previously using
#delete_matchedwhich can have many performance issues at scale (See this similar issue at GitLab). #deleted_matcheddoesn't delete values from all the nodes in a Redis cluster.
Rails
Supported Rails versions are listed in Appraisals.
Installing
Install it yourself as:
$ gem install redis_hash_store
Or add it to your Gemfile:
gem 'redis_hash_store'
and then execute:
$ bundle
Configuration
All you need to do is add:
# config/production(development|test|staging|preview).rb
config.cache_store = :redis_hash_store, redis_cache_store_options
Usage
This gem simply adds new functionality to RedisCacheStore, so all existing logic in that class is not affected.
Here is a list of available methods:
#write_hash_value#read_hash_value#read_hash#delete_hash_value#delete_hash#fetch_hash_value
Examples
Let's imagine we need to store amount of Services for City.
#write_hash_value
city = "Riyadh"
coffee_shop_type = "coffee_shop"
restaurants_type = "restaurant"
coffee_shops_count = Service.where(type: coffee_shop_type, city: city).count
=> 250
restaurants_count = Service.where(type: restaurants_type, city: city).count
=> 340
Rails.cache.write_hash_value("#{city} counters", coffee_shop_type, coffee_shops_count)
=> 1
Rails.cache.write_hash_value("#{city} counters", restaurants_type, restaurants_count)
=> 1
#read_hash_value
Now it's accessible by:
Rails.cache.read_hash_value("#{city} counters", coffee_shop_type)
=> 250
Rails.cache.read_hash_value("#{city} counters", restaurants_type)
=> 340
#read_hash
Looks pretty easy, right? Maybe you're thinking: "What the difference?"
- You can access all records under the
"#{city} counters"hash
Rails.cache.read_hash("#{city} counters")
=> { "coffee_shop"=>250, "restaurant"=>340 }
#delete_hash_value
- You can easily remove every value under
"#{city} counters"
Rails.cache.delete_hash_value("#{city} counters", coffee_shop_type)
=> 1
#delete_hash
- You can also delete the entire
"#{city} counters"hash
Rails.cache.delete_hash("#{city} counters")
=> 1
#fetch_hash_value
- You can fetch needed value under
"#{city} counters"
Rails.cache.fetch_hash_value("#{city} counters", coffee_shop_type) do
Service.where(type: coffee_shop_type, city: city).count
end
=> 250
Rails.cache.fetch_hash_value("#{city} counters", coffee_shop_type, force: true) do
Service.where(type: coffee_shop_type, city: city).count * 2
end
=> 500
Benchmarks
indexes = 1..1_000_000
indexes.each do |index|
Rails.cache.write("some_data_#{index}", index)
Rails.cache.write_hash_value("some_data", index, index)
end
Benchmark.bm do |x|
x.report("delete_matched") { Rails.cache.delete_matched("some_data_*") }
x.report("delete_hash") { Rails.cache.delete_hash("some_data") }
end
user system total real
delete_matched 0.571040 0.244962 0.816002 (3.791056)
delete_hash 0.000000 0.000225 0.000225 (0.677891)
Contributing
Please see CONTRIBUTING.md.