Deleting Large Sets in Redis

To learn more about why deleting large objects is slow in Redis, read this quick overview

To delete a large set in Redis:

  1. Rename the key to a unique, namespaced key so that the set appears “deleted” to other Redis clients immediately.

  2. Incrementally delete members from the set in small batches until it is empty. By limiting the size of our delete commands, we ensure that we don’t block the server for too long.

Please note that the following code doesn’t gracefully handle Redis connection failures. If any Redis command fails and raises an exception, you’ll need to clean up manually.

Pseudo-code

# Rename the key
newkey = "gc:hashes:" + redis.INCR("gc:index")
redis.RENAME("my.set.key", newkey)

# Delete members from the set in batches of 100
cursor = 0
loop
  cursor, members = redis.SSCAN(newkey, cursor, "COUNT", 100)
  if size of members > 0
    redis.SREM(newkey, members)
  end
  if cursor == 0
    break
  end
end

Ruby

$redis = Redis.new

def delete_set(key)
  # Rename the key
  newkey = "gc:sets:#{$redis.incr("gc:index")}"
  $redis.rename(key, newkey)

  # Delete members from the set in batches of 100
  cursor = "0"
  loop do
    cursor, members = $redis.sscan(newkey, cursor, count: 100)
    $redis.srem(newkey, members) if members.size > 0
    break if cursor == "0"
  end
end

# Example:
#
#   delete_set("my.large.set")

Here are some example implementations of the above using background jobs in Ruby:

← Back to “Deleting Large Objects in Redis”

Last updated 09 Jun 2015. Originally written by Tyson Mote

← Back to docs