redis-cli flushall makes key names inaccessible - redis

I ran into something odd today. I found that using $ redis-cli FLUSHDB, I can remove a database and its contents just fine. When I use $ redis-cli FLUSHALL however, it leaves a database which can be seen with $ redis-cli INFO KEYSPACE, but which has no visible keys from $ redis-cli KEYS *. Using $ redis-cli SELECT 0 didn't seem to restore this either. What's going on?
/redis_data $ redis-cli INFO KEYSPACE
# Keyspace
/redis_data $ redis-cli KEYS *
(empty array)
/redis_data $ ##### just added 10 values from a separate container #####
/redis_data $ redis-cli INFO KEYSPACE
# Keyspace
db0:keys=10,expires=0,avg_ttl=0
/redis_data $ redis-cli KEYS *
1) "2022-09-29T16:17:46.519Z_log"
2) "2022-09-29T16:17:47.020Z_log"
3) "2022-09-29T16:17:48.023Z_log"
4) "2022-09-29T16:17:45.015Z_log"
5) "2022-09-29T16:17:47.522Z_log"
6) "2022-09-29T16:17:49.024Z_log"
7) "2022-09-29T16:17:46.018Z_log"
8) "2022-09-29T16:17:48.524Z_log"
9) "2022-09-29T16:17:45.517Z_log"
10) "2022-09-29T16:17:44.519Z_log"
/redis_data $ redis-cli FLUSHDB
OK
/redis_data $ redis-cli INFO KEYSPACE
# Keyspace
/redis_data $ redis-cli KEYS *
(empty array)
/redis_data $ ##### add 10 values again #####
/redis_data $ redis-cli INFO KEYSPACE
# Keyspace
db0:keys=10,expires=0,avg_ttl=0
/redis_data $ redis-cli KEYS *
1) "2022-09-29T16:20:53.203Z_log"
2) "2022-09-29T16:20:55.709Z_log"
3) "2022-09-29T16:20:54.707Z_log"
4) "2022-09-29T16:20:52.702Z_log"
5) "2022-09-29T16:20:55.206Z_log"
6) "2022-09-29T16:20:56.710Z_log"
7) "2022-09-29T16:20:52.206Z_log"
8) "2022-09-29T16:20:56.210Z_log"
9) "2022-09-29T16:20:54.205Z_log"
10) "2022-09-29T16:20:53.703Z_log"
/redis_data $ ##### Per the above, FLUSHDB works fine. Let's try FLUSHALL #####
/redis_data $ redis-cli FLUSHALL
OK
/redis_data $ redis-cli INFO KEYSPACE
# Keyspace
/redis_data $ redis-cli KEYS *
(empty array)
/redis_data $ ##### add 10 values again #####
/redis_data $ redis-cli INFO KEYSPACE
# Keyspace
db0:keys=10,expires=0,avg_ttl=0
/redis_data $ redis-cli KEYS * ##### this should give the 10 keys, but it doesn't #####
(empty array)
/redis_data $ redis-cli SELECT 0
OK
/redis_data $ redis-cli INFO KEYSPACE
# Keyspace
db0:keys=10,expires=0,avg_ttl=0
/redis_data $ redis-cli KEYS * ##### SELECT 0 didn't help either #####
(empty array)
/redis_data $ ##### add 10 values again to test if it's writeable #####
/redis_data $ redis-cli INFO KEYSPACE
# Keyspace
db0:keys=20,expires=0,avg_ttl=0
/redis_data $ redis-cli KEYS * ##### we can see keys increased to 20, so it's still writeable, just KEYS isn't finding it #####
(empty array)

Related

Redis delete batch keys strips slashes from key names

In my MacOs 10.15 environment I have a strange Redis behaviour when I list some keys with:
redis-cli -n 1 --scan --pattern "product_doctrine*"
It gives me for example:
product_doctrine[AppBundle\Entity\ColumnMapping\$GEDMO_TIMESTAMPABLE_CLASSMETADATA][21546]
But It doesn’t delete it using xargs:
redis-cli -n 1 --scan --pattern "product_doctrine*" | xargs -L 1 redis-cli -n 1 del
(integer) 0
Is it maybe of the key name having special characters? Because if I run this inide the redis-cli:
SCAN 0 MATCH product_doctrine*
it shows the keys with escaped antislash:
"product_doctrine[AppBundle\\Entity\\ShopSettings\\$GEDMO_SOFTDELETEABLE_CLASSMETADATA][11677]"
Inside redis-cli I can delete those kind of keys successfully with
127.0.0.1:6379[1]> del "product_doctrine[AppBundle\\Entity\\ShopSettings\\$GEDMO_SOFTDELETEABLE_CLASSMETADATA][11677]"
(integer) 1
On macOS 10.14 the following does it:
redis-cli --scan --pattern "foo*" | sed 's/\\/\\\\/' | xargs -L 1 redis-cli DEL
¯\_(ツ)_/¯

Get all keys in Redis cluster

I am using Redis cluster version redis-5.0.5. I want to see all the keys present in my Redis cluster. I know for standalone we use KEYS * to get all the keys.
what is the way to see all keys in Redis cluster?
$ redis-cli -h hostname -p 90001 -c
hostname:90001> KEYS *
(empty list or set)
// I have data on my cluster
Basically, you'd need to run KEYS * (not in production, please!) on every one of the nodes. The cli can do this with the '--cluster call' command, like so:
redis-cli --cluster call hostname:90001 KEYS "*"
Requirement:
redis-cli
awk
grep
xargs
May be can try this assuming redis server reside in localhost with the default port 6379:
redis-cli cluster nodes | awk '{print $2" "$3}' | grep master | awk -F # '{print $1}' | awk -F : '{print " -h "$1" -p "$2" --scan"}' | xargs -L 1 redis-cli -c
Longer version base question above (90001 port number seriously?) and also you can change the pattern (* no filter) for filtering certain key pattern:
redis-cli -h hostname -p 90001 cluster nodes | awk '{print $2" "$3}' | grep master | awk -F # '{print $1}' | awk -F : '{print " -h "$1" -p "$2" --scan --pattern *"}' | xargs -L 1 redis-cli -c
It connects to any one of the redis node to get cluster info and then execute the keys scanning command on each of the master node.
The SCAN command may be what you're looking for, but it's O(N) so the more keys you have, the slower it's going to be. Also, check out this answer by Marc Gravell for another approach using sets: Get values by key pattern in StackExchange.Redis

Delete keys with spaces

I am trying to delete multiple keys from my remote Redis db using the following command.
redis-cli -h <host> -p 6379 KEYS "myprefix:*" | xargs redis-cli -h <host> -p 6379 DEL
It has deleted all the matching keys except the ones having spaces in them.
For e.g.
Deleted:
myprefix:abc
myprefix:def
myprefix:ghi
Not deleted:
myprefix:jkl mno
myprefix:pqr stu
myprefix:vwx yza
What should be my query pattern so that these get deleted too? I tried googling but was unable to find any solution.
The issue is with xargs, not your KEYS query. If you run your query, you will notice that it correctly returns the keys with spaces in them. The problem is that by default xargs splits the strings piped into it by blanks and newlines. To change this behaviour so that it only delimits by newlines, add the -d "\n" option. For example:
redis-cli -h <host> -p 6379 keys "myprefix:*" | xargs -d "\n" redis-cli -h <host> -p 6379 del
For anyone using Mac OS xargs (BSD) instead of linux (GNU) xargs the following works
redis-cli -h <host> -p 6379 keys "myprefix:*" | xargs -I% redis-cli -h <host> -p 6379 del %
or for other weird characters like speech marks this works
redis-cli -h <host> -p 6379 --scan --pattern "myprefix:*" | tr '\n' '\0' | xargs -0 -I% redis-cli -h <host> -p 6379 del %
Here is an another hack to make it work on Mac.
redis-cli KEYS 'pattern*' | xargs -0 -n1 'echo' | sed "s/^/'/g" | sed "s/$/'/g" | xargs redis-cli DEL
This basically puts quote around your keys before passing to redis-cli DEL

redis keys command delete data but scan command does not

redis-cli -s /data/redis/redis.sock --scan --pattern "*abcd|6128*" | xargs -L 100 redis-cli -s /data/redis/redis.sock DEL
above command is not deleting adta from redis and giving following output
(integer) 0
While the keys command works perfectly
redis-cli -s /data/redis/redis.sock KEYS 'abcd|6291*' | xargs redis-cli -s /data/redis/redis.sock DEL;
Is there is something wrong i am doing
Try xargs with -L 1 instead. Worked for me.
redis-cli -s /data/redis/redis.sock --scan --pattern "*abcd|6128*" | xargs -L 1 redis-cli -s /data/redis/redis.sock DEL
BTW, KEYS should be avoided in production environments as it is a blocking command.
scan only applies to some keys (by default on 10 keys per iteration). It returns an offset to continuesly run scan until you reach offset 0. Then you have sampled all keys. More details are in the documentation: http://redis.io/commands/scan
Keys on the other hand samples all keys in the db in one pass. It is also blocking due to redises single threaded architecture which might be bad for performance of other clients.

Copy all keys from one db to another in redis

Instade of move I want to copy all my keys from a particular db to another.
Is it possible in redis if yes than how ?
If you can't use MIGRATE COPY because of your redis version (2.6) you might want to copy each key separately which takes longer but doesn't require you to login to the machines themselves and allows you to move data from one database to another.
Here's how I copy all keys from one database to another (but without preserving ttls)
#set connection data accordingly
source_host=localhost
source_port=6379
source_db=0
target_host=localhost
target_port=6379
target_db=1
#copy all keys without preserving ttl!
redis-cli -h $source_host -p $source_port -n $source_db keys \* | while read key; do
echo "Copying $key"
redis-cli --raw -h $source_host -p $source_port -n $source_db DUMP "$key" \
| head -c -1 \
| redis-cli -x -h $target_host -p $target_port -n $target_db RESTORE "$key" 0
done
Keys are not going to be overwritten, in order to do that, delete those keys before copying or simply flush the whole target database before starting.
Copies all keys from database number 0 to database number 1 on localhost.
redis-cli --scan | xargs redis-cli migrate localhost 6379 '' 1 0 copy keys
If you use the same server/port you will get a timeout error but the keys seem to copy successfully anyway. GitHub Redis issue #1903
redis-cli -a $source_password -p $source_port -h $source_ip keys /*| while read key;
do echo "Copying $key";
redis-cli --raw -a $source_password -h $source_ip -p $source_port -n $dbname DUMP "$key"| head -c -1| redis-cli -x -a $destination_password -h $destination_IP -p $destination_port RESTORE "$key" 0;
Latest solution:
Use the RIOT open-source command line tool provided by Redislabs to copy the data.
Reference: https://developer.redis.com/riot/riot-redis/cookbook.html#_performing_migration
GitHub project link: https://github.com/redis-developer/riot
How to install: https://developer.redis.com/riot/riot-redis/
# Source Redis db
SH=test1-redis.com
SP=6379
# Target Redis db
TH=test1-redis.com
TP=6379
# Copy from db0 to db1 (standalone Redis db, Or cluster mode disabled)
#
riot-redis -h $SH -p $SP --db 0 replicate -h $TH -p $TP --db 1 --batch 10000 \
--scan-count 10000 \
--threads 4 \
--reader-threads 4 \
--reader-batch 500 \
--reader-queue 2000 \
--reader-pool 4
RIOT is quicker, supports multithreading, and works well with cross-environment Redis data copy ( AWS Elasticache, Redis OSS, and Redislabs ).
Not directly. I would suggest to use the always convenient redis-rdb-tools package (from Sripathi Krishnan) to extract the data from a normal rdb dump, and reinject it to another instance.
See https://github.com/sripathikrishnan/redis-rdb-tools
As far as I understand you need to copy keys from a particular DB (e.g 5 ) to a particular DB say 10. If that is the case you can use redis database dumper (https://github.com/r043v/rdd). Although as per documentation it has a switch (-d) to select a database for operation but didn't work for me, so what I did
1.) Edit the rdd.c file and look for int main(int argc,char argv) function
2.) Change the DB to as per your requirement
3.) compile the src by **make
4.) Dump all keys using ./rdd -o "save.rdd"
5.) Edit the rdd.c file again and change the DB
6.) Make again
7.) Import by using ./rdd "save.rdd" -o insert -s "IP" -p"Port"
I know this is old, but for those of you coming here form Google:
I just published a command line interface utility to npm and github that allows you to copy keys that match a given pattern (even *) from one Redis database to another.
You can find the utility here:
https://www.npmjs.com/package/redis-utils-cli
Try using dump to first dump all the keys and then restore the same
If migrating keys inside of the same redis engine, then you might use internal command MOVE for that (pipelining for more speed):
#!/bin/bash
#set connection data accordingly
source_host=localhost
source_port=6379
source_db=4
target_db=0
total=$(redis-cli -n 4 keys \* | sed 's/^/MOVE /g' | sed 's/$/ '$target_db'/g' | wc -c)
#copy all keys without preserving ttl!
time redis-cli -h $source_host -p $source_port -n $source_db keys \* | \
sed 's/^/MOVE /g' | sed 's/$/ 0/g' | \
pv -s $total | \
redis-cli -h $source_host -p $source_port -n $source_db >/dev/null