Open byroot opened 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
.
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.
And also it makes it easy for proxies to blindly extract the keys without having to know the commands signatures.
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.
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.
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 likeredis.call("GET", redis.key("foo"))
, allowing the client to extract the keys without having to know anything about the command signature.