From 9805fe1914f28693eb0be4f8c2d8377050dd2ebb Mon Sep 17 00:00:00 2001 From: Jacob Vosmaer Date: Thu, 18 Feb 2016 16:55:19 +0100 Subject: Use SCAN during 'rake cache:clear' This allows 'rake cache:clear' to delete millions of keys without choking. It requires Redis 2.8.0 or newer but we needed that already anyway. --- config/application.rb | 4 +++- lib/tasks/cache.rake | 19 +++++++++++++++---- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/config/application.rb b/config/application.rb index 1e9ec74cdbf..0d596ed22f5 100644 --- a/config/application.rb +++ b/config/application.rb @@ -6,6 +6,8 @@ I18n.config.enforce_available_locales = false Bundler.require(:default, Rails.env) module Gitlab + REDIS_CACHE_NAMESPACE = 'cache:gitlab' + class Application < Rails::Application # Settings in config/environments/* take precedence over those specified here. # Application configuration should go into files in config/initializers @@ -89,7 +91,7 @@ module Gitlab redis_config_hash[:path] = redis_uri.path end - redis_config_hash[:namespace] = 'cache:gitlab' + redis_config_hash[:namespace] = REDIS_CACHE_NAMESPACE redis_config_hash[:expires_in] = 2.weeks # Cache should not grow forever config.cache_store = :redis_store, redis_config_hash diff --git a/lib/tasks/cache.rake b/lib/tasks/cache.rake index 1728dda72cf..b262ea898d5 100644 --- a/lib/tasks/cache.rake +++ b/lib/tasks/cache.rake @@ -1,11 +1,22 @@ namespace :cache do + CLEAR_BATCH_SIZE = 1000 + REDIS_SCAN_START_STOP = '0' # Magic value, see http://redis.io/commands/scan + desc "GitLab | Clear redis cache" task :clear => :environment do - # Hack into Rails.cache until https://github.com/redis-store/redis-store/pull/225 - # is accepted (I hope) and we can update the redis-store gem. redis_store = Rails.cache.instance_variable_get(:@data) - redis_store.keys.each_slice(1000) do |key_slice| - redis_store.del(*key_slice) + cursor = [REDIS_SCAN_START_STOP, []] + loop do + cursor = redis_store.scan( + cursor.first, + match: "#{Gitlab::REDIS_CACHE_NAMESPACE}*", + count: CLEAR_BATCH_SIZE + ) + + keys = cursor.last + redis_store.del(*keys) if keys.any? + + break if cursor.first == REDIS_SCAN_START_STOP end end end -- cgit v1.2.1