antirez / RESP3

RESP protocol V3 repository. Contains the specification, and other related resource
229 stars 41 forks source link

Add a distinct type for keys? #29

Open byroot opened 5 years ago

byroot commented 5 years ago

Hi,

According to http://antirez.com/news/125 the goal with RESP3 is to be able to have relatively dumb clients which offer a very simple interface such as result = redis.call(“GET”,keyname); and don't need to know anything about the command it sends.

As the current maintainer of redis-rb, I'm totally behind this as it would indeed make my life much easier, and I'm really eager to be able to delete tons of code.

However I question wether such simplicity will really be achievable in practice. With a regular Redis setup it will indeed be possible, but as soon as you use Redis in a distributed manner, say with Redis cluster, the client do need to know which elements of the command are keys, so that it can hash them and select the proper target.

So ultimately I'm afraid the client will still have to maintain a list of commands, as well as their possible arguments as to be able to extract keys.

Hence why I wonder if keys could be a distinct type from strings, with their own prefix such as # or @.

This way, rather than redis.call("GET", "foo"), the interface would be something like redis.call("GET", redis.key("foo")), allowing the client to extract the keys without having to know anything about the command signature.

kristoff-it commented 5 years ago

I'm not sure how that relates to the wire protocol.

Looking at your example, it's already easy to see a possible solution: make redis.key return a specific type (e.g. an instance of the Key class) that wraps the input value ("foo" in your example) and then, when inside redis.call, just check which arguments are of type Key.

byroot commented 5 years ago

Indeed, and that's how I'll implement it anyway, but if it's not enforced by the protocol, switching a simple client for a cluster client becomes much more problematic.

byroot commented 5 years ago

And also it makes it easy for proxies to blindly extract the keys without having to know the commands signatures.

kristoff-it commented 5 years ago

I see your point now. So it would be a different tagging (let's imagine that we use € instead of $ for key arguments) that proxies might be interested in. But other than proxies, nobody else would care I think.

Redis knows already which args are keys or not, the client that produced the query can know because it must offer to the user a constructor for this hypotetical type, like we mentioned before.

So, other than proxies, who else would benefit for this information showing up in RESP?

One last point: Proxies could use "COMMAND" to learn the key mappings for basically all commands.

byroot commented 5 years ago

the client that produced the query can know because it must offer to the user a constructor for this hypotetical type

Well, that is not the intent @antirez expressed in his blog post:

In the future of Redis I see clients that are smarter under the hood, trying to do their best in order to handle connections, pipelining, and state, and apparently a lot more simpler in the user-facing side, to the point that the ideal Redis client is like:

result = redis.call(“GET”,keyname);

Of course on top of that you can build more advanced abstractions, but the bottom layer should look like that, and the returned reply should not require any filtering that is ad-hoc for specific commands: RESP3 return type should contain enough information to return an appropriate data type. So HGETALL will return a RESP3 “map”, while LRANGE will return an “array”, and EXISTS will return a RESP3 “boolean”.

This also allows new commands to work as expected even if the client library was not specifically designed to handle it. With RESP2 instead what happened was that likely the command worked using mechanisms like "method missing" or similar, but later when the command was really implemented in the client library, the returned type changed, introducing a subtle incompatibility.

Not having to maintain the list of command signatures in the client would significantly reduce their complexity, and would also allow to support extensions ou of the box without having to modify anything in the client.

Proxies could use "COMMAND" to learn the key mappings for basically all commands.

That's actually a good point.