redis - mass inserts and counters - redis

This is my first question here on stackoverflow.
Dear community, thanks a lot for your combined knowledge and expertise !
I'm new to Redis so please bear with me, as I'm sure there is a simple solution.
redis-server --version
=> Redis server v=2.6.14 sha=00000000:0 malloc=libc bits=64
redis-cli --version
=> redis-cli 2.6.14
I have read "How to use Redis mass insertion?"
How to use Redis mass insertion?
I have googled and read a lot of praise for the redis INCR feature. But I don't really understand everything and it does not help me to do this redis-internally only.
My goal:
I want to import 'n' lines of text into redis and retrive them later in exactly this order.
For each line I set a unique key, like key:1, key:2, key:3 etc.
By using an increasing counter as part of the key I am able to later retrieve the lines in the same order in which they were stored in redis.
Now (without redis mass insert) I solve this easily
by using an awk script to generate redis-cli calls, like:
cat data.txt | awk -f myscript.awk | bash
"data.txt" looks like this:
This is the first line.
This here is the much longer second line.
"myscript.awk" looks like this:
#!/usr/bin/awk -f
### This section is being applied before any line is read:
BEGIN {
# Set counter initially to Zero
print "redis-cli SET counter 0"
}
### This section is being applied per line read into awk:
{
# Increase counter by One
print "redis-cli INCR counter"
# Read current counter from redis into an variable
print "MYCOUNTER=`redis-cli GET counter`"
# Use this variable as counter for the key
print "redis-cli SET key:$MYCOUNTER \"" $0 "\""
# Retrive stored value from redis for illustration
print "redis-cli GET key:$MYCOUNTER"
}
The output of "cat data.txt | awk -f myscript.awk | bash" is:
OK
(integer) 1
OK
"This is the first line."
(integer) 2
OK
"This here is the much longer second line."
So everything is fine.
But instead of calling "redis-cli" twice per imported line
I want to use the redis "mass insert" feature. Here I need your help:
How would I do something like this in redis only ?
SET counter 0
=> OK
INCR counter
=> (integer) 1
GET counter
=> "1"
SET KEY:{counter} "Content of line 1"
=> OK
INCR counter
=> (integer) 2
GET counter
=> "2"
SET KEY:{counter} "Different content of line 2"
=> OK
etc., etc.
The "GET counter" lines are just for illustration.
Any help is appreciated. Thanks again !
bernie

Use a list for this. There's no reason to use a new key for each line. All the list commands are here, but the one you want is RPUSH. You can rpush many values at once in the same line, so you'll just do that:
RPUSH some_key line1 line2 ... lineN
Then to retrieve:
LRANGE some_key 0 -1
Quick and easy!

Related

How can I insert many values into a set via redis-cli or otherwise?

I am using redis-cli. I would like to add in a set the numbers 1 all the way to 4,500,000. How can I accomplish this? The docs for sadd do not mention how to do this. If this would involve having to type or paste in every single integer individually, this obviously won't work in the CLI, so is there another way programatically?
You can use a bash script for doing this.
Use 'seq' to create a list of numbers, loop over it and add the current iteration inside the set
#!/bin/bash
for i in `seq 10`
do
redis-cli sadd myset $i
done
In case you need to use redis-cli with host and port details, change the command accordingly: redis-cli -h -p
Once you have this ready in a .sh file, you can run it like:
bash redis_script.sh

Get value by position in Redis

When getting all the keys from Redis, like this:
redis.server.com:6379> keys *
1) "z13235jxby03knne1w1gucl5"
Instead of manually copying the long key to execute get z13235jxby03knne1w1gucl5, I'd like to run something like get $(1) (pseudo code) to get the value at position 1, as output by the keys command.
Is this possible, if not, is there any workaround to not have to manually copy paste?
Note, I don't want to solve this with a script, then I prefer just copy and paste it
off the top of my head, I'm not aware of a way from inside the cli.
But, Regardless of any performance implications, you can pipe the cli command lines together , but you have to do it from the shell
redis-cli --raw KEYS "*" | sed -n 1p | xargs redis-cli GET
where the 1 in :
sed -n 1p
is the line number (1-based index) inside KEYS output.
but still you need to do your validations; like making sure the index is withing the nuber of keys returned by the KEYS command all keys are of simple string type ; not sets, hash maps, etc...

Can I make alias commands on redis-cli?

I have the impression Im always typing again and again the same commands
ZRANGE mykey 0 100 WITHSCORES
and it is quite repetitive as I have to juggle between maps, sets, and sorted sets (and the client is not great, I can't use the same shortcuts that I use in my terminal to delete the previous/next word for instance)
Is there a way, like in bash, to write our own scripts to make our life easier ?
e.g
LISTALL mykey
You can use Redis from bash with redis-cli if that is what you mean?
Then you can make bash aliases. So, in bash:
function LISTALL() { redis-cli "ZRANGE $1 0 100 WITHSCORES"; }
then you can do
LISTALL mykey
and use bash editing.

How to use counters in a redis key?

Is there a way to do this in redis ?
SET counter 0
INCR counter
SET KEY:{counter} "Content of line 1"
INCR counter
SET KEY:{counter} "Different content of line 2"
My example code should be substituted (i.e., transformed at runtime by the redis-cli) into:
SET counter 0
INCR counter
SET KEY:1 "Content of line 1"
INCR counter
SET KEY:2 "Different content of line 2"
etc.
My problem is NOT how to auto-increment the counter.
My problem is syntax: How to include a generic {wildcard} into something like:
SET keyname:{currentcounter} "value" ...
Any help is appreciated. Thanks a lot !
bernie
If you are using redis 2.6+ then you can use lua scripting along with EVAL command like the following:
eval "local c = redis.call('incr', KEYS[1]);
return redis.call('set', KEYS[2] .. ':' .. c, ARGV[1])"
2 counter KEY "Content of line 1"
I broke it up onto multiple lines to make it easier to read.
EDIT
Sorry, I was away on business for a few days. Here is a sample showing that it works.
redis 127.0.0.1:6379> flushdb
OK
redis 127.0.0.1:6379> eval "local c = redis.call('incr', KEYS[1]); return redis.call('set', KEYS[2] .. ':' .. c, ARGV[1])" 2 counter KEY "Content of line 1"
OK
redis 127.0.0.1:6379> keys *
1) "KEY:1"
2) "counter"
redis 127.0.0.1:6379> get counter
"1"
redis 127.0.0.1:6379> get KEY:1
"Content of line 1"
redis 127.0.0.1:6379> eval "local c = redis.call('incr', KEYS[1]); return redis.call('set', KEYS[2] .. ':' .. c, ARGV[1])" 2 counter KEY "Content of the next thing"
OK
redis 127.0.0.1:6379> keys *
1) "KEY:1"
2) "KEY:2"
3) "counter"
redis 127.0.0.1:6379> get counter
"2"
redis 127.0.0.1:6379> get KEY:2
"Content of the next thing"
Nope, SET/GET commands don't support this.
You can do similar things using LUA scripts in redis, or even simpler; you can issue the commands as redis expect them using trivial programming/scripting

Executing batches of commands using redis cli

I have a long text file of redis commands that I need to execute using the redis command line interface:
e.g.
DEL 9012012
DEL 1212
DEL 12214314
etc.
I can't seem to figure out a way to enter the commands faster than one at a time. There are several hundred thousands lines, so I don't want to just pile them all into one DEL command, they also don't need to all run at once.
the following code works for me with redis 2.4.7 on mac
./redis-cli < temp.redisCmds
Does that satisfy your requirements? Or are you looking to see if there's a way to programmatically do it faster?
If you don't want to make a file, use echo and \n
echo "DEL 9012012\nDEL 1212" | redis-cli
The redis-cli --pipe can be used for mass-insertion. It is available since 2.6-RC4 and in Redis 2.4.14.
For example:
cat data.txt | redis-cli --pipe
More info in: http://redis.io/topics/mass-insert
I know this is an old old thread, but adding this since it seems missed out among other answers, and one that works well for me.
Using heredoc works well here, if you don't want to use echo or explicitly add \n or create a new file -
redis-cli <<EOF
select 15
get a
EOF