Request for comments: RESP3, the next Redis protocol

654 views
Skip to first unread message

Salvatore Sanfilippo

unread,
May 7, 2018, 10:38:18 AM5/7/18
to redi...@googlegroups.com
Hello, the following is a draft describing the new Redis protocol, RESP3:

https://gist.github.com/antirez/2bc68a9e9e45395e297d288453d5d54c

This will be implemented after many months of thinking more about the
design, so please, let's use this thread to collect feedbacks. The RESP3
protocol does not really want to get too complicated compared to the
current topic, but certain limitations of the current protocol are evident
for years now... and should be addressed.

Thanks for any feedback,
Salvatore

--
Salvatore 'antirez' Sanfilippo
open source developer - Redis Labs https://redislabs.com

"If a system is to have conceptual integrity, someone must control the
concepts."
— Fred Brooks, "The Mythical Man-Month", 1975.

CharSyam

unread,
May 7, 2018, 11:06:50 AM5/7/18
to redi...@googlegroups.com
Hi, antirez,
How about adding it into redis-rcp github?


--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to redis-db+unsubscribe@googlegroups.com.
To post to this group, send email to redi...@googlegroups.com.
Visit this group at https://groups.google.com/group/redis-db.
For more options, visit https://groups.google.com/d/optout.

Salvatore Sanfilippo

unread,
May 7, 2018, 11:15:58 AM5/7/18
to redi...@googlegroups.com
Thanks, I'll do once the version is a bit more finalized probably. Anyway
Github gists are super available for anyone, which is what is really
important in a public process.
On Mon, May 7, 2018 at 5:06 PM CharSyam <char...@gmail.com> wrote:

> Hi, antirez,
> How about adding it into redis-rcp github?


> 2018-05-07 23:37 GMT+09:00 Salvatore Sanfilippo <ant...@gmail.com>:

>> Hello, the following is a draft describing the new Redis protocol, RESP3:

>> https://gist.github.com/antirez/2bc68a9e9e45395e297d288453d5d54c

>> This will be implemented after many months of thinking more about the
>> design, so please, let's use this thread to collect feedbacks. The RESP3
>> protocol does not really want to get too complicated compared to the
>> current topic, but certain limitations of the current protocol are
evident
>> for years now... and should be addressed.

>> Thanks for any feedback,
>> Salvatore

>> --
>> Salvatore 'antirez' Sanfilippo
>> open source developer - Redis Labs https://redislabs.com

>> "If a system is to have conceptual integrity, someone must control the
>> concepts."
>> — Fred Brooks, "The Mythical Man-Month", 1975.

>> --
>> You received this message because you are subscribed to the Google
Groups "Redis DB" group.
>> To unsubscribe from this group and stop receiving emails from it, send
an email to redis-db+u...@googlegroups.com.
>> To post to this group, send email to redi...@googlegroups.com.
>> Visit this group at https://groups.google.com/group/redis-db.
>> For more options, visit https://groups.google.com/d/optout.


> --
> You received this message because you are subscribed to the Google Groups
"Redis DB" group.
> To unsubscribe from this group and stop receiving emails from it, send an
email to redis-db+u...@googlegroups.com.
> To post to this group, send email to redi...@googlegroups.com.
> Visit this group at https://groups.google.com/group/redis-db.
> For more options, visit https://groups.google.com/d/optout.



Demis Bellot

unread,
May 7, 2018, 11:52:42 AM5/7/18
to redi...@googlegroups.com
Hi Salvatore,

Introducing a new protocol version can have a detrimental fragmentation to the existing ecosystem so it would be nice to learn more about the transitioning story for existing clients/Apps. 

I'm hoping you could provide more detail about the backwards compatibility story. Given most clients were not designed for support of multiple protocol versions in mind I'm curious on what the perceived impact of RESP3 will be to the existing ecosystem:

 - Is RESP3 a superset/extension of RESP? (Given CRLF vs LF is a breaking change I'm assuming no, but potentially clients can handle supporting both by inspecting the first byte. But changes to existing commands might break clients)
 - How should clients support both old and newer versions of Redis, e.g. should they be refactored to support multiple protocol versions? (will there ever be RESP4?)
 - Will upgrading to a newer version of Redis with RESP3 break existing clients/Apps bound to the existing RESP protocol? (i.e. would newer Redis servers auto-detect old clients and fallback to RESP responses?)

Or can newer versions of Redis be statically configured to revert back to support existing RESP mode so upgrading to newer versions of Redis doesn't break existing clients/Apps?

Note that the Hello reply still allows a client that wants to be compatible with older versions of Redis to detect the version of the protocol. Upon connection the client should send a PING command. If the first byte read will be @, the version of the protocol is RESP3, the Hello reply will be processed, and later the PING reply will be read. Instead if the first byte is not @ we just read the PING reply and switch to RESP version 2 mode.

This version detection appears a little hacky given its based on heuristics and there's no notion of a version number. e.g. What would RESP4 version detection look like? It's also unclear if the burden of supporting multiple redis versions is required in every redis client or whether new Redis server versions will be able to support both old RESP and newer RESP3 clients?

Has other solutions for migration been explored, e.g. instead of changing the protocol of existing Redis commands maybe they could be overloaded to specify the protocol that the Redis Server should return, e.g:

    SMEMBERS myset

Which returns the standard RESP Array Reply

    SMEMBERS@3 myset

Which returns the newer RESP3 Set Reply.

A lot of existing protocols specify the version when making the request so servers can seamlessly support both older and newer clients, but it's not clear if Redis plans to support existing clients or break them. Unless there's someway to tell Redis Sever the version it should use for that connection I'm assuming it will just break existing clients. If that's the case are there any details yet on the LTS of the Redis version that supports RESP? (i.e. how long will existing systems bound to RESP receive bug fix / security updates?)

Thanks,
- Demis




>> To post to this group, send email to redi...@googlegroups.com.
>> Visit this group at https://groups.google.com/group/redis-db.
>> For more options, visit https://groups.google.com/d/optout.


> --
> You received this message because you are subscribed to the Google Groups
"Redis DB" group.
> To unsubscribe from this group and stop receiving emails from it, send an

> To post to this group, send email to redi...@googlegroups.com.
> Visit this group at https://groups.google.com/group/redis-db.
> For more options, visit https://groups.google.com/d/optout.



--
Salvatore 'antirez' Sanfilippo
open source developer - Redis Labs https://redislabs.com

"If a system is to have conceptual integrity, someone must control the
concepts."
        — Fred Brooks, "The Mythical Man-Month", 1975.

--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to redis-db+unsubscribe@googlegroups.com.

Salvatore Sanfilippo

unread,
May 7, 2018, 12:50:54 PM5/7/18
to redi...@googlegroups.com
Hello Denis,
On Mon, May 7, 2018 at 5:52 PM Demis Bellot <demis....@gmail.com> wrote:

> Introducing a new protocol version can have a detrimental fragmentation
to the existing ecosystem so it would be nice to learn more about the
transitioning story for existing clients/Apps.

> I'm hoping you could provide more detail about the backwards
compatibility story. Given most clients were not designed for support of
multiple protocol versions in mind I'm curious on what the perceived impact
of RESP3 will be to the existing ecosystem:

Sure

> - Is RESP3 a superset/extension of RESP? (Given CRLF vs LF is a breaking
change I'm assuming no, but potentially clients can handle supporting both
by inspecting the first byte. But changes to existing commands might break
clients)

Not a superset, it's a different incompatible protocol.

> - How should clients support both old and newer versions of Redis, e.g.
should they be refactored to support multiple protocol versions? (will
there ever be RESP4?)

RESP3 has built-in future-proof ways for handling RESP4, 5, 6, ... while
RESP2 must be supported by checking the first byte.
RESP4 will likely be introduced after a long timeframe like RESP3 follows
RESP2 after like 6 years.
If clients should be RESP3 specific of support multiple protocols, is a
choice that only different client lib leaders should do.

> - Will upgrading to a newer version of Redis with RESP3 break existing
clients/Apps bound to the existing RESP protocol? (i.e. would newer Redis
servers auto-detect old clients and fallback to RESP responses?)

Redis 6 (or 7, still not sure) will support *only* RESP3, there will be no
way to use an older client.
However once a Redis server which speaks RESP3 is released under the
"unstable" branch, a minimum of six months will pass before such versions
will be branded GA.

> Or can newer versions of Redis be statically configured to revert back to
support existing RESP mode so upgrading to newer versions of Redis doesn't
break existing clients/Apps?

Nope, this is a lot of useless work, and by breaking compatibility I want
to encourage everybody to move forward.
I did backward compatibility in RESP -> RESP2 transition and regretted it.
Redis 1.2 supported both, but when I went for 2.0 only the new protocol was
supported, and many clients were broken, because nobody gives a shit if it
still works. So we'll do the same basically, but without me doing a mess
inside Redis to support two protocols, just there will be a time when the
clients can be tested against unstable with RESP3, and against the RESP2
stable version, and then we'll move forward.

>> Note that the Hello reply still allows a client that wants to be
compatible with older versions of Redis to detect the version of the
protocol. Upon connection the client should send a PING command. If the
first byte read will be @, the version of the protocol is RESP3, the Hello
reply will be processed, and later the PING reply will be read. Instead if
the first byte is not @ we just read the PING reply and switch to RESP
version 2 mode.


> This version detection appears a little hacky given its based on
heuristics and there's no notion of a version number. e.g. What would RESP4
version detection look like? It's also unclear if the burden of supporting
multiple redis versions is required in every redis client or whether new
Redis server versions will be able to support both old RESP and newer RESP3
clients?

RESP3 has a future proof way to detect newer protocols, because the hello
reply will report also a field with the protocol version, moreover the
reply packet will remain *exactly* as it is in the future from the POV of
the format. So by reading the protocol version, the client will know how to
interpret all the other fields, and what to expect next.

With RESP2 this obviously not possible. However the proposed detection is
not fragile. You can say it's "hacky" but this is an esthetic judgment,
because:

Probability that RESP2 emits @ as a first byte: 0
Probability that RESP3 does not emit @ as first byte: 0
Probability of client mis-detecting the protocol: 0

It's the best we can have given that RESP2 had no such features.

> Has other solutions for migration been explored, e.g. instead of changing
the protocol of existing Redis commands maybe they could be overloaded to
specify the protocol that the Redis Server should return, e.g:

> SMEMBERS myset

> Which returns the standard RESP Array Reply

> SMEMBERS@3 myset

I think we should boldly move forward without having this terrible things
inside Redis. Clients can move forward to newer versions IMHO, there will
be enough time, and people that don't want to stay cutting edge, can still
use older versions of Redis (for a long time as they are doing right now...
there are shops running with 2.4 as we talk), and jump to RESP3 only later
when the ecosystem is mature.
Moreover RESP2 transition did not cause any problem, clients adapted. I
think that of all the things that are broken in the clients ecosystem now
in Redis, very few are related to the actual protocol. They have broken
connection management, broke APIs, lack for tons of new things, and so
forth, but updating the protocol part itself is trivial, especially in the
case of a protocol which is actually *more* client friendly.

> A lot of existing protocols specify the version when making the request
so servers can seamlessly support both older and newer clients, but it's
not clear if Redis plans to support existing clients or break them. Unless
there's someway to tell Redis Sever the version it should use for that
connection I'm assuming it will just break existing clients. If that's the
case are there any details yet on the LTS of the Redis version that
supports RESP? (i.e. how long will existing systems bound to RESP receive
bug fix / security updates?)

Sorry I don't like this and I don't think it's worth at all. Redis is a
simple software, Redis clients are, from the POV of the protocol, simple
software (they are complex to handle things that are not related to the
protocol itself mostly), we can move forward without resembling a COBOL 60s
system in a big corp :-)

Cheers,
Salvatore
>> an email to redis-db+u...@googlegroups.com.
>> >> To post to this group, send email to redi...@googlegroups.com.
>> >> Visit this group at https://groups.google.com/group/redis-db.
>> >> For more options, visit https://groups.google.com/d/optout.


>> > --
>> > You received this message because you are subscribed to the Google
Groups
>> "Redis DB" group.
>> > To unsubscribe from this group and stop receiving emails from it, send
an
>> email to redis-db+u...@googlegroups.com.
>> > To post to this group, send email to redi...@googlegroups.com.
>> > Visit this group at https://groups.google.com/group/redis-db.
>> > For more options, visit https://groups.google.com/d/optout.



>> --
>> Salvatore 'antirez' Sanfilippo
>> open source developer - Redis Labs https://redislabs.com

>> "If a system is to have conceptual integrity, someone must control the
>> concepts."
>> — Fred Brooks, "The Mythical Man-Month", 1975.

>> --
>> You received this message because you are subscribed to the Google
Groups "Redis DB" group.
>> To unsubscribe from this group and stop receiving emails from it, send
an email to redis-db+u...@googlegroups.com.
>> To post to this group, send email to redi...@googlegroups.com.
>> Visit this group at https://groups.google.com/group/redis-db.
>> For more options, visit https://groups.google.com/d/optout.


> --
> You received this message because you are subscribed to the Google Groups
"Redis DB" group.
> To unsubscribe from this group and stop receiving emails from it, send an
email to redis-db+u...@googlegroups.com.

Salvatore Sanfilippo

unread,
May 7, 2018, 12:52:18 PM5/7/18
to redi...@googlegroups.com
P.S. forgot to reply to LTS. LTS will be supported by Redis 5 very likely,
by merging the AWS patch, but this is AFAIK orthogonal to RESP itself.
On Mon, May 7, 2018 at 6:50 PM Salvatore Sanfilippo <ant...@gmail.com>
wrote:

Marc Gravell

unread,
May 7, 2018, 1:22:44 PM5/7/18
to redi...@googlegroups.com
I kinda dislike special treatment of "PING" here, especially given that PING could be disabled or renamed. If you mean "any command", then... my next thought is AUTH - does the "hello" come before or after the successful auth? I wonder if a "CLIENT PROTOCOL 3" or similar might be a suitable handshake element? Of course, by my same reasoning CLIENT might also be renamed or disabled :)

If we're byte counting (the CR purge), then note that a lot of the remaining LF are also technically unnecessary - on length prefixed data or data without a body (null, for example). That might be a step too far, though.

You mention that subscribe / unsubscribe might be subtypes of push messages; would this be in addition to, or instead of, a regular response to the subscribe / unsubscribe request?

What happens if a module or script tries to return a binary error but only RESP 2 is available? Where does a suitable message come from?

Probably more thoughts when I read it more :)

Salvatore Sanfilippo

unread,
May 7, 2018, 2:08:05 PM5/7/18
to redi...@googlegroups.com
Hello Marc,

On Mon, May 7, 2018 at 7:22 PM Marc Gravell <marc.g...@gmail.com> wrote:

> I kinda dislike special treatment of "PING" here, especially given that
PING could be disabled or renamed. If you mean "any command", then... my
next thought is AUTH - does the "hello" come before or after the successful
auth? I wonder if a "CLIENT PROTOCOL 3" or similar might be a suitable
handshake element? Of course, by my same reasoning CLIENT might also be
renamed or disabled :)

I was not clear about that, you can use *anything*, both immediately after
the connection or even in a lazy way, that is, in the reply reading code as
soon as you get "@" as the first type byte, you do the switch to the RESP3
protocol internally.

> If we're byte counting (the CR purge), then note that a lot of the
remaining LF are also technically unnecessary - on length prefixed data or
data without a body (null, for example). That might be a step too far,
though.

That's true indeed, and to be honest I thought about this quite a bit
without finding a good solution, but in the end opted for aesthetics: given
that in many places the \n is needed and makes the protocol dump more
readable in the other cases, I went for having it everywhere.

> You mention that subscribe / unsubscribe might be subtypes of push
messages; would this be in addition to, or instead of, a regular response
to the subscribe / unsubscribe request?

Basically the Pub/Sub protocol would be exactly like today, it only changes
that instead of receiving arrays with the *implicit* meaning of Pub/Sub
messages, you get everything as push messages of type "pubsub", both
otherwise, exact same semantics. And of course in the same connection you
are free to call regular commands.

> What happens if a module or script tries to return a binary error but
only RESP 2 is available? Where does a suitable message come from?

What happens today... we have code in place in order to filter replies and
substitute "\r" and "\n" with spaces :-D

Thanks

Demis Bellot

unread,
May 7, 2018, 2:44:33 PM5/7/18
to redi...@googlegroups.com
I think we should boldly move forward without having this terrible things
inside Redis. Clients can move forward to newer versions IMHO, there will
be enough time, and people that don't want to stay cutting edge, can still
use older versions of Redis

The problem with this approach is that the burden of supporting multiple Redis Servers needs to (multiplicatively) be baked into every client. IMO it's not feasible for most clients to "move" to only support the newer RESP3 protocol, existing clients are going to need to support existing versions of Redis pretty much indefinitely since all existing code bases is dependent on the existing RESP protocol clients. I don't think forcing customers to update their Redis server to the latest RESP3 version is something a client library can dictate given the heterogeneous production environments Redis can be used in.

Redis clients are, from the POV of the protocol, simple
software (they are complex to handle things that are not related to the
protocol itself mostly), 

I agree the Redis protocol is simple which is the reason why there's been an explosion of clients, but forcing clients to support multiple protocol versions makes it less so and whilst increasing the confusion around trying to understand which client version supports which Redis Server version. As a library author with dependent clients there is really no approach other than supporting every Redis protocol (and by extension introduce the complexity of supporting multiple protocol versions). Existing users can't upgrade their Redis server because existing clients don't support it and client libraries can't move to RESP3-only because it breaks existing users. IMO the only other workable solution is to support development/maintenance of multiple client libraries in parallel. 

I'm not aware of any good literature that supports major breaking API versions, basically Stripe avoids it:

A problem with that approach though is that you'd need an incredibly good reason to ever build out a `/v2/` because if you ever bump that major version you're going to leave an incredible number of users behind on the original. Most people want to integrate one time and not have to worry about upgrading (ideally ever).
 
At Stripe, we've tried to build a compromise by introducing minor, date-based versions that include only a fairly constrained set of changes, but which we can bump more liberally. As others have mentioned here, your account gets locked into a version on its first request, and if never want to worry about API versioning at all, you can leave that version untouched essentially indefinitely.


Likewise Rich Hickey is also against making major breaking API changes: https://www.youtube.com/watch?v=oyLBGkS5ICk

Personally I think the cleanest transition is for Redis server to support multiple protocol versions transparently (or at least latest 1 or 2 versions) then when most people are running the latest stable Redis Server version for a couple of years clients can move to only support RESP3 as they can assume most of the ecosystem have upgraded. Otherwise I think you'll find the existing ecosystem will be tied to the last RESP Redis version since they can only migrate unless everything that connects to their Redis servers can support the latest version. Anyway would be good to hear what the feedback of what the existing Redis community thinks, whether they think this is going to cause major fragmentation/friction or not.

- Demis




> >> >> To post to this group, send email to redi...@googlegroups.com.
> >> >> Visit this group at https://groups.google.com/group/redis-db.
> >> >> For more options, visit https://groups.google.com/d/optout.


> >> > --
> >> > You received this message because you are subscribed to the Google
> Groups
> >> "Redis DB" group.
> >> > To unsubscribe from this group and stop receiving emails from it,
send
> an

> >> > To post to this group, send email to redi...@googlegroups.com.
> >> > Visit this group at https://groups.google.com/group/redis-db.
> >> > For more options, visit https://groups.google.com/d/optout.



> >> --
> >> Salvatore 'antirez' Sanfilippo
> >> open source developer - Redis Labs https://redislabs.com

> >> "If a system is to have conceptual integrity, someone must control the
> >> concepts."
> >>          — Fred Brooks, "The Mythical Man-Month", 1975.

> >> --
> >> You received this message because you are subscribed to the Google
> Groups "Redis DB" group.
> >> To unsubscribe from this group and stop receiving emails from it, send

> >> To post to this group, send email to redi...@googlegroups.com.
> >> Visit this group at https://groups.google.com/group/redis-db.
> >> For more options, visit https://groups.google.com/d/optout.


> > --
> > You received this message because you are subscribed to the Google
Groups
> "Redis DB" group.
> > To unsubscribe from this group and stop receiving emails from it, send
an

> > To post to this group, send email to redi...@googlegroups.com.
> > Visit this group at https://groups.google.com/group/redis-db.
> > For more options, visit https://groups.google.com/d/optout.



> --
> Salvatore 'antirez' Sanfilippo
> open source developer - Redis Labs https://redislabs.com

> "If a system is to have conceptual integrity, someone must control the
> concepts."
>          — Fred Brooks, "The Mythical Man-Month", 1975.



--
Salvatore 'antirez' Sanfilippo
open source developer - Redis Labs https://redislabs.com

"If a system is to have conceptual integrity, someone must control the
concepts."
        — Fred Brooks, "The Mythical Man-Month", 1975.

--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to redis-db+unsubscribe@googlegroups.com.

To post to this group, send email to redi...@googlegroups.com.
Visit this group at https://groups.google.com/group/redis-db.
For more options, visit https://groups.google.com/d/optout.

--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to redis-db+unsubscribe@googlegroups.com.

Salvatore Sanfilippo

unread,
May 7, 2018, 3:52:22 PM5/7/18
to redi...@googlegroups.com
Hello Denis,

I see things differently, thanks for trying, but I actually believe that
supporting RESPv2 and RESPv3 in the same client is very simple.
You basically have a property in the object called protover. Note that most
types are backward compatible if not for the LF vs CRLF, this is trivial to
do, read 1 byte or two, based on the version.

All the other types that require a conversion are specific of RESPv3, so
there there are no RESPv2 code paths. You may want just to assert that you
are not processing RESP3 specific types if protover == 2.

Sending commands is the same if not for the CRLF... Also the Pub/Sub
dispatching can be copied almost verbatim and will be called from two code
paths, one is the Pub/Sub mode, which is RESP2 specific, and the other is
the more general dispatched of push messages of RESP3.

I don't see any complexity, and I don't want to support RESP2 forever, so
I'll move forward by completely not implementing RESP2 in Redis 6. I
believe that the clients ecosystem will rapidly adapt because actually the
work to do, compared to the time they have to adapt is large, moreover many
clients that do not receive commits for ages are almost better if they
completely are terminated by the protocol switch, because they give a false
sense of having support while there is actually no real support. At the
same time new RESP3 only clients will emerge, or some will be just adapted.

I understand there are other POVs and they are respectable, but I don't
really agree on what you wrote and on the other opinions of the same sound.

Cheers,
Salvatore
>>> > >> an email to redis-db+u...@googlegroups.com.
>>> > >> >> To post to this group, send email to redi...@googlegroups.com.
>>> > >> >> Visit this group at https://groups.google.com/group/redis-db.
>>> > >> >> For more options, visit https://groups.google.com/d/optout.


>>> > >> > --
>>> > >> > You received this message because you are subscribed to the
Google
>>> > Groups
>>> > >> "Redis DB" group.
>>> > >> > To unsubscribe from this group and stop receiving emails from it,
>>> send
>>> > an
>>> > >> email to redis-db+u...@googlegroups.com.
>>> > >> > To post to this group, send email to redi...@googlegroups.com.
>>> > >> > Visit this group at https://groups.google.com/group/redis-db.
>>> > >> > For more options, visit https://groups.google.com/d/optout.



>>> > >> --
>>> > >> Salvatore 'antirez' Sanfilippo
>>> > >> open source developer - Redis Labs https://redislabs.com

>>> > >> "If a system is to have conceptual integrity, someone must control
the
>>> > >> concepts."
>>> > >> — Fred Brooks, "The Mythical Man-Month", 1975.

>>> > >> --
>>> > >> You received this message because you are subscribed to the Google
>>> > Groups "Redis DB" group.
>>> > >> To unsubscribe from this group and stop receiving emails from it,
send
>>> > an email to redis-db+u...@googlegroups.com.
>>> > >> To post to this group, send email to redi...@googlegroups.com.
>>> > >> Visit this group at https://groups.google.com/group/redis-db.
>>> > >> For more options, visit https://groups.google.com/d/optout.


>>> > > --
>>> > > You received this message because you are subscribed to the Google
>>> Groups
>>> > "Redis DB" group.
>>> > > To unsubscribe from this group and stop receiving emails from it,
send
>>> an
>>> > email to redis-db+u...@googlegroups.com.
>>> > > To post to this group, send email to redi...@googlegroups.com.
>>> > > Visit this group at https://groups.google.com/group/redis-db.
>>> > > For more options, visit https://groups.google.com/d/optout.



>>> > --
>>> > Salvatore 'antirez' Sanfilippo
>>> > open source developer - Redis Labs https://redislabs.com

>>> > "If a system is to have conceptual integrity, someone must control the
>>> > concepts."
>>> > — Fred Brooks, "The Mythical Man-Month", 1975.



>>> --
>>> Salvatore 'antirez' Sanfilippo
>>> open source developer - Redis Labs https://redislabs.com

>>> "If a system is to have conceptual integrity, someone must control the
>>> concepts."
>>> — Fred Brooks, "The Mythical Man-Month", 1975.

>>> --
>>> You received this message because you are subscribed to the Google
Groups "Redis DB" group.
>>> To unsubscribe from this group and stop receiving emails from it, send
an email to redis-db+u...@googlegroups.com.
>>> To post to this group, send email to redi...@googlegroups.com.
>>> Visit this group at https://groups.google.com/group/redis-db.
>>> For more options, visit https://groups.google.com/d/optout.

>> --
>> You received this message because you are subscribed to the Google
Groups "Redis DB" group.
>> To unsubscribe from this group and stop receiving emails from it, send
an email to redis-db+u...@googlegroups.com.
>> To post to this group, send email to redi...@googlegroups.com.
>> Visit this group at https://groups.google.com/group/redis-db.
>> For more options, visit https://groups.google.com/d/optout.


> --
> You received this message because you are subscribed to the Google Groups
"Redis DB" group.
> To unsubscribe from this group and stop receiving emails from it, send an
email to redis-db+u...@googlegroups.com.

Daniel Hochman

unread,
May 7, 2018, 4:13:32 PM5/7/18
to Redis DB
Attributes are awesome! Very happy to see this in the protocol. I noticed the spec does mention some detail of the server's implementation of RESP3, specifically that the server will continue to only accept arrays for requests. This may not be the right forum for discussion on this point since it goes beyond protocol and into implementation. I am wondering if we can potentially have the server allow attributes on the request.

For proxy developers it will be very helpful to include metadata on both the request and the response, similar to HTTP headers. The proxy can intercept per-request metadata and read out a retry policy, a consistency requirement, tracing spans, etc. We have been thinking of overloading the protocol to handle this for some time. Of course, since we have a proxy we can do it without server support and strip out attribute-like data before passing the request on to the server. However, it would be nice to have the server allow and ignore request attributes for compatibility purposes and the upstreaming of open-source client functionality that can handle such communication. Such a feature could also prove useful for modules if they want to allow client directives in attributes.

Thanks,
Daniel @ Lyft

Salvatore Sanfilippo

unread,
May 7, 2018, 5:38:21 PM5/7/18
to redi...@googlegroups.com
Hi Daniel,

On Mon, May 7, 2018 at 10:13 PM Daniel Hochman <dan...@runops.com> wrote:

> I am wondering if we can potentially have the server allow attributes on
the request.

I see how this could be useful, so far I don't have a so big use case in
order to justify doing this, but the good thing is that in case we want at
a latter point a more colorful client->server semantic, we could do it. For
instance one thing that makes attributes tempting is to set keys attributes
that can later be retrieved with the key. However for space concerns, the
key attributes would reuse some spare bits here and there, so there would
be probably a fixed number of fixed attributes that you can set, and later
the server may report the attributes only if non-zero. In such case
however, probably it's ok to go for the SETATTRIB command or something like
that. This makes the client->server chat still a command based experience
which has certain advantages.

> For proxy developers it will be very helpful to include metadata on both
the request and the response, similar to HTTP headers. The proxy can
intercept per-request metadata and read out a retry policy, a consistency
requirement, tracing spans, etc. We have been thinking of overloading the
protocol to handle this for some time. Of course, since we have a proxy we
can do it without server support and strip out attribute-like data before
passing the request on to the server. However, it would be nice to have the
server allow and ignore request attributes for compatibility purposes and
the upstreaming of open-source client functionality that can handle such
communication. Such a feature could also prove useful for modules if they
want to allow client directives in attributes.

That's an interesting pattern indeed. What makes me worried is that the
current attribute implementation of RESP3 does not make the request being
able to be *wrapped* into the attribute envelope, so the proxy may turn
being a bit more complex in order to remember the state.

A potential option to model this could be the following:

MULTI
ECHO my-attribs
... some command ...
EXEC

Let's say that right now I've no strong plans to go in that direction, that
could be useful but is at the limits of the complexity I would like to add
right now. However at some point things like that could be considered if we
find, along the way, that the power of the client->server communication
path is still missing.

However note that many of the things in RESP3 basically originated like 5
years ago. It was kinda clear ASAP that there was some big limitation in
RESP2. In the sending part instead things are a bit smoother. Not because
there are no limits, but because in some way the semantical content of
commands being so limited, allows the server to inspect everything before
execution, do cluster redirections, and so forth, so the limit of sending
just commands turned out to be some kinda of strength.

Cheers,
Salvatore


> Thanks,
> Daniel @ Lyft

> On Monday, May 7, 2018 at 7:38:18 AM UTC-7, Salvatore Sanfilippo wrote:

>> Hello, the following is a draft describing the new Redis protocol, RESP3:

>> https://gist.github.com/antirez/2bc68a9e9e45395e297d288453d5d54c

>> This will be implemented after many months of thinking more about the
>> design, so please, let's use this thread to collect feedbacks. The RESP3
>> protocol does not really want to get too complicated compared to the
>> current topic, but certain limitations of the current protocol are
evident
>> for years now... and should be addressed.

>> Thanks for any feedback,
>> Salvatore

>> --
>> Salvatore 'antirez' Sanfilippo
>> open source developer - Redis Labs https://redislabs.com

>> "If a system is to have conceptual integrity, someone must control the
>> concepts."
>> — Fred Brooks, "The Mythical Man-Month", 1975.

> --
> You received this message because you are subscribed to the Google Groups
"Redis DB" group.
> To unsubscribe from this group and stop receiving emails from it, send an
email to redis-db+u...@googlegroups.com.
> To post to this group, send email to redi...@googlegroups.com.
> Visit this group at https://groups.google.com/group/redis-db.
> For more options, visit https://groups.google.com/d/optout.



b...@malec.us

unread,
May 8, 2018, 2:50:41 AM5/8/18
to redi...@googlegroups.com
Salvatore, I like the new data types, especially the attribute, map, and push types. I agree with the others that there will be difficulties transitioning between protocols, but currently I don't have any great suggestions. It would seem to me that for the time being a connection to the Redis server should default to RESP2 and change to RESP3 on client request. I would think (hope?) most clients would want to support the RESP3 improvements so support would arrive pretty quickly.

One question, though: you mentioned the client should send a PING command to determine if the server supported RESP2 or RESP3--should the client terminate the PING command with <CRLF> or <LF>? Wouldn't the client already know if the server supported RESP3 before it could make that determination?

As you know, my big interest is client-side caching, and I know it's too early to start discussing that but I am interested in what you're thinking as it could impact RESP3. Are you thinking that the client would "subscribe" to specific key changes, making that decision based on the key's popularity attribute? Or would the Redis server just send push messages for any changes to keys above a certain popularity level? Also have you considered having an alternate numeric ID for keys, which you could reference in push messages in place of the actual key? That would keep the message short, even in the case of long key names. I think that would be a good use of attributes, but is that something you'd want to send with every time a key was updated?

Also I like Daniel's idea of attributes with requests. Again thinking of client-side caching, one thing we've noticed is that once data gets into the client-side cache, Redis will see very few requests for that key even if it's actually being requests hundreds of times a second. Perhaps the client could use attributes to send "hints" to Redis about key popularity, e.g. "this key was requested 10,000 times in the last minute". Then the key statistics maintained by Redis could more accurately reflect client demand. Definitely not something necessary, but could be a nice-to-have.

Looking forward to watching this discussion evolve 😊

Ben

yos...@gmail.com

unread,
May 8, 2018, 3:00:14 AM5/8/18
to Redis DB
Hi Salvatore, a more expressive protocol that supports common types is a great idea, it's easy to immediately see how it solves lots of common problems and simplifies clients.

When reading the spec it occurred to me that it may be better to treat RESP3 as a protocol stack, with proper layers: serialization of primitives, session layer (handshake, state, etc) and an app layer (especially as with Lua and modules there is little control over how it's used).  If we follow this then the Hello special type may not be needed, it can use any other type as part of a well defined handshake process implemented on top of the serialization layer protocol.

Variable length (streaming) strings and aggregates are really much needed, in one place the spec says they are supported but I couldn't find how or an example.

The definition of aggregates is extremely permissive, which I fear may add unnecessary complexity for clients that implement it.  For example, arrays of different arbitrary types, a set that has a error blob element, etc.  To me, a good baseline may be JSON - if I'm able to convert RESP3 aggregate to JSON and back without losing expressive information that's probably good enough.

Moving from CRLF to LF, I have a feeling it may be a pain in the a** in many cases (old implementations being migrated, code reuse, etc.) that may not justify the savings.

Marc Gravell

unread,
May 8, 2018, 4:31:28 AM5/8/18
to redi...@googlegroups.com
I was not clear about that, you can use *anything*, both immediately after the connection or even in a lazy way, that is, in the reply reading code as soon as you get "@" as the first type byte, you do the switch to the RESP3 protocol internally.

This suggests that the server is always going to switch to RESP 3 without reference to the client. Is this correct? i.e. is the proposal that some future redis server version would switch to RESP 3 and *only* RESP 3?

I'm not saying that's impossible, but that is a very significant change and will obviously break clients and tooling wholesale; it is kinda hostile - but bold. But it feels like this is something that could be done electively with some kind of negotiation, i.e. client: "hi, I speak 3 or 2", server: "3's good, here you go" or server: "ERR unknown command" (or whatever).

It is also possible I've misunderstood.

Marc

Salvatore Sanfilippo

unread,
May 8, 2018, 4:51:57 AM5/8/18
to redi...@googlegroups.com
Hi Ben,

On Tue, May 8, 2018 at 8:50 AM <b...@malec.us> wrote:
Salvatore, I like the new data types, especially the attribute, map, and push types.  I agree with the others that there will be difficulties transitioning between protocols, but currently I don't have any great suggestions.  It would seem to me that for the time being a connection to the Redis server should default to RESP2 and change to RESP3 on client request.  I would think (hope?) most clients would want to support the RESP3 improvements so support would arrive pretty quickly.

Yes I also really want certain new things to enter the protocol ASAP. I talk about the Map type and other stuff with other folks in the Redis community for about 5 years at this point!

I'll reply to Marc's email about this topic of protocol transition, in order to provide a clarification. Thanks for the feedback.
 
One question, though:  you mentioned the client should send a PING command to determine if the server supported RESP2 or RESP3--should the client terminate the PING command with <CRLF> or <LF>?  Wouldn't the client already know if the server supported RESP3 before it could make that determination?

There are two alternatives about that. One is to use the "inline" protocol to send the first ping, which is still supported by RESP3. It is basically the ability to just send "PING\n" or "PING\r\n" (the inline protocol supports both).
The other is to make the RESP3 parser flexible and accept in input "\r\n" terminated elements. I'm less happy with that possibility because I don't like the "be open on what you accept and strict on what you send" way of thinking. Specifications are there to be honored to the point IMHO. But perhaps in that case there to be flexible make sense.

As you know, my big interest is client-side caching, and I know it's too early to start discussing that but I am interested in what you're thinking as it could impact RESP3.  Are you thinking that the client would "subscribe" to specific key changes, making that decision based on the key's popularity attribute?  Or would the Redis server just send push messages for any changes to keys above a certain popularity level?  Also have you considered having an alternate numeric ID for keys, which you could reference in push messages in place of the actual key?  That would keep the message short, even in the case of long key names.  I think that would be a good use of attributes, but is that something you'd want to send with every time a key was updated?

I'll open a new topic about this, but basically as a first draft I combined the ideas you exposed at Redis Conf with server-side tracking, so the server knows the hash slots the client could have keys into, so it can just send a subset of invalidation messages. More on that in the next topic, it's too important and needs a full discussion :-D

Also I like Daniel's idea of attributes with requests.  Again thinking of client-side caching, one thing we've noticed is that once data gets into the client-side cache, Redis will see very few requests for that key even if it's actually being requests hundreds of times a second.  Perhaps the client could use attributes to send "hints" to Redis about key popularity, e.g. "this key was requested 10,000 times in the last minute".  Then the key statistics maintained by Redis could more accurately reflect client demand.  Definitely not something necessary, but could be a nice-to-have.

It's useful to ping back the server with info, but I've the feeling that sending additional info about keys with a command is more uniform.
 

Looking forward to watching this discussion evolve 😊

Me too! Thanks

Salvatore Sanfilippo

unread,
May 8, 2018, 5:02:22 AM5/8/18
to redi...@googlegroups.com
Hello Yossi,

On Tue, May 8, 2018 at 9:00 AM <yos...@gmail.com> wrote:

> Hi Salvatore, a more expressive protocol that supports common types is a
great idea, it's easy to immediately see how it solves lots of common
problems and simplifies clients.

Thanks, I agree and if you look at clients like Redigo or Redic, you think,
hey those clients are simple and neat, but how they could be simpler? Now
we have a way. I hope that also this will also will open the way for new
clients to be simpler in general from the POV of the way they mediate the
API.

> When reading the spec it occurred to me that it may be better to treat
RESP3 as a protocol stack, with proper layers: serialization of primitives,
session layer (handshake, state, etc) and an app layer (especially as with
Lua and modules there is little control over how it's used). If we follow
this then the Hello special type may not be needed, it can use any other
type as part of a well defined handshake process implemented on top of the
serialization layer protocol.

The problem is that RESP3 can be made to do anything, but RESP2 can't be
changed, so it's not clear how this handshake works. Moreover I wanted
really the hello message to be "push style" because I don't like much the
idea of using round trip times to perform an handshake. This way AFAIK
accept() returns, we write to the socket ASAP, and the client should be
able to read the reply immediately and go on, which is a latency win.

> Variable length (streaming) strings and aggregates are really much
needed, in one place the spec says they are supported but I couldn't find
how or an example.

If you check the latest TODO session, it's a work in progress, I had no
time to finish that part, but will do soon.

> The definition of aggregates is extremely permissive, which I fear may
add unnecessary complexity for clients that implement it. For example,
arrays of different arbitrary types, a set that has a error blob element,
etc. To me, a good baseline may be JSON - if I'm able to convert RESP3
aggregate to JSON and back without losing expressive information that's
probably good enough.

Arrays of different types are already in RESP2 and actively used by Redis,
so basically the only possible change is to say that keys in maps should
not be aggregate data types. But anyway, I think that mostly nobody could
use it, and clients for languages where this is not trivial to model
(aggregate data types as keys) can just raise an error when this happens.
Redis for sure will not use such features, but in modules, to prevent
actively the API from producing such beasts is hard, so I'll likely leave
it as an open possibility and just hint that servers producing the replies,
should avoid to use aggregate data types. But I don't see myself doing
complex things inside Redis to avoid Lua/modules from doing that.

> Moving from CRLF to LF, I have a feeling it may be a pain in the a** in
many cases (old implementations being migrated, code reuse, etc.) that may
not justify the savings.

Yes, this is a good point IMHO, food for thoughts. If we stay CRLF clients
implementing both the protocols will be simpler and sending the first PING
is a no brainer. However we'll remain with this CRLF thing forever. A
tradeoff to consider.

Thanks for the inputs,
Salvatore

> On Monday, May 7, 2018 at 5:38:18 PM UTC+3, Salvatore Sanfilippo wrote:

>> Hello, the following is a draft describing the new Redis protocol, RESP3:

>> https://gist.github.com/antirez/2bc68a9e9e45395e297d288453d5d54c

>> This will be implemented after many months of thinking more about the
>> design, so please, let's use this thread to collect feedbacks. The RESP3
>> protocol does not really want to get too complicated compared to the
>> current topic, but certain limitations of the current protocol are
evident
>> for years now... and should be addressed.

>> Thanks for any feedback,
>> Salvatore

>> --
>> Salvatore 'antirez' Sanfilippo
>> open source developer - Redis Labs https://redislabs.com

>> "If a system is to have conceptual integrity, someone must control the
>> concepts."
>> — Fred Brooks, "The Mythical Man-Month", 1975.

> --
> You received this message because you are subscribed to the Google Groups
"Redis DB" group.
> To unsubscribe from this group and stop receiving emails from it, send an
email to redis-db+u...@googlegroups.com.
> To post to this group, send email to redi...@googlegroups.com.
> Visit this group at https://groups.google.com/group/redis-db.
> For more options, visit https://groups.google.com/d/optout.



Salvatore Sanfilippo

unread,
May 8, 2018, 5:08:40 AM5/8/18
to redi...@googlegroups.com
Hello Marc,

and here I really want to reply everybody, not just you. If you look at
this transition asymptotically, things start to have a completely different
aspect:

In 2 years from now, Redis 7 would anyway finally remove support for RESP2,
but clients will surely *still* implement RESP2 because we know for history
now that a lot of important shops remain in Redis old 3, 4 years, since it
works, there are mostly no security concerns inside many production
environments where Redis is totally obscured somewhere, and nobody wants to
update what works and is stable.

So we have two possibilities: make both the server and the client handle
the two protocols, and anyway find that when we switch to RESP3 only at
some point, a lot of people will be in the same situation of having a
client not supporting it.

Or... we can just switch asap to RESP3 in Redis 6.0, and at least save the
server from implementing both the protocols.
Now if you consider that:

1) Anyway clients have to implement both.
2) That server side implementing both is much more complex, and requires
conditionals in almost every command.

What is the gain in having also the server switch to a stage where both are
implemented? No less work for clients. Strongly delayed adoption, and when
this topic will no longer be hot, we switch to RESP3 only and a lot of
things will break randomly. At least now it's an hot topic. This is not
going to impact the server OR the clients. It's going to impact the clients
and the server, or just the clients, I would pick the second one :-)

Cheers,
Salvatore

Marc Gravell

unread,
May 8, 2018, 6:33:00 AM5/8/18
to redi...@googlegroups.com
I get what you're saying, and I understand the logic in terms of the server, but it does seem pretty brutal to hard kill so many clients until they update. You can have pretty reasonable confidence that the major clients will update, but some never will - it seems to *unnecessarily* fragment the available clients, which could in turn make it hard for people to adopt server 6, which in turn impacts whether clients update (feedback loop).

As I said: it is bold. It might work fine and everything is peachy... but it might also cause huge problems and barriers.

It feels like most of the changes proposed could be done with a reasonably cheap level of back-compat - for example attributes simply evaporate, sets / arrays etc all serialize as arrays.

Complicated.

yos...@gmail.com

unread,
May 8, 2018, 7:04:37 AM5/8/18
to Redis DB


On Tuesday, May 8, 2018 at 12:02:22 PM UTC+3, Salvatore Sanfilippo wrote:
Hello Yossi,

On Tue, May 8, 2018 at 9:00 AM <yos...@gmail.com> wrote:

> Hi Salvatore, a more expressive protocol that supports common types is a
great idea, it's easy to immediately see how it solves lots of common
problems and simplifies clients.

Thanks, I agree and if you look at clients like Redigo or Redic, you think,
hey those clients are simple and neat, but how they could be simpler? Now
we have a way. I hope that also this will also will open the way for new
clients to be simpler in general from the POV of the way they mediate the
API.

> When reading the spec it occurred to me that it may be better to treat
RESP3 as a protocol stack, with proper layers: serialization of primitives,
session layer (handshake, state, etc) and an app layer (especially as with
Lua and modules there is little control over how it's used).  If we follow
this then the Hello special type may not be needed, it can use any other
type as part of a well defined handshake process implemented on top of the
serialization layer protocol.

The problem is that RESP3 can be made to do anything, but RESP2 can't be
changed, so it's not clear how this handshake works. Moreover I wanted
really the hello message to be "push style" because I don't like much the
idea of using round trip times to perform an handshake. This way AFAIK
accept() returns, we write to the socket ASAP, and the client should be
able to read the reply immediately and go on, which is a latency win.

The reality is that most clients/apps will already have at least one roundtrip (AUTH), and quite a few I've seen (or implemented) also PING to validate connectivity and trigger authentication on demand.  So if it's possible to come up with a clean and neat design I don't think there will be a regression here in terms of performance if the handshake is limited to a single ClientHello/ServerHello iteration.


> Variable length (streaming) strings and aggregates are really much
needed, in one place the spec says they are supported but I couldn't find
how or an example.

If you check the latest TODO session, it's a work in progress, I had no
time to finish that part, but will do soon.

My bad, thanks.


> The definition of aggregates is extremely permissive, which I fear may
add unnecessary complexity for clients that implement it.  For example,
arrays of different arbitrary types, a set that has a error blob element,
etc.  To me, a good baseline may be JSON - if I'm able to convert RESP3
aggregate to JSON and back without losing expressive information that's
probably good enough.

Arrays of different types are already in RESP2 and actively used by Redis,
so basically the only possible change is to say that keys in maps should
not be aggregate data types. But anyway, I think that mostly nobody could
use it, and clients for languages where this is not trivial to model
(aggregate data types as keys) can just raise an error when this happens.
Redis for sure will not use such features, but in modules, to prevent
actively the API from producing such beasts is hard, so I'll likely leave
it as an open possibility and just hint that servers producing the replies,
should avoid to use aggregate data types. But I don't see myself doing
complex things inside Redis to avoid Lua/modules from doing that.

Maybe I'm wrong here, but I think the cases you refer to in RESP2 are logically an array of objects.  If the implementation is not trivial it can be left to the user but I think if you agree it's not a useful feature I suggest to narrow down the protocol specification so if things broken it's clear on which side they need to be fixed...

zhao zhao

unread,
May 8, 2018, 7:08:43 AM5/8/18
to redi...@googlegroups.com
It seems like redis with RESP3 is a new product not just a new version, just as RESP3 is not an update based on RESP v2, it's really a big change.

To unsubscribe from this group and stop receiving emails from it, send an email to redis-db+unsubscribe@googlegroups.com.

Salvatore Sanfilippo

unread,
May 8, 2018, 7:51:29 AM5/8/18
to redi...@googlegroups.com
On Tue, May 8, 2018 at 12:33 PM Marc Gravell <marc.g...@gmail.com> wrote:

> I get what you're saying, and I understand the logic in terms of the
server, but it does seem pretty brutal to hard kill so many clients until
they update.

Yes but this soon or later is needed, we can't support RESP2 forever
otherwise many clients will simply never update, nor there will be enough
reason for creating new ones if certain clients are totally abandoned.
Moreover a point could be made about abandoned clients to really not be
able to serve any production-level user.

> You can have pretty reasonable confidence that the major clients will
update, but some never will - it seems to *unnecessarily* fragment the
available clients, which could in turn make it hard for people to adopt
server 6, which in turn impacts whether clients update (feedback loop).

My claim is that abandoned clients not updating could be in some way a very
small loss, because of the reasons above.

> As I said: it is bold. It might work fine and everything is peachy... but
it might also cause huge problems and barriers.

We already saw this, when Redis was a lot less popular. After 1.2 that had
both the supports, Redis 2.0 deleted the support and the client ecosystem
adapted. I think the same will happen, but faster because:

1. RESP1 -> RESP2 did not provide the same benefits than going RESP3. To
return coherent data types without filtering is really a good thing.
2. Redis is now more popular.
3. We are going, as you suggested, to adopt a "grid" of features in the
client page (I already talked with Fabio Nicotra about that, and he'll
implement it in the next weeks). So we can bring more visibility in what
clients really do, to show that not every client is the same, and this may
speedup the process of deprecating certain clients in favor of new ones.

> It feels like most of the changes proposed could be done with a
reasonably cheap level of back-compat - for example attributes simply
evaporate, sets / arrays etc all serialize as arrays.

It's not impossible for sure, but given that we are going to deprecate
anyway RESP2 at some point, I would force the move here to make sure the
end users are more likely to benefit from RESP3 changes ASAP, and save the
above work, which why not huge is surely sizable. And perhaps in 1 year
we'll be here again with a similar situation of many clients not yet
updated, so what to do, to to take it more or break things anyway?

> Complicated.

There is no definitely perfect solution, so I would go for the cleanest one
at least :-)

Cheers,
Salvatore

Salvatore Sanfilippo

unread,
May 8, 2018, 7:56:56 AM5/8/18
to redi...@googlegroups.com
On Tue, May 8, 2018 at 1:04 PM <yos...@gmail.com> wrote:

> The reality is that most clients/apps will already have at least one
roundtrip (AUTH), and quite a few I've seen (or implemented) also PING to
validate connectivity and trigger authentication on demand. So if it's
possible to come up with a clean and neat design I don't think there will
be a regression here in terms of performance if the handshake is limited to
a single ClientHello/ServerHello iteration.

Makes sense, but for my personal taste, handshaking is already over the
line. I see the current push hello message as a very good solution
honestly. It's a shame to make this more complex from my POV.



> Maybe I'm wrong here, but I think the cases you refer to in RESP2 are
logically an array of objects. If the implementation is not trivial it can
be left to the user but I think if you agree it's not a useful feature I
suggest to narrow down the protocol specification so if things broken it's
clear on which side they need to be fixed...

Sorry this point is not clear for me, I think I'm not understanding what
you say. I can describe what is the difference between the two protocols in
order to make this more clear.

Basically in RESP2 you can have Array of any possible type, including
arrays of arrays that have inside anything, heterogeneously.
RESP3 in this regard is the same, and the Set type is exactly like the
Array type.
Let's assume that it is obvious that we need to emit Arrays having as sub
types Sets, Maps, ... and everything else, because of MULTI semantics, and
because this is handled by clients without having to do any effort, so,
what's left? AFAIK the only thing left is the Map type keys. So, is your
sole concern the fact that Map types should not be aggregates, but should
be, for instance, only single values, or even more strictly, strings?

Thanks,
Salvatore

Marc Gravell

unread,
May 8, 2018, 8:58:59 AM5/8/18
to redi...@googlegroups.com
First, a quickie (second email inbound in a sec with more...):

I don't think there will be a regression here in terms of performance if the handshake is limited to
a single ClientHello/ServerHello iteration.

To echo that; a lot of clients will already be doing things like "CLIENT SETNAME", "INFO" (perhaps section-restricted) and a few other things. In many cases (not all), all this initial connect stuff will be pipelined *and* use local buffering such that it all goes in a single output packet, so: I would expect the performance penalty of an explicit handshake to be negligible in many real cases.
Regards,

Marc

Marc Gravell

unread,
May 8, 2018, 9:08:11 AM5/8/18
to redi...@googlegroups.com


If I can repeat one of the points I made at redisconf; one of the larger barriers for library authors adding *even minor features* is that there can be a surprising amount of work involved checking that the solution you have come up with is a reasonable fit to the problem, and verifying that it works in all the edge cases. This extends even to verifying that a PR (if someone else does the leg-work) meets the intent. It is a huge "ask" to hope library authors will leap on that immediately, especially if they're not currently at a time when they're considering updating their servers locally.

I'm also thinking ahead to what happens to consuming code. There's 3 scenarios I can see without thinking much:

1: compile time typing (interfaces, strong contracts, etc), but where the existing code already understands the intent manually on a command-by-command basis, and already parses the arrays into lists/sets/etc: outcome - the parsing code perhaps gets simpler with RESP3 (although it needs to retain the RESP2 version for older servers), no other impact

2: compile time typing (interfaces, strong contracts, etc), but where the existing code hands back naked arrays that mimic RESP2: outcome - either the client has to ignore the semantic data and hand back the naked array again, or it needs to smash compatibility, breaking all the consumers

3: dynamic typing (ECMA-script, etc): similar problem as #2; if the client library starts respecting the semantic data and handing back semantically relevant types (sets, arrays, etc) - then any **existing** code is now broken **at runtime**, as it might be using methods that no longer exist (a "set" is different to an "array", for example).

Given the impact of breaking *all* of their existing users and the inevitable flood of support tickets, I can see most clients authors from #2 and #3 saying "uh, nope; to hell with that - I'm just going to ignore the metadata and return what I've always returned".

As a result, the only sane way for most clients to implement this would be to double their API surface; as in "here's the 'legacy' method how it used to work", and "here's the RESP 3 version". You'd probably need this even for Lua in redis for EVAL/EVALSHA: you'd need one version of redis.call for "old" Lua scripts to use, where things come back as arrays, and a **different** redis.call3 (naming is hard) for new semantic-aware Lua scripts to use, which might return more semantic data, attributes, etc. How much of an impact this is depends on the nature of the client, I guess; if you only have a single "run this command" method, that might be reasonable, but: that is *not* how all clients are written.

And: this is also making the assumption that all client authors will realise the impact of changing the return types to match the semantic data; I expect that a few would simply update, and then boom: broken users, where they need fundamentally different application code to talk to different redis versions - exactly the problem that libraries are meant to solve, not cause.

So; there's some huge barriers here that go beyond just making some quick protocol changes in a few libraries. I'm not saying revving the protocol is a bad thing or undesirable - I really like the shape of the changes under discussion; I just think there's a lot of important things to consider here.

Marc


On Tue, 8 May 2018 at 12:56, Salvatore Sanfilippo <ant...@gmail.com> wrote:


--
Regards,

Marc

Salvatore Sanfilippo

unread,
May 8, 2018, 11:16:18 AM5/8/18
to redi...@googlegroups.com
Hello Marc,

in general I agree with you about many points (but notably not about the
only sane thing to do is to provide two separated interfaces), but all this
if feel is not related to the fact of Redis supporting or not two versions
at the same time.
Anyway at some point clients will need to update. What we can do is two
things:

1. To provide a long time in which RESP3 is available in unstable, but not
released as any release candidate. Let's say in the 6 months - 1 year range.
2. To provide a lot of documentation for client developers. One of the
current worst things in the client side is that there is no way to tell if
you are doing good or not by doing certain things. I believe we need a
detailed document about how certain things should be implemented, what a
client normally should do when the connection is broken, in type
conversion, in MULTI/EXEC, pipelining, Cluster, and so forth.

A lot of time, an implementation of the server you can test against, and
more information, should improve the state significantly.

About providing two interfaces, I've the feeling that clients for highly
dynamic languages where the return value is untyped, dual support makes a
lot of sense... While for clients that will require breaking the API, they
could do the same thing the server will do, and at some point just support
RESP3 in never versions, while continuing to fix critical bugs in the older
versions, so that there is a TLS version supporting RESP2, only critical
bugs fixed, and the RESP3 version with the new API and the new developments.

Cheers,
Salvatore

Salvatore Sanfilippo

unread,
May 8, 2018, 11:19:23 AM5/8/18
to redi...@googlegroups.com
But what is the advantage of the explicit handshake? That's the point IMHO.
With the explicit handshake it will be hard even to change the format in
which clients communicate with the server in the future, because you have
to ask for handshake, and I would not go for a special form just for
handshake, it should be a normal command like any other. This is already a
disadvantage without ever gaining anything so far. I can understand if we
implement a new "HELLO" command that is used in order to retrieve more in
depth things about the server state, and at the same time set the client
name, and so forth, but this is like a second step that is to fix the fact
that INFO is not the right interface to call. But from the POV of protocol
and server discovery, the server presenting itself looks more obvious to me.

yos...@gmail.com

unread,
May 8, 2018, 12:14:53 PM5/8/18
to Redis DB


On Tuesday, May 8, 2018 at 2:56:56 PM UTC+3, Salvatore Sanfilippo wrote:
On Tue, May 8, 2018 at 1:04 PM <yos...@gmail.com> wrote:

> The reality is that most clients/apps will already have at least one
roundtrip (AUTH), and quite a few I've seen (or implemented) also PING to
validate connectivity and trigger authentication on demand.  So if it's
possible to come up with a clean and neat design I don't think there will
be a regression here in terms of performance if the handshake is limited to
a single ClientHello/ServerHello iteration.

Makes sense, but for my personal taste, handshaking is already over the
line. I see the current push hello message as a very good solution
honestly. It's a shame to make this more complex from my POV.

My point here is not how the handshake implemented, but that it's part of a higher level session protocol spec, so it should not have a dedicated serialization format.  I value a lot separation of transport/serialization and session (and also session/app).


> Maybe I'm wrong here, but I think the cases you refer to in RESP2 are
logically an array of objects.  If the implementation is not trivial it can
be left to the user but I think if you agree it's not a useful feature I
suggest to narrow down the protocol specification so if things broken it's
clear on which side they need to be fixed...

Sorry this point is not clear for me, I think I'm not understanding what
you say. I can describe what is the difference between the two protocols in
order to make this more clear.

Basically in RESP2 you can have Array of any possible type, including
arrays of arrays that have inside anything, heterogeneously.
RESP3 in this regard is the same, and the Set type is exactly like the
Array type.
Let's assume that it is obvious that we need to emit Arrays having as sub
types Sets, Maps, ... and everything else, because of MULTI semantics, and
because this is handled by clients without having to do any effort, so,
what's left? AFAIK the only thing left is the Map type keys. So, is your
sole concern the fact that Map types should not be aggregates, but should
be, for instance, only single values, or even more strictly, strings?

MULTI was the use case I was looking to prove me wrong.  So as multi-type elements are already in use in RESP2, I agree with you there's no point to change that.

Salvatore Sanfilippo

unread,
May 9, 2018, 5:22:55 AM5/9/18
to redi...@googlegroups.com
On Tue, May 8, 2018 at 6:15 PM <yos...@gmail.com> wrote:

> My point here is not how the handshake implemented, but that it's part of
a higher level session protocol spec, so it should not have a dedicated
serialization format. I value a lot separation of transport/serialization
and session (and also session/app).

This is a very respectable POV, but if you read the RESP3 document, the
premises are the contrary, IMHO RESP3 makes sense because instead it
removes the barriers between all the three, turning something otherwise
more complex in something much simpler to understand/implement.
It's basically a different way to approach the problem...

However at least in one place, I pushed this forward too much, as noted by
Yao Yue on Twitter, that is: the Attribute type does not need to have its
own data type, but may be more flexible.
So I'm probably going to change this as: if the first byte is "|", whatever
type follows is an attribute of the reply. No need for it to be a Map with
a special first byte.

> MULTI was the use case I was looking to prove me wrong. So as multi-type
elements are already in use in RESP2, I agree with you there's no point to
change that.

Still your observation about Map keys IMHO is a sensible one that we should
consider, saying that probably aggregated data types as keys are wrong,
even if we can't enforce it easily in the API of Lua/Modules.

Thanks,
Salvatore

Mark Paluch

unread,
May 9, 2018, 10:29:51 AM5/9/18
to Redis DB
Hi Salvatore, 

I see similar points as Marc here:

1. I like in general the ideas and to extend the protocol. Having finally binary types and maps is a step in the right direction.

2. Having a push handshake is the first thing that will break with existing clients as they don't expect this kind of behavior. Introducing at least a command that generates a response allows verification of the connectivity. Even introduction in one of the next versions (5.x) would allow clients to adopt this new behavior and a make a smoother transition instead of a hard break.

3. Boldly removing support is a hard break for clients. Observing the client-ecosystem, Redis puts clients in charge to compensate for things that should stay in Redis itself simple. While this works to some extent, it's a huge ask for the community to adapt to whatever Redis is doing.

There are a lot of major and popular clients out there. Some of these are very widely adopted but their maintainers stopped maintenance or don't have time to maintain them anymore. Breaking support is a good reason to reconsider whether the underlying data store persistence technology solves more issues than it causes. On the other side, some major clients don't even have support for all Redis features because maintainers can't keep up with maintenance. Cleaning up the client-ecosystem might turn out well for well-maintained clients. For everybody else, it is a huge effort. 

Leaving clients without a viable alternative may work for the server side but then, why going down the RfC route at all if the points that hurt the most aren't addressed in a consumer-friendly way?

Cheers, 
Mark

Jay Rolette

unread,
May 9, 2018, 11:55:14 AM5/9/18
to redis
+100

--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to redis-db+unsubscribe@googlegroups.com.

Salvatore Sanfilippo

unread,
May 10, 2018, 4:19:20 PM5/10/18
to redi...@googlegroups.com
Hello Mark, thanks for the feedbacks:

On Wed, May 9, 2018 at 4:30 PM Mark Paluch <mpa...@paluch.biz> wrote:

> 1. I like in general the ideas and to extend the protocol. Having finally
binary types and maps is a step in the right direction.

Glad you think those are positive changes.

> 2. Having a push handshake is the first thing that will break with
existing clients as they don't expect this kind of behavior. Introducing at
least a command that generates a response allows verification of the
connectivity. Even introduction in one of the next versions (5.x) would
allow clients to adopt this new behavior and a make a smoother transition
instead of a hard break.

I want RESP3 to be right, not to be backward compatible. Consider that I
value backward compatibility to an incredible extent, to the point that
Redis is still API compatible with version 0.9, and that RDB files from
such an era can still be loaded.

However application level compatibility and internals/protocols are a
different matter. From that POV I think it's good to always change to aim
at the best. Now let's evaluate the technical merits. I believe that
actually a push banner is a good idea because it allows to break, in future
versions of RESP, everything without problems for the client to discover
what is happening. Anyway a client that can interoperate with RESP3, using
a client-initiated handshake or not, requires to be aware, so we are not
going to have backward compatibility just because there is an handshake
command. So receiving a push welcome message, means that after that, which
is the only thing that must be backward compatible for ever (and only for a
few fields!), the client can follow based on the "resp" attribute (a
number, in our case "3").

Also note that with user initiated handshake, the client may kinda work for
some time even if the protocol is different. When things are not compatible
you want things to fail fast. The push reply starting with an invalid
character also accomplishes this.

> 3. Boldly removing support is a hard break for clients. Observing the
client-ecosystem, Redis puts clients in charge to compensate for things
that should stay in Redis itself simple. While this works to some extent,
it's a huge ask for the community to adapt to whatever Redis is doing.

I don't think this respects the current reality. Of all the systems out
there Redis is the most client-friendly or in the top N for sure, the
project traditionally cared a lot about offloading the client to do too
much work. The Streams data type in Redis 5 are a good example, many things
provided could be modeled in the client.

There is another reason why what you are saying is basically not true in my
opinion: clients will anyway have to support RESP3 and RESP2, because the
support is going to be dropped like it happened in Redis 2.0 with RESP1
even if we take a double implementation for some time, but more simply
because to have a Redis 6 that has a double semantic of returning different
types depending on the configuration setting inside Redis is very confusing
for the users, so everybody should try to move forward to the new
semantics. So the work from the POV of the client is unavoidable.

The point is if this work should also be done on the server or not, and
that part can be avoided. Note that I'm not worried by doing such work,
it's not huge, it's only lame and ugly, this is why I don't want it.
Commands returning a different type depending on the context, client used,
and configuration, why? Just to delay the RESP3 adoption.

> There are a lot of major and popular clients out there. Some of these are
very widely adopted but their maintainers stopped maintenance or don't have
time to maintain them anymore. Breaking support is a good reason to
reconsider whether the underlying data store persistence technology solves
more issues than it causes. On the other side, some major clients don't
even have support for all Redis features because maintainers can't keep up
with maintenance. Cleaning up the client-ecosystem might turn out well for
well-maintained clients. For everybody else, it is a huge effort.

So here your reasoning is: there are environments using Redis just by
inertia, with an abandoned client, yet they'll upgrade the Redis server,
and will find that they need a new client, and will say: "Hey but we don't
need Redis!". This is a setup where it is ok for users to abandon Redis, if
they needed this call to action to remove something which is not useful.

I think that people that want to stay with Redis 5, that will be supported
for the next 2 years and will not have any protocol incompatibility, will
have no troubles at all, but in 2 years they need to understand if to stay
with Redis 5, that could be perfectly fine especially if those people are
running abandoned clients and are not willing to do any effort, or if they
want to upgrade to Redis 6 and use a new client.

Moreover note that some cleanup in the client space is not a bad thing. The
abandoned and under-supported clients that were often a few weeks projects
are causing a lot of harm in some way: the client is the interface for the
server, and sometimes the server looks like not working as expected because
the client is not a serious product but was an hobby project.

> Leaving clients without a viable alternative may work for the server side
but then, why going down the RfC route at all if the points that hurt the
most aren't addressed in a consumer-friendly way?

First because the RfC was about how to make RESP3 good, and the discussion
was unfortunately mostly oriented about how to retain RESP2. Second because
asking the POV of the community does not mean to change idea just by a
democratic process, otherwise Redis hashes would have expires in single
items, and Redis would output JSON. It's a process: you understand what
people have to say, and you check if this is aligned with what you want to
do.

For instance Yossi proposed to tale CRLF so that the clients will send
commands the same format, and this is a good idea, the RfC is useful so.
Yao told on Twitter, why on the Earth you want just maps as aux info, so
the "|" character is going to change into "whatever type follows is aux
info". So the RfC is useful for this, and also to have a trace about why
Redis may drop the support for RESP2. People may be happy or unhappy with
that, but at least there was a process and a justification (agreeable or
not).

Cheers,
Salvatore

> Cheers,
> Mark

> Am Montag, 7. Mai 2018 16:38:18 UTC+2 schrieb Salvatore Sanfilippo:

>> Hello, the following is a draft describing the new Redis protocol, RESP3:

>> https://gist.github.com/antirez/2bc68a9e9e45395e297d288453d5d54c

>> This will be implemented after many months of thinking more about the
>> design, so please, let's use this thread to collect feedbacks. The RESP3
>> protocol does not really want to get too complicated compared to the
>> current topic, but certain limitations of the current protocol are
evident
>> for years now... and should be addressed.

>> Thanks for any feedback,
>> Salvatore

>> --
>> Salvatore 'antirez' Sanfilippo
>> open source developer - Redis Labs https://redislabs.com

>> "If a system is to have conceptual integrity, someone must control the
>> concepts."
>> — Fred Brooks, "The Mythical Man-Month", 1975.

> --
> You received this message because you are subscribed to the Google Groups
"Redis DB" group.
> To unsubscribe from this group and stop receiving emails from it, send an
email to redis-db+u...@googlegroups.com.
> To post to this group, send email to redi...@googlegroups.com.
> Visit this group at https://groups.google.com/group/redis-db.
> For more options, visit https://groups.google.com/d/optout.



Pierre Chapuis

unread,
May 11, 2018, 4:39:16 AM5/11/18
to Redis DB
The RESP3 protocol is asymmetrical: only a subset can be sent by the client to the server, while the server can return the full set of types available. This is due to the fact that RESP is designed to send non structured commands like SET mykey somevalue or SADD myset a b c d. Such commands can be represented as arrays, where each argument is an array element, so this is the only type the client can send to a server.

I wonder if being symmetrical would not be a good thing for Redis as well, maybe sometimes just as an alternative to array commands.

Take HMSET, for instance. A lot of clients will have the signature HMSET(<key>, <map>). I think it might be interesting to support this at the protocol level in RESP3, especially given that you will do it for return types.

Big number

The format is exactly the same as normal numbers except you use ( instead of :. Does it really make sense to introduce a new type? Or, if it does, would it not be better to have a different format, e.g. having the number prefixed by its length (like strings), and/or an encoding more compact that base 10? Because I don't think it is really useful to have such large numbers be human readable in base 10 in practice, they are more likely to be canonically encoded as something else.

Aggregate data types

Your protocol appears to have the same issues as MessagePack, mostly regarding skipping, i.e. if you see an element in a list it is not possible to know the size of that element without decoding it. It will probably be less of an issue with RESP3 than with MessagePack though, because I don't expect (as of now) people to use RESP3 for very large messages. It may be relevant for the attribute type though (which clients may often want to skip). Note that the usual (and kind of ugly) workaround for that in MessagePack would be to encode the payload that should be skipped as a string...

(I know the spec says that clients should accumulate attributes and be able to return them, but if servers start to send too many attributes I am sure some clients will implement an option to drop all attributes to avoid useless memory allocations...)

Maps can have any other type as field and value [...]  Client libraries should return Maps using the idiomatic dictionary type available.

This isn't going to go well. As far as I know, a lot of languages will not allow all possible types as dictionary keys, and so those two sentences appear to be contradictory to me. I would limit map keys to strings, which will probably be the main use case anyway. Also, you define maps as "ordered" but the dictionary type in most languages is not order-preserving...

-- 
Pierre Chapuis

Salvatore Sanfilippo

unread,
May 11, 2018, 4:54:07 AM5/11/18
to redi...@googlegroups.com
On Fri, May 11, 2018 at 10:39 AM Pierre Chapuis <catwe...@gmail.com>
wrote:

> I wonder if being symmetrical would not be a good thing for Redis as
well, maybe sometimes just as an alternative to array commands.

I don't think this is worth it because the command semantics is explicitly
specified by the command itself, so to give HMSET an hash or a linear array
of elements does not improve things in any way.
On the other side it changes the fundamentally simple command semantic: a
command is just a list of arguments, and this fact is used by Redis in
different ways.
Moreover the changes in RESP3 were earned in the real world, the fact that
the return type was always an array was an observable problem for years,
while it is not clear how the lack of ways of sending a map to a command
was a problem.

>> Big number

> The format is exactly the same as normal numbers except you use ( instead
of :. Does it really make sense to introduce a new type? Or, if it does,
would it not be better to have a different format, e.g. having the number
prefixed by its length (like strings), and/or an encoding more compact that
base 10? Because I don't think it is really useful to have such large
numbers be human readable in base 10 in practice, they are more likely to
be canonically encoded as something else.

The point about having a big number type is to tell the reading client,
when it is implemented in a low level programming language, that the number
will fit an unsigned 64 bit integer or not.
Because Redis RESP2 numbers were specified to be in the range of a int64_t,
and for most returned numbers this is perfectly fine, but we may have cases
in the future were we may want to have commands returning very large
numbers.
In this case to return a string is not sounding because we have back the
same problem of clients having to know what the object is to do the
conversion.
About encoding the numbers, this is against the observability of the
protocol which is one of the main desiderata in the design document, and
IMHO we would not save much, and force the user to call less obvious APIs
to decode.

>> Aggregate data types


> Your protocol appears to have the same issues as MessagePack, mostly
regarding skipping, i.e. if you see an element in a list it is not possible
to know the size of that element without decoding it. It will probably be
less of an issue with RESP3 than with MessagePack though, because I don't
expect (as of now) people to use RESP3 for very large messages. It may be
relevant for the attribute type though (which clients may often want to
skip). Note that the usual (and kind of ugly) workaround for that in
MessagePack would be to encode the payload that should be skipped as a
string...

Actually this is a feature: it allows to generate the protocol
incrementally. For a serialization format maybe this is a problem, but for
a client-server transmission problem this is a feature.
This is one of the reasons I don't think the two problems are the same
problem (serialization and client-server chats).

> (I know the spec says that clients should accumulate attributes and be
able to return them, but if servers start to send too many attributes I am
sure some clients will implement an option to drop all attributes to avoid
useless memory allocations...)

Note that RESP3 is perfect to discard stuff as it is. You have to decode
things to discard but the large blobs inside the returned types do not need
any decoding, since the strings are not escaped like in JSON.
I think that the features returning push data to the client must have
control because otherwise you incur in a bandwidth problem, much before
than you have a CPU-usage by the parser problem, so anyway to add features
that will send a lot of random push data in the connection is not a good
idea anyway.

>> Maps can have any other type as field and value [...] Client libraries
should return Maps using the idiomatic dictionary type available.

> This isn't going to go well. As far as I know, a lot of languages will
not allow all possible types as dictionary keys, and so those two sentences
appear to be contradictory to me. I would limit map keys to strings, which
will probably be the main use case anyway. Also, you define maps as
"ordered" but the dictionary type in most languages is not
order-preserving...

This is probably a good idea indeed.

Thanks,
Salvatore

> --
> Pierre Chapuis

Gu Rui

unread,
May 20, 2018, 6:00:19 PM5/20/18
to Redis DB
Hi Salvatore,

I very much like the idea of having attribute types, particularly in the case when a key is requested, its popularity score and/or TTL is also returned to the client side. What I am also interested is the ability to manipulate some of these attributes from client side. In other words, having some attributes that managed by the client side that may only makes sense to a client side logic. Such as serialisation format used for this key, the object version this key is using, or anything useful before the result is parsed, I think useful information like those is better stored as attributes of the data than stored in a separate key or as part of the data. 

Best regards

Rui Gu


On Monday, 7 May 2018 15:39:18 UTC+0:10, Salvatore Sanfilippo wrote:
Hello, the following is a draft describing the new Redis protocol, RESP3:

https://gist.github.com/antirez/2bc68a9e9e45395e297d288453d5d54c

This will be implemented after many months of thinking more about the
design, so please, let's use this thread to collect feedbacks. The RESP3
protocol does not really want to get too complicated compared to the
current topic, but certain limitations of the current protocol are evident
for years now... and should be addressed.

Thanks for any feedback,
Salvatore

Salvatore Sanfilippo

unread,
May 21, 2018, 7:05:04 AM5/21/18
to redi...@googlegroups.com
Complex question, but the gist is the following: ability to store
structured key metadata in a complex form is not planned, because I feel
that would be a huge overkill compared to the amount of usage that would
get.
However a different matter would be the ability to find for instance 8/16
spare bits where the key is stored, and to have SETFLAG or alike in order
to set key flags that are reported back. That would be interesting in
creating client-side caching systems which are more aware of app-level
state, would have zero memory impact (assuming we find a way to store those
bits in the context or existing structures... somewhere), and the reporting
could be enabled via the "CLIENT" command, so that if any flag is non-zero,
it is reported back to the client as auxiliary information. At the same
time it is conceivable to have a "sticky" bit among those bits, that if set
by the client will let the key flags be preserved even in the case the key
is replaced (for instance by the next SET operation).

Cheers

Юрий Соколов

unread,
Jul 3, 2018, 1:49:57 AM7/3/18
to Redis DB
As a connector writer, I have two wishes.

First is a rather small with: please use hex instead of decimals for length and integers
Decimals could not be encoded without division and modulo operations.
While most lengths are <100, and could be replaced with with just table lookup, it is still annoying.
Or at least accept hex numbers if they are prefixed with 'x', so client may send both '123' and 'x7b'

And please, allow leading zero, so that '9', '09' and '0009' are all acceptable and mean '9'.
Same for 'x9', 'x09', 'x0009'

Second with is larger: make protocol "Async" ready.
It means, introduce the way to assing "request numbers" and return them back, if they were sent.
I propose to use '#' character as designator of request number:

Request:

    #234<CR>
    *2<CR>
        $3<CR>
        GET<CR>
        $5<CR>
        mykey<CR>

Response:

     #234<CR>
     $9<CR>
     you value<CR>

Push notification may also include request number, if subscribe request did include it.
Many subscribe requests may send same request number, then all push notifications for them will be sent with that number.
If one connection sents same (or intersecting) subscription with other request number,
then either Push notification is duplicated for each subscription request, or several request numbers are sent before Push body.

Introducing async protocol has 2 benefits:
- first, it will allow to build great proxies for redis, that will allow to use same client connections for both blocking and not-blocking commands.
  Proxy will reuse single connection to redis for all non-blocking commands, and will use connection pool for blocking commands.
- in a far future, it will allow to do same thing within Redis: it will be possible to responde to non-blocking command immediately
  despite many blocking commands from the same connection are waiting for response.

There are at least several in-memory database that implements async protocol, and it is really profitable.

Note, that request numbering could be optional in Redis, so simple clients may omit sending '#234\n' before request,
and then Redis will send response without '#234\n' and will block connection on blocking command.

Marc Gravell

unread,
Jul 3, 2018, 8:53:17 AM7/3/18
to redi...@googlegroups.com
Re async - observation: on a per connection basis, this is already possible, since messages are processed in connection order; so all you need is a per-connection queue of "awaiting reply" messages.

Anecdotally, even for the proxy scenario where you're tracking multiple connections: it is presumably *much more efficient* to simply store a FIFO queue per connection and simply dequeue the next thing awaiting a response - rather than having to look things up by some index.

That leaves the non-blocking command case; while I agree that is an interesting aspect, IMO that deserves to be considered fully in its own right, rather than forced in here. So - and maybe I'm missing the point here (I do that a lot) - it isn't obvious to me that there is anything extra needed to enable fully async access over multiple connections.

Marc (StackExchange.Redis)

--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To unsubscribe from this group and stop receiving emails from it, send an email to redis-db+u...@googlegroups.com.
To post to this group, send email to redi...@googlegroups.com.
Visit this group at https://groups.google.com/group/redis-db.
For more options, visit https://groups.google.com/d/optout.


--
Regards,

Marc

Юрий Соколов

unread,
Jul 3, 2018, 10:20:16 AM7/3/18
to Redis DB


вторник, 3 июля 2018 г., 15:53:17 UTC+3 пользователь Marc Gravell написал:
Re async - observation: on a per connection basis, this is already possible, since messages are processed in connection order; so all you need is a per-connection queue of "awaiting reply" messages.

It doesn't called "async". It is "pipelined" protocol. RESP2 is pipelined, but not async.
It has one huge disadvantage: single blocking call (even "SET" that should reach the disk) stops whole request queue.
That is why most Redis clients uses pool of connections in "request-response" mode instead of being inherently pipelined.

But Redis, as any event-loop based application, doesn't like "request-response through numerouse connections" mode of operation.
It likes "pipelined requests through small number of connection".

In our company, we don't use any explicitely blocking command (like BLPOP), and don't use disk storage (therefore, SET also considered non-blocking).
So, I wrote implicitely pipelined connector, and it reduced Redis's CPU usage at least twice at our RPS scale (40% cpu ->20% cpu).
 
Anecdotally, even for the proxy scenario where you're tracking multiple connections: it is presumably *much more efficient* to simply store a FIFO queue per connection and simply dequeue the next thing awaiting a response - rather than having to look things up by some index.

Proxy scenario multiplies disaster: many clients are proxied into one connection, and single blocking call from single client will block all clients at once.
That is why most of Redis Proxies dosn't support blocking requests (like BLPOP).

And requests index could be really fast if it done right.
I did it right at least once (for other in-memory storage with truly async protocol and implementation), so I know.
 
That leaves the non-blocking command case; while I agree that is an interesting aspect, IMO that deserves to be considered fully in its own right, rather than forced in here. So - and maybe I'm missing the point here (I do that a lot) - it isn't obvious to me that there is anything extra needed to enable fully async access over multiple connections.

I don't understand your "enable fully async access over multiple connections".
I mean, async access over single connection.
At least, support of protocol.
I doubt Redis will change its internals to be fully async in near future.
But it will allow Redis to become fully async in far future.
And protocol support will open door for smart async proxies already, before Redis will become async itself.

Reply all
Reply to author
Forward
0 new messages