Bulk delete keys

更新时间:
复制 MD 格式

Delete keys from a Tair instance in bulk using non-blocking methods such as SCAN + UNLINK or pipeline mode.

Choose a deletion method

Scenario

Method

Blocking

Risk

I have a list of specific keys to delete

Method 1: Delete from a file

No

Low

I need to delete keys matching a pattern in production

Method 2: SCAN + UNLINK (Recommended)

No

Low

I need maximum throughput for batch deletion

Method 3: Pipeline mode

No

Low

I'm in a dev/test environment with few keys

Method 4: KEYS + DEL (Use with caution)

Yes

High

Important notes

  • Back up your data before deleting keys.

  • Perform deletions during off-peak hours to minimize impact.

  • Cannot run in DMS: Use redis-cli or a Python client on an ECS instance or local machine.


Method 1: Delete from a file

Best for a predefined list of keys stored in a text file.

Prerequisites

Write the keys to delete to a text file, one key per line.

Command

# UNLINK is non-blocking (Redis 4.0+). For earlier versions, use DEL.
cat <file> | xargs redis-cli -h <host> -p <port> -a <password> UNLINK

Parameters

Parameter

Description

file

Path to the file containing keys. Example: key.txt

host

The endpoint of the Tair instance. See View endpoints.

port

Port number. Default: 6379.

password

The password used to log on to the instance. See Authentication methods for instances.

Example

cat key.txt | xargs redis-cli -h r-bp127cu5tb*****.redis.rds.aliyuncs.com -a Test**** UNLINK

Verify the deletion

# Verify that keys are deleted. Expected result: 0
redis-cli -h <host> -p <port> -a <password> --scan --pattern '<key pattern in the file>' | wc -l

Method 2: SCAN + UNLINK (Recommended)

Recommended for production. Iteratively scans and deletes keys without blocking the server.

Code

import redis
import sys

def main(argv):
    if len(argv) < 4:
        print("Usage: python scan_and_del.py host port password match")
        sys.exit(-1)

    host = argv[1]
    port = argv[2]
    password = argv[3]
    match = argv[4]
    print("host: %s, port: %s, password: %s, match: %s\n" % (host, port, password, match))

    redis_cli = redis.StrictRedis(host=host, port=port, password=password)
    cursor = 0
    rnd = 1

    while rnd == 1 or cursor != 0:
        result = redis_cli.scan(cursor=cursor, match=match, count=1000)
        ret_cursor = result[0]
        ret_keys = result[1]
        num_keys = len(ret_keys)
        print("del %d keys in round %d, cursor: %d" % (num_keys, rnd, ret_cursor))
        if 0 != num_keys:
            ret_unlink = redis_cli.unlink(*ret_keys)
            print("ret_unlink: %d, ret_keys: %s" % (ret_unlink, ret_keys))
        cursor = ret_cursor
        rnd += 1
        print("")

if __name__ == '__main__':
    main(sys.argv)

Run

python scan_and_unlink.py <host> <port> <password> "<key>" 

Parameters

Parameter

Description

host

The endpoint of the Tair instance. See View endpoints.

port

Port number. Default: 6379

password

The password used to log on to the instance. See Authentication methods for instances.

key

Key pattern. Example: "test*" matches test1, test2, test3

Pattern syntax

Pattern

Matches

w?rld

5-char strings: world, warld, wxrld

w*rld

Any length: wrld, woooorld

w[ae]rld

warld, werld (not world)

w[^e]rld

world, warld (not werld)

w[a-b]rld

warld, wbrld

Verify the deletion

Verify that all matching keys are deleted:

redis-cli -h <host> -p <port> -a <password> --scan --pattern '<key>' | wc -l
# Expected output: 0

Method 3: Pipeline mode

Maximizes throughput by batching UNLINK commands to reduce network round trips.

Code

import redis
import sys


def main(argv):
    if len(argv) < 4:
        print("Usage: python scan_and_del_pipeline.py host port password match")
        sys.exit(-1)

    host = argv[1]
    port = int(argv[2])  # Convert port to integer
    password = argv[3]
    match = argv[4]
    print(f"host: {host}, port: {port}, password: {'*' * len(password)}, match: {match}\n")

    # After accumulating 1000 keys, submit a DEL command through the pipeline. You can adjust this number as needed.
    pipeline_batch_size = 1000
    
    redis_cli = redis.StrictRedis(host=host, port=port, password=password, decode_responses=True)
    
    cursor = 0
    total_deleted_count = 0
    keys_to_delete = []

    print("Starting key scan...")
    # Use a 'while True' loop and exit when the cursor is 0.
    while True:
        # 1. Scan a batch of keys.
        cursor, keys = redis_cli.scan(cursor=cursor, match=match, count=1000)

        if keys:
            # 2. Collect the scanned keys into a list for deletion.
            keys_to_delete.extend(keys)

        # 3. When the deletion list reaches the batch size or the scan is complete, execute the deletion.
        if len(keys_to_delete) >= pipeline_batch_size or cursor == 0:
            if keys_to_delete:
                print(f"Accumulated {len(keys_to_delete)} keys. Preparing to delete via Pipeline...")

                # --- Pipeline -----------
                pipe = redis_cli.pipeline(transaction=False, shard_hint=None)
                pipe.delete(*keys_to_delete)
                result = pipe.execute()
                # -------------------------

                deleted_in_batch = result[0]
                total_deleted_count += deleted_in_batch

                print(f"  -> Pipeline executed. Deleted {deleted_in_batch} keys in this batch.")

                # Clear the deletion list to prepare for the next batch.
                keys_to_delete = []

        # 4. If the scan is complete, exit the loop.
        if cursor == 0:
            break

    print(f"\nScan finished. Total keys deleted: {total_deleted_count}")


if __name__ == '__main__':
    main(sys.argv)
    

Run

python scan_and_unlink_pipe.py <host> <port> <password> "<key>" 

Parameters

Parameter

Description

host

The endpoint of the Tair instance. See View endpoints.

port

Port number. Default: 6379

password

The password used to log on to the instance. See Authentication methods for instances.

key

Key pattern. Example: "test*" matches test1, test2, test3

Pattern syntax

Pattern

Matches

w?rld

5-char strings: world, warld, wxrld

w*rld

Any length: wrld, woooorld

w[ae]rld

warld, werld (not world)

w[^e]rld

world, warld (not werld)

w[a-b]rld

warld, wbrld

Verify

redis-cli -h <host> -p <port> -a <password> --scan --pattern '<key>' | wc -l
# Expected output: 0

Method 4: KEYS + DEL (Use with caution)

Warning

The KEYS command blocks the server and may cause high CPU usage. Use this method only in development environments or during planned outages.

When to use

  • Development or staging environments

  • Databases with a small number of keys

  • During complete service outages

Command

redis-cli -h <host> -p <port> -a <password> KEYS "<key>" | xargs redis-cli -h <host> -p <port> -a <password> DEL

Parameters

Parameter

Description

host

The endpoint of the Tair instance. See View endpoints.

port

Port number. Default: 6379

password

The password used to log on to the instance. See Authentication methods for instances.

key

Key pattern. Example: "test*" matches test1, test2, test3

Pattern syntax

Pattern

Matches

w?rld

5-char strings: world, warld, wxrld

w*rld

Any length: wrld, woooorld

w[ae]rld

warld, werld (not world)

w[^e]rld

world, warld (not werld)

w[a-b]rld

warld, wbrld

Example

redis-cli -h r-bp127cu5tb*****.redis.rds.aliyuncs.com -a Test**** KEYS "test*" | xargs redis-cli -h r-bp127cu5tb*****.redis.rds.aliyuncs.com -a Test**** DEL

Verify

redis-cli -h <host> -p <port> -a <password> --scan --pattern '<key>' | wc -l
# Expected output: 0

FAQ

Q: Why does SCAN fail to find expected keys?

A: The keys may reside in a different database. A Tair instance has 256 databases by default. Run INFO keyspace to identify which databases contain keys, then use one of the following methods:

  1. Use the -n parameter to specify the database (Recommended):

    redis-cli -h <host> -p <port> -a <password> -n <db>
  2. Use the SELECT command to switch to the database:

    redis-cli -h <host> -p <port> -a <password>
    > SELECT <db>

Related topics