Navigation Menu

Skip to content

mrsool/redis_hash_store

Repository files navigation

RedisHashStore

RedisHashStore extends ActiveSupport's RedisCacheStore to provide the ability to easily use Redis hashes for caching.

We decided to create this gem because:

  1. We were previously using #delete_matched which can have many performance issues at scale (See this similar issue at GitLab).
  2. #deleted_matched doesn'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:

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?"

  1. You can access all records under the "#{city} counters" hash
Rails.cache.read_hash("#{city} counters")
=> { "coffee_shop"=>250, "restaurant"=>340 }

#delete_hash_value

  1. You can easily remove every value under "#{city} counters"
Rails.cache.delete_hash_value("#{city} counters", coffee_shop_type)
=> 1

#delete_hash

  1. You can also delete the entire "#{city} counters" hash
Rails.cache.delete_hash("#{city} counters")
=> 1

#fetch_hash_value

  1. 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.

About

RedisHashStore extends ActiveSupport's RedisCacheStore to provide the ability to easily use Redis hashes for caching.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 4

  •  
  •  
  •  
  •  

Languages