Salvador Dali
Salvador Dali

Reputation: 222461

How to get all keys with their values in redis

I know that in order to get all the list of all keys in Redis, I have to use KEYS *, but is there a way to output all keys together with their values?

Few minutes of searching did not yield any result.

P.S. thank you very much for answers, but I am looking for a native solution. I can write a function that iterates through all the output of KEYS * by myself.

Upvotes: 117

Views: 274857

Answers (18)

Markus
Markus

Reputation: 181

Same output as firelync one-liner, but easier to type and only invokes redis twice:

echo 'keys YOURKEY*' | redis-cli | xargs  redis-cli mget

Only suitable for a hand full of values, and ommits the name of the key

Upvotes: 1

Mohsen Shamohamadi
Mohsen Shamohamadi

Reputation: 67

This shell script retrieves all Redis keys with their corresponding values using the SCAN command.

It uses a while loop to iterate through batches of keys retrieved from Redis, and a for loop to iterate through the keys in each batch. For each key, it retrieves its value using the GET command, and prints the key-value pairs in a formatted manner to the console.

The script continues to retrieve and process batches of keys until all keys have been retrieved

    #!/bin/sh
    
    # Start Redis CLI and retrieve all keys using SCAN command
    redis_keys=$(redis-cli --raw SCAN 0)
    
    # Loop through keys and retrieve values
    while [ "$redis_keys" != "0" ]; do
      # Extract the cursor and keys from SCAN command response
      cursor=$(echo "$redis_keys" | head -n 1)
      keys=$(echo "$redis_keys" | tail -n +2)
    
      # Loop through the keys and retrieve their values
      for key in $keys; do
        value=$(redis-cli --raw GET "$key")
        echo "Key: $key | Value: $value"
      done
    
      # Retrieve the next batch of keys using the new cursor
      redis_keys=$(redis-cli --raw SCAN "$cursor")
    done

Upvotes: 2

Coco
Coco

Reputation: 906

With redis-cli you can export keys and values as following:

#!/bin/bash

# Get all keys and their values using redis-cli
redis-cli --raw KEYS "*" | while read key; do
  value=$(redis-cli --raw GET "$key")
  echo "$key: $value" >> "redis_dump.txt"
done

Every key and value will be added as a new line in redis_dump.txt.

Upvotes: 1

nmtri
nmtri

Reputation: 474

Check out solution for Alpine linux container

  • Create file redis

    #!/bin/bash
    apk --update add redis
    host="$1"
    port="$2"
    
    redis-cli -h "${host}" -p "${port}" --scan --pattern 'key_prefix_*' | while read key;
    do
       value=$(redis-cli -h "${host}" -p "${port}" get "${key}")
       echo "${key} : ${value}"
    done
    
  • Run: chmod 755 redis

  • Run: /bin/sh redis {Your Redis Host} {Your Redis Port}

Upvotes: 0

mdparthi
mdparthi

Reputation: 133

I have updated the script with some more keys and here goes

#!/bin/bash

# Default to '*' key pattern, meaning all redis keys in the namespace
REDIS_KEY_PATTERN="${REDIS_KEY_PATTERN:-*}"
for key in $(redis-cli --scan --pattern "$REDIS_KEY_PATTERN")
do
    type=$(redis-cli type $key)
    if [ $type = "list" ]
    then
        printf "$key => \n$(redis-cli lrange $key 0 -1 | sed 's/^/  /')\n"
    elif [ $type = "hash" ]
    then
        printf "$key => \n$(redis-cli hgetall $key | sed 's/^/  /')\n"
    elif [ $type = "smembers" ]
    then
        printf "$key => $(redis-cli smembers $key)\n"
    elif [ $type = "zset" ]
    then
        printf "$key => $(redis-cli zrange $key 0 -1)\n"
    elif [ $type = "set" ]
    then
        printf "$key => $(redis-cli smembers $key)\n"
    else
        printf "$key => $(redis-cli get $key)\n"

    fi
done

Upvotes: 0

Zap
Zap

Reputation: 346

This simple script worked for me (I store in my REDIS key-value sets)

#!/bin/bash

for key in $(redis-cli -p <port> -n <db num> keys \*);
  do
    OUTPUT=$(redis-cli -p <port> -n <db num> GET $key)
    echo "$key", "${OUTPUT}" >> redis_pairs.csv
done

You simply execute it:

$ chmod +x script.sh
$ ./script.sh

The final output is a .csv file (comma delimiter) of the pairs I needed.

Upvotes: 0

DevonDahon
DevonDahon

Reputation: 8350

Below is just a little variant of the script provided by @"Juuso Ohtonen".

I have add a password variable and counter so you can can check the progression of your backup. Also I replaced simple brackets [] by double brackets [[]] to prevent an error I had on macos.

1. Get the total number of keys

$ sudo redis-cli
INFO keyspace
AUTH yourpassword
INFO keyspace

2. Edit the script

#!/bin/bash

# Default to '*' key pattern, meaning all redis keys in the namespace
REDIS_KEY_PATTERN="${REDIS_KEY_PATTERN:-*}"
PASS="yourpassword"
i=1
for key in $(redis-cli -a "$PASS" --scan --pattern "$REDIS_KEY_PATTERN")
do
    echo $i.
    ((i=i+1))
    type=$(redis-cli -a "$PASS" type $key)
    if [[ $type = "list" ]]
    then
        printf "$key => \n$(redis-cli -a "$PASS" lrange $key 0 -1 | sed 's/^/  /')\n"
    elif [[ $type = "hash" ]]
    then
        printf "$key => \n$(redis-cli -a "$PASS" hgetall $key | sed 's/^/  /')\n"
    else
        printf "$key => $(redis-cli -a "$PASS" get $key)\n"
    fi
    echo
done

3. Execute the script

bash redis_print.sh > redis.bak

4. Check progression

tail redis.bak

Upvotes: 2

Kees C. Bakker
Kees C. Bakker

Reputation: 33371

Tried the given example, but over VPN and with 400k+ keys it was too slow for me. Also it did not give me the key objects.

I wrote a small Python called tool redis-mass-get to combine KEYS and MGET requests against Redis:

# installation:
pip install redis-mass-get

# pipeline example CSV:
redis-mass-get -f csv -och redis://my.redis.url product:* | less

# write to json-file example with progress indicator:
redis-mass-get -d results.json -jd redis://my.redis.url product:*

It supports JSON, CSV and TXT output to file or stdout for usage in pipes. More info can be found at: Reading multiple key/values from Redis.

Upvotes: 1

Amorphous
Amorphous

Reputation: 772

Use this script for redis >=5:

#!/bin/bash
redis-cli keys "*" > keys.txt
cat keys.txt | awk '{ printf "type %s\n", $1 }' | redis-cli > types.txt
paste -d'|' keys.txt types.txt | awk -F\| '
   $2 == "string"               { printf "echo \"KEY %s %s\"\nget %s\n", $1, $2, $1 }
   $2 == "list" || $2 == "set"  { printf "echo \"KEY %s %s\"\nsort %s by nosort\n", $1, $2, $1 }
   $2 == "hash"                 { printf "echo \"KEY %s %s\"\nhgetall %s\n", $1, $2, $1 }
   $2 == "zset"                 { printf "echo \"KEY %s %s\"\nzrange %s 0 -1 withscores\n", $1, $2,$1 }
' | redis-cli
rm keys.txt
rm types.txt

Upvotes: 3

Kartik Chauhan
Kartik Chauhan

Reputation: 3068

You can use MGET to get the values of multiple keys in a single go.

Example:

redis> SET key1 "Hello"
"OK"
redis> SET key2 "World"
"OK"
redis> MGET key1 key2 nonexisting
1) "Hello"
2) "World"
3) (nil)

For listing out all keys & values you'll probably have to use bash or something similar, but MGET can help in listing all the values when you know which keys to look for beforehand.

Upvotes: 7

r043v
r043v

Reputation: 1869

check out my tool, rdd

rdd -v

will output you all keys with data

Upvotes: -2

Juuso Ohtonen
Juuso Ohtonen

Reputation: 9662

I refined the bash solution a bit, so that the more efficient scan is used instead of keys, and printing out array and hash values is supported. My solution also prints out the key name.

redis_print.sh:

#!/bin/bash

# Default to '*' key pattern, meaning all redis keys in the namespace
REDIS_KEY_PATTERN="${REDIS_KEY_PATTERN:-*}"
for key in $(redis-cli --scan --pattern "$REDIS_KEY_PATTERN")
do
    type=$(redis-cli type $key)
    if [ $type = "list" ]
    then
        printf "$key => \n$(redis-cli lrange $key 0 -1 | sed 's/^/  /')\n"
    elif [ $type = "hash" ]
    then
        printf "$key => \n$(redis-cli hgetall $key | sed 's/^/  /')\n"
    else
        printf "$key => $(redis-cli get $key)\n"
    fi
done

Note: you can formulate a one-liner of this script by removing the first line of redis_print.sh and commanding: cat redis_print.sh | tr '\n' ';' | awk '$1=$1'

Upvotes: 26

JackAss
JackAss

Reputation: 338

scan 0 MATCH * COUNT 1000 // it gets all the keys if return is "0" as first element then count is less than 1000 if more then it will return the pointer as first element and >scan pointer_val MATCH * COUNT 1000 to get the next set of keys it continues till the first value is "0".

Upvotes: 0

Steave J.
Steave J.

Reputation: 41

I had the same problem, and I felt on your post.

I think the easiest way to solve this issue is by using redis Hashtable.

It allows you to save a Hash, with different fields and values associated with every field.

To get all the fiels and values client.HGETALLL does the trick. It returns an array of

all the fields followed by their values.

More informations here https://redis.io/commands/hgetall

Upvotes: 4

Nikhil Pate
Nikhil Pate

Reputation: 641

Yes, you can do print all keys using below bash script,

for key in $(redis-cli -p 6379 keys \*);
  do echo "Key : '$key'" 
     redis-cli -p 6379 GET $key;
done

where, 6379 is a port on which redis is running.

Upvotes: 52

Jain Rachit Kumar
Jain Rachit Kumar

Reputation: 4277

I have written a small code for this particular requirement using hiredis , please find the code with a working example at http://rachitjain1.blogspot.in/2013/10/how-to-get-all-keyvalue-in-redis-db.html

Here is the code that I have written,

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hiredis.h"

int main(void)
{
        unsigned int i,j=0;char **str1;
        redisContext *c; char *t;
        redisReply *reply, *rep;

        struct timeval timeout = { 1, 500000 }; // 1.5 seconds
        c = redisConnectWithTimeout((char*)"127.0.0.2", 6903, timeout);
        if (c->err) {
                printf("Connection error: %s\n", c->errstr);
                exit(1);
        }

        reply = redisCommand(c,"keys *");
        printf("KEY\t\tVALUE\n");
        printf("------------------------\n");
        while ( reply->element[j]->str != NULL)
        {
                rep = redisCommand(c,"GET  %s", reply->element[j]->str);
                if (strstr(rep->str,"ERR Operation against a key holding"))
                {
                        printf("%s\t\t%s\n",  reply->element[j]->str,rep->str);
                        break;
                }
                printf("%s\t\t%s\n",  reply->element[j]->str,rep->str);
                j++;
                freeReplyObject(rep);
        }
}

Upvotes: 1

firelynx
firelynx

Reputation: 32204

There is no native way of doing this.

The Redis command documentation contains no native commands for getting the key and value of multiple keys.

The most native way of doing this would be to load a lua script into your redis using the SCRIPT LOAD command or the EVAL command.

Bash Haxx solution

A workaround would be to use some bash magic, like this:

echo 'keys YOURKEY*' | redis-cli | sed 's/^/get /' | redis-cli 

This will output the data from all the keys which begin with YOURKEY

Note that the keys command is a blocking operation and should be used with care.

Upvotes: 69

Didier Spezia
Didier Spezia

Reputation: 73206

KEYS command should not be used on Redis production instances if you have a lot of keys, since it may block the Redis event loop for several seconds.

I would generate a dump (bgsave), and then use the following Python package to parse it and extract the data:

https://github.com/sripathikrishnan/redis-rdb-tools

You can have json output, or customize your own output in Python.

Upvotes: 14

Related Questions