DEV Community

PikachuEXE
PikachuEXE

Posted on

[Redis] How To: Remove Redis Keys without TTL (in Ruby)

Background

Going to update our caching Redis Server config
to have maxmemory-policy become volatile-ttl
Doc: https://redis.io/topics/lru-cache

Since we use allkeys-lru before and have keys without TTL set (TTL key would return -1)

Those keys are required to be removed or they will never be evicted after config update

Code

::Rails.application.config.cache_store.redis.with do |c| cursor = "0" count = 0 # Fetch keys in batches using SCAN to avoid blocking the Redis server. begin cursor, keys = c.scan(cursor, count: 1000) all_key_count = c.dbsize puts("cursor: #{cursor}") puts("#{count}/#{all_key_count} keys scanned") keys_del = keys.each_with_object([]) do |key, keys_to_be_del| # Won't expire if !key.match?("sprockets|sidekiq|sessions") && c.ttl(key) == -1 keys_to_be_del.push(key) puts("to be deleted: <#{key}>") end end c.del(*keys_del) unless keys_del.empty? count += keys.size puts("#{count} keys scanned") end until cursor == "0" end 
Enter fullscreen mode Exit fullscreen mode

cursor, keys = c.scan(cursor, count: 1000)
SCAN is good, KEYS is bad

!key.match?("sprockets|sidekiq|sessions")
This is due to I am testing my code in development and the Redis server is used for sprockets caching, (rack?) sessions, sidekiq and caching
Feel free to remove it if you want

puts("to be deleted: <#{key}>")
Just another debugging code
I actually commented this code when running on production

c.del(*keys_del) unless keys_del.empty?
Time complexity: O(N)
You can choose to collect all keys then remove the keys in batches

Top comments (0)