5 ms·
I completely agree with the sentiment. And this is why such a statement made by antirez leaves me puzzled. I admire Redis for its performance and simplicity of
by pathsjs 10y ago
I completely agree with the sentiment. And this is why such a statement made by antirez leaves me puzzled.
I admire Redis for its performance and simplicity of setup, but if there is one thing that Redis does not have is a coherent API.
Whenever I use Redis, I absolutely need the command cheatsheet, as it seems that every command works differently. There is no commonality in data structures. The whole thing seems more dictated by the underlying implementation than the desire of providing a simple API.
For instance, why LPUSH accepts multiple parameters but LPUSHX does not? Why there is even hyperloglog in a database? Where did the need for RPUSHLPOP come from? Why the options for SCRIPT DEBUG are YES, SYNC and NO?
I don't want to be too negative. I appreciate the great work that has been done on Redis, but I feel it really needs to rethink the whole API layer.
- matt4077 10y agoWell hyperloglog is simply a golden bullet for all the time-series systems currently en vogue. "How many people with Windows 7 visited google.com yesterday?" -> come back in a year and the query is done. "+/- 2% is ok." -> Instant answer.
- dvirsky 10y agoMost of redis' API is quite coherent. Some of the incoherence is due to the fact that some commands get less attention, such as LPUSHX (which I've never really noticed and I've been using redis for 6 years). Some is because of the core idea of remaining backwards compatible, so even if you have option or commands added, they will never replace old ones, which can cause a bit of complexity and inconsistency. > Why there is even hyperloglog in a database? Remember that redis is not really a database but a "data structure server". I have to say I personally don't think this should have been part of the redis core, and it's a textbook example of what redis modules should be, but it came 2-3 years before modules. > Where did the need for RPUSHLPOP come from? It came from distributed work queues, which are a popular use case for redis. The documentation actually goes into great detail explaining how to use it.
- catwell 10y agoLPUSHX got my attention so I opened a pull request making it variadic (along with other commands) three years ago [1]. Of course since then the codebase changed and it can no longer be merged. If there is still interest I could try to fix it, although I don't use Redis as much anymore and I have not looked at its code for a long time. [1] https://github.com/antirez/redis/pull/1232 https://github.com/antirez/redis/pull/1232
- dvirsky 10y agotry to go on the #redis freenode channel and ask antirez about it.
- antirez 10y agoHey! Yes I'm interested, the PR was not handled for the usual reasons but making the commands variadic is a good idea. However I'm surprised there is not just the need to change the command table since I remembered, incorrectly, all the variants were handled by a single function.
- catwell 10y agoYeah, as you can see the issue was that it is a different function, pushxGenericCommand(), which is used for LPUSHX, RPUSHX and LINSERT. For me having the same function for LPUSHX / RPUSHX and LINSERT does not make much sense (it uses different code depending on whether or not an argument is NULL anyway) so I had started by making LINSERT not rely on it. My initial goal at the time was not to make LPUSHX and RPUSHX variadic, since like you said they are not used so much. It was actually to make LINSERT variadic, which can result in a significant performance boost compared to calling it several times. Anyway, I will try to find the time to adapt it to the current code base.
- jamespedwards 10y ago"data structure server" hits the nail on the head. Because Redis is such a paradigm shift from a traditional database, it doesn't matter how simple Redis is, it will always feel complicated if people go into it anticipating a traditional database. ...Some of us don't like Chipotle because it has too many choices, even though we could just order the get/set burrito.
- antirez 10y agoHello pathsjs, well first of all, one thing is that I make efforts towards a goal, another thing is to reach it. In your analysis I don't reach the goal of simplicity, but I can ensure you I really try hard. Now more to the point, I still think Redis is a simple system: > one thing that Redis does not have is a coherent API. Unfortunately coherence is pretty orthogonal to simplicity, or sometimes there is even a tension between the two. For instance instead of making an exception in one API I can try to redesign everything in more general terms so that everything fits: more coherence and less simplicity. In general complex systems can be very coherent. Similarly the PHP standard library is extremely incoherent but is simple, you read the man page and you understand what something does in a second. > Whenever I use Redis, I absolutely need the command cheatsheet [snip] This actually means that Redis is very simple, in complex systems to check the command fingerprint in the manual page does not help, since it is tricky to understand how the different moving parts interact. However it is true that in theory Redis could have more organized set of commands, like macro-type commands with sub operations: "LIST PUSH ..." "LIST POP ..." and so forth. Many of this things were never fixed because I believe that is more aesthetic than a substantial difference, and the price to pay to give coherence later is breaking the backward compatibility. > why LPUSH accepts multiple parameters but LPUSHX does not? Since nobody uses LPUSHX almost and is a kinda abandoned command, but this is something that we can fix since does not break backward compatibility. > Why there is even hyperloglog in a database? Because Redis is a data structures server and HLLs are data structures. > Where did the need for RPUSHLPOP come from? It is documented and has nothing to do with simplicity / coherence. > Why the options for SCRIPT DEBUG are YES, SYNC and NO? They have different fork behavior, as explained in the doc. I think Redis is a system that is easy to pickup overall, but that's not the point of my blog post. However our radically different point of view on what simplicity is is the interesting part IMHO. I bet you could easily design a system that is complex for me because of, for instance, attempt to provide something very coherent, because breaking coherency for a few well-picked exceptions to the rule is a great way to avoid over-generalization.
- andreaferretti 10y agoHi antirez, I think we just have two opposing views about what constitutes simplicity. I agree that Redis has the rare advantage that one can understand a command at a time, and the cheat sheet is essentially all that is needed to work with it efficiently. Many systems have a documentation that is much more involved, and in this sense Redis is simple. Still, the reason I find it non simple is that it seems like you (or other contributors) added a random selection of data structures and operations in it. It is difficult to imagine which operations or data structures will be available without consulting the instructions. For instance, there is hyperloglog, but there are no trees or graphs, or sorted maps. And lists have LPUSHX, but no LSETX, nor there is a LLAST operation (I guess it may be for efficiency reasons, but then LINDEX has the same complexity). Sets have SUNION and SUNIONSTORE, but there is no LCONCAT or LCONCATSTORE. Let me add an example, since I think it highlights the difference in approach we may have. I find the Scala collections very well designed and easy to work with. Each collection has essentially the same (large) set of operations, from `map` and `filter` to more sophisticated ones such as `combinations(n)` or `sliding(len, step)`. Not only that, but usually this operations will preserve the types, whenever possible. This means that, say, `map`ping over a list will produce a list, while `map`ping over a string will produce a string (if the function is char -> char) or a sequence otherwise. Similarly mapping over a bitset will produce a bitset if the function is int -> int, or a set otherwise, since bitsets only represent sets of integers. This allows me to write even very complex algorithms succintly, without needing to consult the API. I find this very simple from the point of view of the user, although the design for writers themselves is pretty complex. On the other hand, comments such as http://stackoverflow.com/questions/1722726/is-the-scala-2-8-collections-library-a-case-of-the-longest-suicide-note-in-hist http://stackoverflow.com/questions/1722726/is-the-scala-2-8-... prove that some other people find it complex and daunting. In short: I find Redis easy to use (and this is one of the reasons I do use it often!), but not simple in the sense that it is easy to grasp the design.