Skip to content

Instantly share code, notes, and snippets.

@rpond-pa
Forked from brasic/clear_redis_script.rb
Last active August 29, 2015 14:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rpond-pa/18f0fbf7381b950aa5c3 to your computer and use it in GitHub Desktop.
Save rpond-pa/18f0fbf7381b950aa5c3 to your computer and use it in GitHub Desktop.
#!/usr/bin/env ruby
require 'redis'
# Clear a large number of keys matching a pattern using SCAN and
# pipelining to avoid killing the server.
class ClearKeys
def initialize(pattern, host='localhost', postprocess_pattern=nil)
@redis = Redis.new(host: host)
@pattern = pattern
@postprocess_pattern = postprocess_pattern
end
def call
puts db_info
puts "Clearing #{@pattern}"
keys, time = timed { get_keys }
puts "#{keys.size} matching keys found in #{time} sec."
keys = postprocess(keys)
puts "#{keys.size} matching keys after postprocessing"
unless ENV['DRY_RUN']
puts "deleting..."
_, time = timed { clear(keys) }
puts "Deleted in #{time} sec."
puts db_info
end
end
def clear(keys)
keys.each_slice(500) do |chunk|
@redis.pipelined do
chunk.each do |key|
@redis.del key
end
end
end
end
def postprocess(keys)
return keys if !@postprocess_pattern
regex = Regexp.new(@postprocess_pattern)
keys.select{ |k| regex.match k }
end
def db_info
"DB stats: #{@redis.info['db0']}"
end
def timed(&block)
start = Time.now
result = block.call
elapsed = (Time.now - start).round(2)
return [result, elapsed]
end
def get_keys
@redis.scan_each(match: @pattern, count:1000).to_a
end
end
if ARGV[0].nil?
puts "Syntax: #{$0} REDIS_PATTERN [HOST] [REGEX]"
else
ClearKeys.new(ARGV[0], ARGV[1], ARGV[2]).call
end
@rpond-pa
Copy link
Author

Requires redis 2.8. The scan command is not present on earlier versions of Redis.

@rpond-pa
Copy link
Author

# clear redis keys matching redis-globbed pattern `*:ovc:*` that
# also have a number at the end.  Perform dry run first.
#
$ DRY_RUN=true ./clear_redis_script.rb *:ovc:* localhost ':\d+$'
DB stats: keys=329,expires=329,avg_ttl=936664199
Clearing *:ovc:*
5 matching keys found in 0.0 sec.
2 matching keys after postprocessing

# perform actual wipe
#
$ ./clear_redis_script.rb *:ovc:* localhost ':\d+$'
DB stats: keys=329,expires=329,avg_ttl=936552482
Clearing *:ovc:*
5 matching keys found in 0.0 sec.
2 matching keys after postprocessing
deleting...
Deleted in 0.0 sec.
DB stats: keys=327,expires=327,avg_ttl=936517877


# delete all keys matching a globbed pattern without
# extra postprocessing
#
$ ./clear_redis_script.rb *:src2:* localhost
DB stats: keys=327,expires=327,avg_ttl=936517870
Clearing *:src2:*
327 matching keys found in 0.0 sec.
327 matching keys after postprocessing
deleting...
Deleted in 0.01 sec.
DB stats:

@rpond-pa
Copy link
Author

Updating the test for the proper cache clear run. Removed the ':\d+% check. Also added noglob to run in a z-shell.

At production, we will replace localhost with the hostname for our cache server.

DRY_RUN=true noglob ./clear_redis_script.rb *:ovc:* localhost
DRY_RUN=true noglob ./clear_redis_script.rb *:src2:* localhost
noglob ./clear_redis_script.rb *:ovc:* localhost
noglob ./clear_redis_script.rb *:src2:* localhost

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment