Support for multi-bulk commands in Redis

347 views
Skip to first unread message

Salvatore Sanfilippo

unread,
Oct 9, 2009, 1:17:25 PM10/9/09
to Redis DB
Hello,

some day ago I committed code to support the multi bulk protocol to
issue queries to Redis.

The protocol is fully backward compatible, but now it's possible to
send commands this way:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
*3
$3
set
$6
foobar
$3
xyz
+OK

*2
$3
get
$6
foobar
$3
xyz

This basically means that all the parts are now binary safe. Using
this new protocol the keys itself are binary safe and can be any kind
of binary string, but probably it's a good idea to avoid to use this
feature as the usual commands are probably a little bit faster when
using the old protocol. I'm not sure about this...

What's important about this new feature is that allows to implement
MSET (atomic multi set of multiple keys/values) and commands to
manipulate hashes.

Another interesting property is that with the new protocol there is no
need to know if the command is a bulk command or not, so client
libraries targeting new versions of Redis may use this new protocol
when dealing with unknown commands. This will make this client
automagically capable of sending commands they don't know at all.

In the next week I'll continue implemeting MSET, and the Hashes. Then
I want to feature freeze to make this stable and release Redis 1.1
given that there will be enough new features to make a release:
integer encoding to save memory, MSET and support for hashes.

Cheers,
Salvatore


--
Salvatore 'antirez' Sanfilippo
http://invece.org

"Once you have something that grows faster than education grows,
you’re always going to get a pop culture.", Alan Kay

jza...@gmail.com

unread,
Oct 15, 2009, 3:48:34 PM10/15/09
to Redis DB
That's rather awesome. Nice work!

Jeremy
> Salvatore 'antirez' Sanfilippohttp://invece.org

Birukoff

unread,
Oct 15, 2009, 9:34:54 PM10/15/09
to Redis DB
Great! This allows to use spaces in keys. For my project it is very
important.
Let's hope v1.1 comes out soon :)

Andrei
> Salvatore 'antirez' Sanfilippohttp://invece.org

Salvatore Sanfilippo

unread,
Oct 16, 2009, 7:47:25 AM10/16/09
to redi...@googlegroups.com
2009/10/16 Birukoff <biru...@gmail.com>:

>
> Great! This allows to use spaces in keys. For my project it is very
> important.
> Let's hope v1.1 comes out soon :)

Hello,

this basically means we have to change the return value of KEYS! From
a simple string where every key is space separated, to a multi bulk
reply.

Btw I just committed MSET and MSETNX on Git. Client libs hacking
required in order to make this working in the real world.

Birukoff

unread,
Oct 16, 2009, 8:29:11 AM10/16/09
to Redis DB
> this basically means we have to change the return value of KEYS!
Well, since api is going to change anyway with the introduction of
hash datatype, why not to change KEYS a little bit? ;)
I can explain why it could be important: in my project, I store and
analyze people's search queries. We could replace spaces with
underscore or something, but this will only work until someone enters
search query with underscore in it...

William Morgan

unread,
Oct 16, 2009, 9:00:50 AM10/16/09
to redis-db
Reformatted excerpts from Birukoff's message of 2009-10-16:

> I can explain why it could be important: in my project, I store and
> analyze people's search queries. We could replace spaces with
> underscore or something, but this will only work until someone enters
> search query with underscore in it...

The problem of escaping strings has been solved for a long time.
--
William <wmo...@masanjin.net>

Birukoff

unread,
Oct 16, 2009, 10:03:49 AM10/16/09
to Redis DB
I can't figure out how to send these new commands... As soon as I send
'*3\r\n' (or just '*3') to redis, it returns error (unknown command).
Using newest source from github.


On 9 окт, 21:17, Salvatore Sanfilippo <anti...@gmail.com> wrote:
> Salvatore 'antirez' Sanfilippohttp://invece.org

Salvatore Sanfilippo

unread,
Oct 16, 2009, 10:21:56 AM10/16/09
to redi...@googlegroups.com
It smells a lot like "didn't typed make" issue :)

2009/10/16 Birukoff <biru...@gmail.com>:
--
Salvatore 'antirez' Sanfilippo

Birukoff

unread,
Oct 16, 2009, 1:26:23 PM10/16/09
to Redis DB
Good joke :)
Still, I can do it with simple commands, like PING: write '*1\r\n$4\r
\nping\r\n' to the socket, and read '+PONG\r\n' back.
With more elaborate commands, it doesn't work here.
To set 'foobar' key to 'xyz' value I am supposed to write the
following to the socket, right?
'*3\r\n$3\r\nset\r\n$6\r\nfoobar\r\n$3\r\nxyz\r\n'
Correct? But server waits for more input from me, and doesn't respond.


On 16 окт, 18:21, Salvatore Sanfilippo <anti...@gmail.com> wrote:
> It smells a lot like "didn't typed make" issue :)
>
> 2009/10/16 Birukoff <biruk...@gmail.com>:

Salvatore Sanfilippo

unread,
Oct 16, 2009, 2:41:48 PM10/16/09
to redi...@googlegroups.com
2009/10/16 Birukoff <biru...@gmail.com>:
>
> Good joke :)
> Still, I can do it with simple commands, like PING: write '*1\r\n$4\r
> \nping\r\n' to the socket, and read '+PONG\r\n' back.
> With more elaborate commands, it doesn't work here.
> To set 'foobar' key to 'xyz' value I am supposed to write the
> following to the socket, right?
> '*3\r\n$3\r\nset\r\n$6\r\nfoobar\r\n$3\r\nxyz\r\n'
> Correct? But server waits for more input from me, and doesn't respond.

Hello again!

yes, correct, this is what happens by telnet:

Connected to localhost.
Escape character is '^]'.
*3
$3
set
$6
foobar
$3
xyz
+OK

But I actually tested this new code *only* by telnet, so maybe it's
broken? Let's try with netcat:

echo -n "*3\r\n\$3\r\nset\r\n\$6\r\nfoobar\r\n\$3\r\nxyz\r\n" | nc
localhost 6379

no look, didn't got +OK this time.

I guess it's broken and to try just by telnet was not wise :)
I'll fix this problem tonight, that's in a few hours.

Cheers,
Salvatore
--
Salvatore 'antirez' Sanfilippo

Salvatore Sanfilippo

unread,
Oct 16, 2009, 5:37:11 PM10/16/09
to redi...@googlegroups.com
2009/10/16 Salvatore Sanfilippo <ant...@gmail.com>:

> I guess it's broken and to try just by telnet was not wise :)
> I'll fix this problem tonight, that's in a few hours.

Ok, now it's fixed.

Cheers,
Salvatore

--

Salvatore Sanfilippo

unread,
Oct 16, 2009, 5:43:08 PM10/16/09
to redi...@googlegroups.com
On Fri, Oct 16, 2009 at 11:37 PM, Salvatore Sanfilippo
<ant...@gmail.com> wrote:
> 2009/10/16 Salvatore Sanfilippo <ant...@gmail.com>:
>
>> I guess it's broken and to try just by telnet was not wise :)
>> I'll fix this problem tonight, that's in a few hours.
>
> Ok, now it's fixed.
>
> Cheers,
> Salvatore

Update: tested some corner case, and pipelining when mixing old style
and new style protocol and all appears to be ok:

% echo -n "PING\r\n*3\r\n\$3\r\nset\r\n\$6\r\nfoobar\r\n\$3\r\nxyz\r\n*3\r\n\$3\r\nset\r\n\$6\r\nfoobar\r\n\$3\r\nxyz\r\nPING\r\n"
| nc localhost 6379
+PONG
+OK
+OK
+PONG

This does not mean it's rock solid code but is a good sign. I'll
continue to stress / debug / read it.

Luca Guidi

unread,
Oct 17, 2009, 9:17:22 AM10/17/09
to redi...@googlegroups.com
Hi Salvatore,
What's the exact syntax for MSET and MSETNX?

Cheers,

Salvatore Sanfilippo

unread,
Oct 17, 2009, 9:23:03 AM10/17/09
to redi...@googlegroups.com
On Sat, Oct 17, 2009 at 3:17 PM, Luca Guidi <guidi...@gmail.com> wrote:
> Hi Salvatore,
> What's the exact syntax for MSET and MSETNX?

Hello Luca,

sorry, no documentation yet :( This is the minimal specification to
play with this commnads:

MSET key value ?key value? ?key value? ... ?key value?

Set all the keys to the specified values, atomically.

MSETNX does exactly the same, with "NX" semantic, but it is in my
opinion very interesting how it works:
if even a single key already exists, then no key at all will be set
(and 0 is returned instead of 1, like SETNX).

This makes a huge difference in building locking free algorithms, as
this ensures the ability to use SETNX to set a number of attributes of
the same object without race conditions. So for instance if two
clients will run the following two commands rougly at the same time:

a) SETNX foo:1000:name antirez foo:1000:phonenum 9403953405345 foo:1000:age 32
b) SETNX foo:1000:name mirka foo:1000:phonenum 1234567890 foo:1000:age 25

the foo:100:* fields will be either set all accordingly to a) or b). A
"mix" can't happen.

Luca Guidi

unread,
Oct 17, 2009, 9:33:07 AM10/17/09
to redi...@googlegroups.com
Hi again,
That syntax was my first attempt, but just tell me if I'm wrong: if I try with telnet the last key is never set:
MSET key1 value1 key2 value2 key3 value3[enter]
\n[enter]
+OK
get key3
$0

Salvatore Sanfilippo

unread,
Oct 17, 2009, 9:52:56 AM10/17/09
to redi...@googlegroups.com
Hello Luca,

when you use it this way, the last argument is a bulk one, so:

MSET key1 value1 key2 value2 key3 <count>
<value>

Probably the problem is this. But actually you have to use the new
protocol! Otherwise value1, value2 can't be binary safe strings.

Ciao,
Salvatore

Birukoff

unread,
Oct 17, 2009, 12:56:38 PM10/17/09
to Redis DB
Another bug: MSET behaves as MSETNX (i.e. it doesn't modify values of
existing keys, although returns +OK).

Andrei


On 17 окт, 17:52, Salvatore Sanfilippo <anti...@gmail.com> wrote:
> Hello Luca,
>
> when you use it this way, the last argument is a bulk one, so:
>
> MSET key1 value1 key2 value2 key3 <count>
> <value>
>
> Probably the problem is this. But actually you have to use the new
> protocol! Otherwise value1, value2 can't be binary safe strings.
>
> Ciao,
> Salvatore
>
>
>
> On Sat, Oct 17, 2009 at 3:33 PM, Luca Guidi <guidi.l...@gmail.com> wrote:
> > Hi again,
> > That syntax was my first attempt, but just tell me if I'm wrong: if I try
> > with telnet the last key is never set:
> > MSET key1 value1 key2 value2 key3 value3[enter]
> > \n[enter]
> > +OK
> > get key3
> > $0
> > Luca
> > --
> > lucaguidi.com
> > twitter.com/jodosha
>
> --
> Salvatore 'antirez' Sanfilippohttp://invece.org

Salvatore Sanfilippo

unread,
Oct 17, 2009, 4:04:51 PM10/17/09
to redi...@googlegroups.com
On Sat, Oct 17, 2009 at 6:56 PM, Birukoff <biru...@gmail.com> wrote:
>
> Another bug: MSET behaves as MSETNX (i.e. it doesn't modify values of
> existing keys, although returns +OK).
>
> Andrei

Andrei, thanks, now it's fixed.

Sorry for this bug, it was pretty stupid and I didn't tested this
command enough, from all the point of view.

I'll try to do a better work for the next times, it's not respectful
to provide code that contains a lot of stupid bugs that make early
adopters (the best kind of users) loose their time.

Monday I'll test the code more extensively.

Regards,
Salvatore

--
Salvatore 'antirez' Sanfilippo

Salvatore Sanfilippo

unread,
Oct 17, 2009, 4:19:05 PM10/17/09
to redi...@googlegroups.com
On Sat, Oct 17, 2009 at 6:56 PM, Birukoff <biru...@gmail.com> wrote:
>
> Another bug: MSET behaves as MSETNX (i.e. it doesn't modify values of
> existing keys, although returns +OK).

Just added support for MSET and MSETNX using the new protocol to
redis-cli utility. So it should be a bit simpler to test the new
commands by hand.

Cheers,
Salvatore


--
Salvatore 'antirez' Sanfilippo

Luca Guidi

unread,
Oct 18, 2009, 8:38:06 AM10/18/09
to redi...@googlegroups.com
Hi,
I implemented the new protocol and MSET/MSETNX commands for ruby gem:
Reply all
Reply to author
Forward
0 new messages