Deleting all non-expiring keys in a Redis sever from command line
23 Dec
This ending year, we have been reading, installing and testing several in RAM key-value storage(NoSQL), engines. We have decided to give Redis a try mainly because it can save the data to disk, in case you have to restart a server or it crashes, you have have your data back. Our experience with Redis has been mixed, good and bad things, but that will be for another post…
One of the main disadvantages of newer, less mature storage engines than for example MySQL, is the administration tools and features. In this case, as data is kept into memory, if you create a key-value pair, without setting the expiry time, it will stay there in aeternum. Specially on Redis, since data is recovered from disk when the service starts. This creates an administrative problem when you cannot control how programmers use Redis; unfortunately there is no simple way of retrieving all non-expiring keys or keys with more than n seconds to expire from the server in order to delete them. We have already requested this feature: http://code.google.com/p/redis/issues/detail?id=347 But in the mean time, we came out with a one line set of commands to delete them:
redis-cli keys "*" | while read LINE ; do TTL=`redis-cli ttl $LINE`; if [ $TTL -eq -1 ]; then echo "Del $LINE"; RES=`redis-cli del $LINE`; fi; done;
You still need to retrieve all keys, then ask for their expiry time, but is not too slow. You can also modify it to delete keys expiring in more than n seconds, for that case you can use:
redis-cli keys "*" | while read LINE ; do TTL=`redis-cli ttl $LINE`; if [ $TTL -ge 3600 ]; then echo "Del $LINE"; RES=`redis-cli del $LINE`; fi; done;
Where 3600 is the min expiry time you want to delete in seconds.
If you only want to delete keys matching a pattern you can edit the “*” part and add a wildcard expression.
You can probably improve the commands, but this helped us delete the necessary keys, hope it can help you too!

This blog is maintained by Nicolas Poggi, PhD candidate, Performance Analyst, Web Developer, and SysAdmin since ’96. Trying to help improve and foster Internet technologies to make them more reachable and most importantly, efficient to host.
You can also just run the cli on its own and type
keys *
and then cut and paste them in, if you don’t have a lot of them.
Constantly calling the CLI from the command line seems a little clumsy to me.
yes, you can do that, but in our setup we have over 17 servers with redis and thousands of keys each. We have written a full shell script to be multiserver. We also don’t want to delete all keys, for that you have: flushall and flushdb
We also had have a good key name design, so that we can delete specific group of keys. For example we use the database table names, for the cached DB queries. So you do
keys DBCACHE_TABLE_NAME_*
Hi
Thanks for the nice shellscript
Exactly what we needed after filling our sessions redis with a lot of -1 TTL keys after a bad deploy. We will set an EXPIRE on the keys instead of deleting them.
Great tip! Thank you guys!
Got a quick question for you guys, if you don’t mind. When running this command/script I do get many
“Could not connect to Redis at 192.168.100.67:6379: Cannot assign requested address” Notices.
Here’s an example for a typical run:
/usr/bin/redis-cli -h 192.168.100.67 keys “PHPREDIS_SESSION*” | while read LINE ; do TTL=`/usr/bin/redis-cli -h 192.168.100.67 ttl $LINE`; if [ $TTL -eq -1 ]; then echo “Del $LINE”; RES=`/usr/bin/redis-cli -h 192.168.100.67 del $LINE`; fi; done;
Del PHPREDIS_SESSION:jtdvuj4mi6l6vir1nm0ri20cd5
Del PHPREDIS_SESSION:cd2mhppk8133t21jd49covhjf3
Del PHPREDIS_SESSION:i1am29ggecrl4a68frnq5k7pn6
Could not connect to Redis at 192.168.100.67:6379: Cannot assign requested address
bash: [: -eq: unary operator expected
Could not connect to Redis at 192.168.100.67:6379: Cannot assign requested address
bash: [: -eq: unary operator expected
[-- snip --]
Could not connect to Redis at 192.168.100.67:6379: Cannot assign requested address
bash: [: -eq: unary operator expected
Del PHPREDIS_SESSION:5ngggms75vbo9eqd0bjvo5d3k1
Del PHPREDIS_SESSION:2n3ehbel7mvgs8439njo3n77f4
Del PHPREDIS_SESSION:ma75ctd759of9jdl5fb0n3ar27
Del PHPREDIS_SESSION:cjf47edvjefc81pprojpdalt07
I have couple of speculations about this issue but I’ll highly appreciate any input or insights you might have.
Thanks again
Have a sweet 2013
Hi Mickey, I think the problem is that you’re overloading the redis server. One workaround would be to add a sleep (micro sleep) in between deletes with: usleep 10
You can play around with different usleep values according to your server. Hope it helps.
Yup, that does the job. Many thanks!