Search code examples
redisin-memory-databasekey-value-storeordered-map

Why there is no ordered hashmap in Redis?


Redis Data types includes sorted set and other necessary data-structures for key-value storage. But I wonder why it doesn't have any sorted map like Java's TreeMap or C++'s std::map. I think the underlying data-structure would be mostly similar of sorted set as both are supposed to be balanced binary search tree.

There must be some use-cases where we have to store key-value pair in specific order according to key. But current sorted set only serves the purpose of storing key according to score.


Solution

  • There must be some use-cases where we have to store key-value pair in specific order according to key

    Since Redis keys are binary strings, I assume that the specific order you mentioned, is lexicographical order (specifically, keys are compared with the memcmp function). In that case, you can easily implement a C++'s std::map with SORTED SET. You can achieve this with 2 steps:

    Build a std::set with Redis' Sorted Set

    If 2 elements in a SORTED SET have the same score, they're ordered in lexicographical order. So in order to build a std::set, just give all members in a SORTED SET with the same score:

    zadd std::set 0 c
    zadd std::set 0 a
    zadd std::set 0 b
    
    // since all these members have the same score,
    // the result is lexicographical ordered:
    // a b c
    zrange std::set 0 -1
    
    // the following command will fail, since 'c' already exists.
    zadd std::set 0 c
    

    Since Redis 2.8, it supports some commands to operate on the lexicographical ranges, so that you can build something similar to std::set::lower_bound, or std::set::upper_bound

    // something similar to lower_bound: find all members not less than b
    zrangebylex std::set [b +
    // something similar to upper_bound: find all members greater than b
    zrangebylex std::set (b +
    

    Map each key in the set with a value

    Since you already get a std::set, then map the key with a value, you can get a std::map.

    set a value_a
    set b value_b
    set c value_c
    

    Combine these 2 steps together

    You can wrap the whole work into a lua script to have a built-in std::map. And use it like this:

    redis-cli --eval map.lua map_name , key value