Blog Post

Azure PaaS Blog
16 MIN READ

Redis Keys Statistics

LuisFilipe's avatar
LuisFilipe
Icon for Microsoft rankMicrosoft
Jan 21, 2026

Collect Redis Key TTL and Key sizes

Redis Keys statistics including Key Time-to-Live (TTL) statistics and Key sizes are useful for troubleshooting cache usage and performance, from client side.

Key Time-to-Live (TTL):


TTL may have impact on memory usage and memory available on Redis services.

Data Loss on Redis services may happened unexpectedly due to some issue on backend, but may also happen due to Memory eviction policy, or Time-to-Live (TTL) expired.
Memory eviction policy may remove some keys from Redis service, but only when used capacity (the space used by Redis keys) reach 100% on memory available.

Not having any unexpected issue on Redis backend side or not reaching the maximum memory available, the only reason for having some keys removed from cache is due to TTL value.

  • TTL may not be defined at all, and in that case the key remains in the cache forever (persistent)
  • TTL can be set while setting a new key 
  • TTL can be set / re-set later after key creation

TTL is defined in seconds or milliseconds, or with a negative value:

  • -1, the key exists but has no expiration (it’s persistent); this happens when the TTL was not defined or it was removed using PERSIST command
  • -2, if the key does not exist.
  • any other value

Related commands:

  • SET key1 value1 EX 60 - defines TTL as 60 seconds
  • SET key1 value1 PX 60000 - defines TTL as 60000 milliseconds (60 seconds)
  • EXPIRE key1 60 - Set a timeout of 60 seconds on key1
  • TTL key1 - returns the current TTL value, in seconds
  • PTTL key1 - returns the current TTL value, in milliseconds
  • PERSIST key1 removes TTL from that key and make the key persistent

Notes:

  • TTL counts down in real time, but Redis expiration is lazy + active, so exact timing isn’t guaranteed to the millisecond.
  • A TTL of 0 is basically a race condition, that usually are not seen, it because the key expires immediately.
  • EXPIRE key 0 deletes the key right away.

There is no guarantee the deletion happens exactly at expiration time. Redis lazy + active expiration means the key is checked only when someone touches it (lazy), but to avoid memory filling up with expired junk, Redis also runs a background job to periodically scan a subset of keys and delete the expired ones (active). So, some expired keys may survive a bit longer, not accessible anymore but still im memory.

Example Redis lazy:

  • at 11:59:00 SET key1 value1 EX 60 - 60 seconds expiration time
  • key1 expires at 12:00:00
  • no one accesses it until 12:00:05 - when someone try to access key1 at 12:00:05, Redis identify the key1 expired and delete it.

Example Redis active:

  • for the same key1, after 12:00:00. if during the periodically background job Redis scan the subset of keys containing key1, that key1 will be actively deleted.

For that reason, we may see some higher memory usage than the real memory used by active keys in the cache.
For more information about Redis commands, check Redis Inc - Commands

 

Key Sizes:


Large key value sizes in the cache, may have high impact on Redis performance.
Redis service is designed to 1KB response size, and Microsoft recommends to use up to 100KB on Azure Redis services, to get a better performance.
Redis response size may not be exactly the same as key size, as Response size is the sum of the response from each operation sent to Redis.
While the response size can be the size of only one key requested (like GET), we can see very often response size being a sum of more than one key, as result of multikey operations (like MGET and others).

The scope of this article is the focus on each key size; so, we will not discuss on this article the implications of multikey commands.


By design Redis service is a single thread system per shard, and this is not a Microsoft/Azure limitation but a Redis design feature.
To be very quick on processing requests, Redis is optimized to work and process small keys, and for that is more efficient using a single thread instead of the need of context switching.
In a multi threaded system, context switching happens when the processor stops executing one thread and starts executing another.
When that happens, the OS saves the current thread’s state (registers, program counter, stack pointer, etc.) and restores the state of the next thread. 
To save time on that process, Redis service is designed to run in a single thread system.


Due to the single thread nature, all operations sent to Redis service, are waiting in a queue to be processed.
To minimize latency, all keys must remain small so they can be processed efficiently and responses can be transmitted to the client quickly over the network.

For that reason, it's important to understand the key sizes we have on our Redis service, and maintain all keys as small as possible.


Scripts Provided


To help on identifying some specific TTL values and Keys sizes in a Redis cache, two solutions are provided below:

     1. Get Key statistics - that scans all cache and return only the amount of Redis keys with: 

    • Number of keys with TTL no set
    • Number of keys with TTL higher or equal to a user defined TTL threshold
    • Number of keys with TTL lower than a user defined TTL threshold
    • Number of keys with value size higher or equal than a user defined Size threshold
    • Number of keys with value size lower than a user defined Size threshold
    • Total number of keys in the cache.
    • It also includes start and end time, and the total time spent on the keys scan.

     2. List Key Names - this script returns a list of Redis Keys names, based on parameters provided:

    • No TTL set, or
    • TTL higher or equal to a user defined TTL threshold, or
    • TTL lower than to a user defined TTL threshold
    • Key value size higher or equal than a user defined Size threshold, or
    • Key value size lower than a user defined Size threshold
    • Total number of keys in the cache
    • It also includes start and end time, and the total time spent on the keys scan.

 

WARNING:

Due to the need to read all keys in the cache, both solutions can cause high workload on Redis side, specially for high datasets on the cache, with high number of keys.
Both solutions are using LUA script that runs on Redis side, and depending on the amount of keys in the cache, may block all other commands to be processed, while the script is running.
The duration time on the output from each script run, may help to identify the impact of the scripts to run.
Run it carefully and do some tests first on your developing environment, before using in a production.

 

1- Get Key statistics

To get Redis key statistics, we use Linux Bash shell and Redis-cli tool to run LUA script on Redis side, to get TTL values and sizes from each key.
This solution is very fast, but needs to scan all keys in the cache during the LUA script run.
This may block Redis to process other requests, due to the single-thread nature of Redis service.

The below script scans all cache and return only the amount of Redis keys with: 

    • Number of keys with TTL no set
    • Number of keys with TTL higher or equal to a user defined TTL threshold
    • Number of keys with TTL lower than a user defined TTL threshold
    • Number of keys with value size higher or equal than a user defined Size threshold
    • Number of keys with value size lower than a user defined Size threshold
    • Total number of keys in the cache.
    • It also includes start and end time, and the total time spent on the keys scan.

Output:

========================================================
Scanning number of keys with TTL threshold 100 Seconds, and Key size threshold 500 Bytes
Start time: dd-mm-YY 18:12:15
-----------------------
Total keys scanned: 1227
------------
TTL not set : 2
TTL >= 100 seconds: 1225
TTL < 100 seconds: 0
TTL invalid/error : 0
Non existent key : 0
------------
Keys with Size >= 500 Bytes: 1225
Keys with Size < 500 Bytes: 2
Keys with invalid Size : 0
------------------------
End time: dd-mm-YY 19:12:16
Duration : 0 days 00:00:00.630
========================================================

How to run:

  • create the below getKeyStats.sh and getKeyStats.lua files on same folder, on your Linux environment (Ubuntu 20.04.6 LTS used)
  • give permissions to run Shell script, with command chmod 700 getKeyStats.sh
  • Call the script using the syntax:

./getKeyStats.sh host password [port] [ttl_threshold] [size_threshold]

Script parameters:

  •  host (mandatory) : the URI for the cache
  •  password (mandatory) : the Redis access key from the cache
  •  port (optional - default 10000) : TCP port used to access the cache
  •  ttl_threshold (optional - default 600 - 10 minutes) : Key TTL threshold (in seconds) to be used on the results (use -1 to 1 to get Keys with no TTL set)
  •  size_threshold (optional - default 102400 - 100KB) : Key Size threshold to be used on the results

Tested with:

  • Ubuntu 20.04.6 LTS
  • redis-cli -v
        redis-cli 7.4.2
  • Redis services:
    • Azure Managed Redis Balanced B0 OSSMode
    • Azure Cache for Redis Standard C1

getKeyStats.sh

#!/usr/bin/env bash
#============================== LUA script version =================
# Linux Bash Script to get statistics from Redis Keys TTL values and Key value sizes
# It returns the Number of:
#   - keys with TTL no set
#   - keys with TTL higher or equal to TTL_treshold
#   - keys with TTL lower TTL_threshold
#   - keys with value size higher or equal than Size_threshold
#   - keys with value size lower than Size_threshold
#   - total number of keys in the cache.
#-------------------------------------------------------
# WARNING:
# It uses LUA script to run on Redis server side.
# Use it carefully, during low Redis workoads.
# Do your tests first on a Dev environment, before use it on production.
#-------------------------------------------------------
# It requires :
#    redis-cli v7 or above
#--------------------------------------------------------
# Usage:
# getRedisTTL.sh <cacheuri> <cacheaccesskey> [<accessport>(10000)] [<ttl_treashold>(600)] [<size_threshold>(102400)]
#========================================================

#------------------------------------------------------
# To use non-ssl port requites to remove --tls parameter from Redis-cli command below
#------------------------------------------------------

# Parameters
REDIS_HOST="${1:?Usage: $0 <host> <password> [port] [ttl_threshold] [Size_Threshold]}"
REDISCLI_AUTH="${2:?Usage: $0 <host> <password> [port] [ttl_threshold] [Size_Threshold]}"
REDIS_PORT="${3:-10000}"             # 10000 / 6380 / 6379
REDIS_TTL_THRESHOLD="${4:-600}"      # 10 minutes
REDIS_SIZE_THRESHOLD="${5:-102400}"  # 100KB

# Port number must be numeric
if ! [[ "$REDIS_PORT" =~ ^[0-9]+$ ]]; then
  echo "ERROR: Redis Port must be numeric"
  exit 1
fi

# TTL threshold must be numeric
if ! [[ "$REDIS_TTL_THRESHOLD" =~ ^[0-9]+$ ]]; then
  echo "ERROR: TTL threshold must be numeric"
  exit 1
fi

# Size threshold must be numeric
if ! [[ "$REDIS_SIZE_THRESHOLD" =~ ^[0-9]+$ ]]; then
  echo "ERROR: Size threshold must be numeric"
  exit 1
fi

echo ""

echo "========================================================"
echo "Scaning number of keys with TTL threshold $REDIS_TTL_THRESHOLD Seconds, and Key size threshold $REDIS_SIZE_THRESHOLD Bytes"

# Start time
start_ts=$(date +%s.%3N)
echo "Start time: $(date "+%d-%m-%Y %H:%M:%S")"
echo "------------------------"

echo ""

# Procesing
result=$(redis-cli \
  -h "$REDIS_HOST" \
  -a "$REDISCLI_AUTH" \
  -p "$REDIS_PORT" \
  --tls \
  --no-auth-warning \
  --raw \
  --eval getKeyStats.lua , "$REDIS_TTL_THRESHOLD" "$REDIS_SIZE_THRESHOLD" \
  | tr '\n' ' ')

read no_ttl nonexist ttl_high ttl_low ttl_invalid size_high size_low size_nil total <<< "$result"

if [[ $result == ERR* ]]; then
  echo "Redis Lua error:"
  echo "$result"
else
  echo "Total keys scanned: $total"
  echo "------------"
  echo "TTL not set       : $no_ttl"
  echo "TTL >= $REDIS_TTL_THRESHOLD seconds: $ttl_high"
  echo "TTL <  $REDIS_TTL_THRESHOLD seconds: $ttl_low"
  echo "TTL invalid/error : $ttl_invalid"
  echo "Non existent key  : $nonexist"
  echo "------------"
  echo "Keys with Size >= $REDIS_SIZE_THRESHOLD Bytes: $size_high"
  echo "Keys with Size <  $REDIS_SIZE_THRESHOLD Bytes: $size_low"
  echo "Keys with invalid Size        : $size_nil"
fi

echo ""
echo "------------------------"
end_ts=$(date +%s.%3N)
echo "End time: $(date "+%d-%m-%Y %H:%M:%S")"

# Duration - Extract days, hours, minutes, seconds, milliseconds
duration=$(awk "BEGIN {print $end_ts - $start_ts}")
days=$(awk "BEGIN {print int($duration/86400)}")
hours=$(awk "BEGIN {print int(($duration%86400)/3600)}")
minutes=$(awk "BEGIN {print int(($duration%3600)/60)}")
seconds=$(awk "BEGIN {print int($duration%60)}")
milliseconds=$(awk "BEGIN {printf \"%03d\", ($duration - int($duration))*1000}")
echo "Duration  : ${days} days $(printf "%02d" "$hours"):$(printf "%02d" "$minutes"):$(printf "%02d" "$seconds").$milliseconds"
echo "========================================================"

getKeyStats.lua

local ttl_threshold = tonumber(ARGV[1])
local size_threshold = tonumber(ARGV[2])
local cursor = "0"

-- Counters
local no_ttl = 0
local nonexist = 0
local ttl_high = 0
local ttl_low = 0
local ttl_invalid = 0
local size_high = 0
local size_low = 0
local size_nil = 0
local total = 0

repeat
  local scan = redis.call("SCAN", cursor, "COUNT", 1000)
  cursor = scan[1]
  local keys = scan[2]
  for _, key in ipairs(keys) do

      local ttl = redis.call("TTL", key)
      local size = redis.call("MEMORY","USAGE", key)
      total = total + 1

      if ttl == -1 then
        no_ttl = no_ttl + 1
      elseif ttl == -2 then
        nonexist = nonexist + 1
      elseif type(ttl) ~= "number" then
        ttl_invalid = ttl_invalid + 1
      elseif ttl >= ttl_threshold then
        ttl_high = ttl_high + 1
      else
        ttl_low = ttl_low + 1
      end

      if size == nil then
        size_nil = size_nil + 1
      elseif size >= size_threshold then
        size_high = size_high + 1
      else
        size_low = size_low + 1
      end

  end
until cursor == "0"

return {
  no_ttl,
  nonexist,
  ttl_high,
  ttl_low,
  ttl_invalid,
  size_high,
  size_low,
  size_nil,
  total
}

 

Performance:

Redis service used: Azure Managed Redis - Balanced B0 - OSSMode

Scanning number of keys with TTL threshold 600 Seconds, and Key size threshold 102400 Bytes

Total keys scanned: 46161

TTL not set : 0
TTL >= 600 seconds: 46105
TTL < 600 seconds: 56
TTL invalid/error : 0
Non existent key : 0

Keys with Size >= 102400 Bytes: 0
Keys with Size < 102400 Bytes: 46161
Keys with invalid Size : 0

Duration : 0 days 00:00:00.602
# ------------------

Redis service used: Azure Cache for Redis - Standard - C1

Scanning number of keys with TTL threshold 100 Seconds, and Key size threshold 500 Bytes

Total keys scanned: 1227

TTL not set : 2
TTL >= 100 seconds: 1225
TTL < 100 seconds: 0
TTL invalid/error : 0
Non existent key : 0

Keys with Size >= 500 Bytes: 1225
Keys with Size < 500 Bytes: 2
Keys with invalid Size : 0

Duration : 0 days 00:00:00.630
# ------------------

WARNING:
The above scripts uses LUA script, that runs on Redis side, and may block you normal workload.
Use it carefully when have a large number of keys in the cache, and during low workload times.

 

2 - List Key Names

Once we identify some amount of keys in the cache with some specific threshold, we may want to list that key names.
The below script can help on that, and returns a list of Redis Keys names with:

  • No TTL set
  • TTL higher or equal to a user defined TTL threshold
  • TTL lower than to a user defined TTL threshold
  • Key value size higher or equal than a user defined Size threshold
  • Key value size lower than a user defined Size threshold
  • Total number of keys in the cache
  • It also includes start and end time, and the total time spent on the keys scan.

Output:

List all key names with TTL above 100 Seconds, and Key size larger 500 Bytes

Start time: dd-mm-YY 18:30:22
------------------------
1) "--------------------------------------"
2) "Key_1787_1022: TTL: 461837 seconds, Size: 1336 Bytes"
            (...)
1551) "Key_1173_1022: TTL: 389795 seconds, Size: 1336 Bytes"
1552) "--------------------------------------"
1553) "Scan completed."
1554) "Total of 1550 keys scanned."
1555) "1225 keys found with TTL >= 100 seconds, and size larger than 500 Bytes"
1556) "--------------------------------------"
End time: dd-mm-YY 18:30:22
Duration : 0 days 00:00:00.545
========================================================

How to run:

  • create the below listKeys.sh file under some folder, on your Linux environment (Ubuntu 20.04.6 LTS used)
  • give permissions to run Shell script, with command chmod 700 listKeys.sh
  • Call the script using the syntax:

./listKeys.sh host password [port] [+/-][ttl_threshold] [+/-][size_threshold]

Script parameters:

  • host (mandatory) : the URI for the cache
  • password (mandatory) : the Redis access key from the cache
  • port (optional - default 10000) : TCP port used to access the cache
  • [+/-] (optional) before ttl_threshold: indicates if we want return keys with lower "-", or higher TTL "+" or "" than ttl_threshold 

  • ttl_threshold (optional - default 600 - 10 minutes) : Key TTL threshold (in seconds) to be used on the results (use -1 to get Keys with no TTL set)
  • [+/-] (optional) before size_threshold: indicates if we want return keys with small size "-", or large size "+" or "" than size_threshold
  • size_threshold (optional - default 102400 - 100KB) : Key Size threshold to be used on the results

 

Tips:

  • use ttl_threshold = -1 to return key names with no TTL (ex: /listKeys.sh [port] -1 [+/-][size_Threshold])

  • use ttl_threshold = 0 to return key names with any TTL (ex: /listKeys.sh [port] 0 [+/-][size_Threshold])

  • use ttl_threshold = -500 to return key names with TTL below 500 seconds (ex: /listKeys.sh [port] -500 [+/-][size_Threshold])
  • use ttl_threshold = 500 to return key names with TTL above or equal to 500 seconds (ex: /listKeys.sh [port] 500 [+/-][size_Threshold])

  • use size_threshold = 0  to return key names with any size in the cache (ex: /listKeys.sh [port] [+/-][ttl_threshold] 0)
  • use size_threshold = -1000  to return key names with size below 1000 Bytes (ex: /listKeys.sh [port] [+/-][ttl_threshold] -1000)
  • use size_threshold = 1000  to return key names with size above or equal to 1000 Bytes (ex: /listKeys.sh [port] [+/-][ttl_threshold] 1000)

  • use ttl_threshold = 0 AND size_threshold = 0 to return all key names with any TTL and any size in the cache (ex: /listKeys.sh [port] 0 0)
  • use ttl_threshold = -1 AND size_threshold = 0 to return all key names with no TTL and any size in the cache (ex: /listKeys.sh [port] -1 0)


Tested with:

  • Ubuntu 20.04.6 LTS
  • redis-cli -v
        redis-cli 7.4.2
  • Redis services:
    • Azure Managed Redis Balanced B0 OSSMode
    • Azure Cache for Redis Standard C1

 

listKeys.sh

#!/usr/bin/env bash
set -euo pipefail
#============================== LUA script version =================
# Linux Bash Script to list Redis Keys names
# It returns key names with:
#   - No TTL set
#   - with TTL higher or equal to TTL_treshold
#   - with TTL lower TTL_threshold
#   - with value size higher or equal than Size_threshold
#   - with value size lower than Size_threshold
#   - total number of keys in the cache.
#-------------------------------------------------------
# WARNING:
# It uses LUA script (included on Bash code) to run on Redis server side.
# Use it carefully, during low Redis workoads.
# Do your tests first on a Dev environment, before use it on production.
#-------------------------------------------------------
# It requires :                                                                                               
#    redis-cli v7 or above                                                                                    
#--------------------------------------------------------                                                     
# Usage:                                                                                                      
# listKeys.sh <cacheuri> <cacheaccesskey> [<accessport>(10000)] [+/-][<ttl_treashold>(-1)] [+/-][<size_treashold>(102400)]
#========================================================

#------------------------------------------------------
# Using non-ssl port requires to remove --tls parameter on Redis-cli command below
#------------------------------------------------------

sintax="<redis_host> <password> [redis_port] [+/-][ttl_threshold] [+/-][size_threshold]"
REDIS_HOST="${1:?Usage: $0 $sintax}"
REDISCLI_AUTH="${2:?Usage: $0 $sintax}"
REDIS_PORT="${3:-10000}"          # Redis port (10000, 6380, 6379)
KEYTTL_THRESHOLD=${4:-"-1"}       # -1, +TTL_threshold, TTL_threashold, -TTL_threshold
KEYSIZE_THRESHOLD="${5:-102400}"  # +Size_threshold, Size_threashold, -Size_threshold

# Port number must be numeric
if ! [[ "$REDIS_PORT" =~ ^[0-9]+$ ]]; then
  echo "ERROR: Redis Port must be numeric"
  exit 1
fi

# Check if KEYTTL_THRESHOLD is a valid integer
if ! [[ "$KEYTTL_THRESHOLD" =~ ^[-+]?[0-9]+$ ]]; then
    echo "Error: ttl_threshold $KEYTTL_THRESHOLD is not an integer"
    exit 1
fi

# Check if KEYSIZE_THRESHOLD is a valid integer
if ! [[ "$KEYSIZE_THRESHOLD" =~ ^[-+]?[0-9]+$ ]]; then
    echo "Error: Size_threshold $KEYSIZE_THRESHOLD is not an integer"
    exit 1
fi

# Check if TTL Threasold is positive (or zero), or  negative
if [ "$KEYTTL_THRESHOLD" -ge 0 ]; then
    TTLSIGN="+"
else
    TTLSIGN="-"
fi

# Check if Size Threshold is positive (or zero), or  negative
if [ "$KEYSIZE_THRESHOLD" -ge 0 ]; then
    SIZESIGN="+"
    size_text="larger"
else
    SIZESIGN="-"
    size_text="smaler"
fi

# specific with no TTL set
if [ "$KEYTTL_THRESHOLD" -eq -1 ]; then
    ttl_text="No TTL set"
fi
if [ "$KEYTTL_THRESHOLD" -ge 0 ]; then
    ttl_text="TTL above $KEYTTL_THRESHOLD Seconds"
fi
if [ "$KEYTTL_THRESHOLD" -lt -1 ]; then
    ttl_text="TTL below ${KEYTTL_THRESHOLD#[-+]} Seconds"
fi

# remove any sign
KEYTTL_THRESHOLD="${KEYTTL_THRESHOLD#[-+]}"
KEYSIZE_THRESHOLD="${KEYSIZE_THRESHOLD#[-+]}"

echo "========================================================"
echo "List all key names with $ttl_text, and Key size $size_text $KEYSIZE_THRESHOLD Bytes"

# Start time
start_ts=$(date +%s.%3N)
echo "Start time: $(date "+%d-%m-%Y %H:%M:%S")"
echo "------------------------"

echo ""

# Procesing
redis-cli -h "$REDIS_HOST" -p "$REDIS_PORT" -a "$REDISCLI_AUTH" --tls --no-auth-warning EVAL "
local cursor = '0'
local ttl_threshold = tonumber(ARGV[1])    -- KEYTTL_THRESHOLD
local ttl_sign = ARGV[2]                   -- TTLSIGN
local size_threshold = tonumber(ARGV[3])   -- KEYSIZE_THRESHOLD
local size_sign = ARGV[4]                  -- SIZESIGN
local output = {}
local count = 0
local totalKeys = 0
local strKeyTTL = ''
local strKeySize = ''


-- Scanning keys in the cache
table.insert(output, '--------------------------------------')

repeat
    local res = redis.call('SCAN', cursor, 'COUNT', 100)
    cursor = res[1]

    for _, k in ipairs(res[2]) do
        local ttl = redis.call('TTL', k)
        local size = redis.call('MEMORY','USAGE', k)
        totalKeys = totalKeys + 1

        if (size_sign == '+' and size >= size_threshold) or (size_sign == '-' and size < size_threshold) then
            -- TTL == -1 → no expiration
            if ttl_sign == '-' and ttl_threshold == 1 then
                if ttl == -1 then
                    table.insert(output, k .. ': TTL: -1, Size: ' .. size .. ' Bytes')
                    count =  count + 1
                end

            -- TTL comparisons (exclude -1 and -2)
            else
                if ttl >= 0 then
                    table.insert(output, k .. ': TTL: ' .. ttl .. ' seconds, Size: ' .. size .. ' Bytes')
                    if ttl_sign == '-' and ttl < ttl_threshold then
                        count =  count + 1
                    elseif ttl_sign == '+' and ttl >= ttl_threshold then
                        count =  count + 1
                    end
                end
            end
        end
    end
until cursor == '0'


-- Adding summary to output
table.insert(output, '--------------------------------------')

if (size_sign == '+') then
   strKeySize = 'larger'
else
   strKeySize = 'smaler'
end
strKeySize = 'size ' .. strKeySize .. ' than ' .. size_threshold .. ' Bytes'

if ttl_sign == '-' and ttl_threshold == 1 then
   strKeyTTL = 'No TTL'
elseif ttl_sign == '-' then
   strKeyTTL = 'TTL < ' .. ttl_threshold .. ' seconds'
elseif ttl_sign == '+' then
   strKeyTTL = 'TTL >= ' .. ttl_threshold .. ' seconds'
end
strKeyTTL = ' keys found with ' .. strKeyTTL

table.insert(output, 'Scan completed.')
table.insert(output, 'Total of ' .. totalKeys .. ' keys scanned.')
table.insert(output, count .. strKeyTTL .. ', and ' .. strKeySize)
table.insert(output, '--------------------------------------')

return output
" 0 "$KEYTTL_THRESHOLD" "$TTLSIGN" "$KEYSIZE_THRESHOLD" "$SIZESIGN"

echo " "

end_ts=$(date +%s.%3N)
echo "End time: $(date "+%d-%m-%Y %H:%M:%S")"

# Duration - Extract days, hours, minutes, seconds, milliseconds
duration=$(awk "BEGIN {print $end_ts - $start_ts}")
days=$(awk "BEGIN {print int($duration/86400)}")
hours=$(awk "BEGIN {print int(($duration%86400)/3600)}")
minutes=$(awk "BEGIN {print int(($duration%3600)/60)}")
seconds=$(awk "BEGIN {print int($duration%60)}")
milliseconds=$(awk "BEGIN {printf \"%03d\", ($duration - int($duration))*1000}")
echo "Duration  : ${days} days $(printf "%02d" "$hours"):$(printf "%02d" "$minutes"):$(printf "%02d" "$seconds").$milliseconds"
echo "========================================================"


Performance:

This script is much cleaner and more connection-efficient than the previous one, for the same results.
It creates only one connection to Redis service, and all processing is made on Redis side on LUA script.
Despite much more efficient, LUA script may block normal workload on Redis, namely having a large dataset, with high number of keys in the cache.

Redis service used: Azure Managed Redis Balanced B0 OSSMode

# ------------------
Scan completed. Total keys listed: 46005
Duration : 0 days 00:00:01.437

# ------------------
Redis service used: Azure Cache for Redis - Standard - C1
Scan completed. Total keys listed: 1225
Duration : 0 days 00:00:00.545

# ------------------

 

WARNING:
The above script uses LUA script, that runs on Redis side, and may block you normal workload.
Use it carefully when have a large number of keys in the cache, and during low workload times.

 

References

I hope this can be useful !!!

Updated Jan 20, 2026
Version 1.0
No CommentsBe the first to comment