Skip to content

Instantly share code, notes, and snippets.

@dbernheisel
Last active October 8, 2019 17:34
Show Gist options
  • Save dbernheisel/33e69acc1d2d27b0a1c61c7e55953822 to your computer and use it in GitHub Desktop.
Save dbernheisel/33e69acc1d2d27b0a1c61c7e55953822 to your computer and use it in GitHub Desktop.
Expire redis keys en-masse
#!/bin/bash
# Mass expire Redis keys using the SCAN command so it doesn't block or overwhelm
# memory
# Usage example: ./mass-expire-redis.sh "127.0.0.1" "6379" "mykey:*" "300"
# Logs to ./filename.ext.log
if [ $# -ne 4 ]; then
echo "Usage: $0 <host> <port> <pattern> <expiration>"
exit 1
fi
HOST=$1; shift
PORT=$1; shift
PATTERN=$1; shift
TTL=$1; shift
COUNT=100
CURSOR=0
TOTAL=0
LOG="$0.log"
expire_keys() {
read -rd ' ' CURSOR KEYS <<< \
"$(redis-cli -h "$HOST" -p "$PORT" SCAN $CURSOR MATCH "$PATTERN" COUNT $COUNT)"
KEYS_COUNT=$(wc -l <<< "$KEYS")
TOTAL=$(( TOTAL + KEYS_COUNT ))
printf "Total %s \t | Page of %s: " "$TOTAL" "$KEYS_COUNT"
PROCESSED=0
ALREADY_TTL=0
while read -r KEY; do
[ "$KEY" = "" ] && continue
CURRENT_TTL="$(redis-cli -h "$HOST" -p "$PORT" <<< "TTL $KEY" | awk '{print $NF}')"
if [ "$CURRENT_TTL" = "-1" ]; then
EXPIRE_COMMAND="EXPIRE $KEY $TTL"
echo "$EXPIRE_COMMAND" >> "$LOG"
redis-cli -h "$HOST" -p "$PORT" <<< "$EXPIRE_COMMAND" &>> "$LOG"
(( PROCESSED++ ))
else
(( ALREADY_TTL++ ))
fi
done <<< "$KEYS"
printf "Set TTL for %s, %s already set\n" "${PROCESSED-0}" "${ALREADY_TTL-0}"
if [ "$CURSOR" -ne 0 ]; then
expire_keys
fi
}
date > "$LOG"
expire_keys
@dbernheisel
Copy link
Author

dbernheisel commented Oct 7, 2019

testing:

$ for i in {1..1000}; do
  redis-cli <<< "SET mykey:$i wat" &>/dev/null
done
$ ./mass-expire-redis.sh "127.0.0.1" "6379" "mykey:*" "300"
Total 77         | Page of 77: Set TTL for 77, 0 already set
Total 163        | Page of 86: Set TTL for 86, 0 already set
Total 252        | Page of 89: Set TTL for 89, 0 already set
Total 334        | Page of 82: Set TTL for 82, 0 already set
Total 419        | Page of 85: Set TTL for 85, 0 already set
Total 507        | Page of 88: Set TTL for 88, 0 already set
Total 587        | Page of 80: Set TTL for 80, 0 already set
Total 662        | Page of 75: Set TTL for 75, 0 already set
Total 743        | Page of 81: Set TTL for 81, 0 already set
Total 822        | Page of 79: Set TTL for 79, 0 already set
Total 912        | Page of 90: Set TTL for 90, 0 already set
Total 991        | Page of 79: Set TTL for 79, 0 already set
Total 1000       | Page of 9: Set TTL for 9, 0 already set
$ ./mass-expire-redis.sh "127.0.0.1" "6379" "mykey:*" "300"
Total 77         | Page of 77: Set TTL for 0, 77 already set
Total 163        | Page of 86: Set TTL for 0, 86 already set
Total 252        | Page of 89: Set TTL for 0, 89 already set
Total 334        | Page of 82: Set TTL for 0, 82 already set
Total 419        | Page of 85: Set TTL for 0, 85 already set
Total 507        | Page of 88: Set TTL for 0, 88 already set
Total 587        | Page of 80: Set TTL for 0, 80 already set
Total 662        | Page of 75: Set TTL for 0, 75 already set
Total 743        | Page of 81: Set TTL for 0, 81 already set
Total 822        | Page of 79: Set TTL for 0, 79 already set
Total 912        | Page of 90: Set TTL for 0, 90 already set
Total 991        | Page of 79: Set TTL for 0, 79 already set
Total 1000       | Page of 9: Set TTL for 0, 9 already set
$ redis-cli --scan --pattern mykey:* | xargs redis-cli unlink
(integer) 1000
$ ./mass-expire-redis.sh "127.0.0.1" "6379" "mykey:*" "300"
$ echo $?
0

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