3.4 Hashes

  • Redis in Action – Home
  • Foreword
  • Preface
  • Part 1: Getting Started
  • Part 2: Core concepts
  • 1.3.1 Voting on articles
  • 1.3.2 Posting and fetching articles
  • 1.3.3 Grouping articles
  • 4.2.1 Configuring Redis for replication
  • 4.2.2 Redis replication startup process
  • 4.2.3 Master/slave chains
  • 4.2.4 Verifying disk writes
  • 5.1 Logging to Redis
  • 5.2 Counters and statistics
  • 5.3 IP-to-city and -country lookup
  • 5.4 Service discovery and configuration
  • 5.1.1 Recent logs
  • 5.1.2 Common logs
  • 5.2.2 Storing statistics in Redis
  • 5.3.1 Loading the location tables
  • 5.3.2 Looking up cities
  • 5.4.1 Using Redis to store configuration information
  • 5.4.2 One Redis server per application component
  • 5.4.3 Automatic Redis connection management
  • 8.1.1 User information
  • 8.1.2 Status messages
  • 9.1.1 The ziplist representation
  • 9.1.2 The intset encoding for SETs
  • Chapter 11: Scripting Redis with Lua
  • 11.1.1 Loading Lua scripts into Redis
  • 11.1.2 Creating a new status message
  • 11.2 Rewriting locks and semaphores with Lua
  • 11.3 Doing away with WATCH/MULTI/EXEC
  • 11.4 Sharding LISTs with Lua
  • 11.5 Summary
  • 11.2.1 Why locks in Lua?
  • 11.2.2 Rewriting our lock
  • 11.2.3 Counting semaphores in Lua
  • 11.4.1 Structuring a sharded LIST
  • 11.4.2 Pushing items onto the sharded LIST
  • 11.4.4 Performing blocking pops from the sharded LIST
  • A.1 Installation on Debian or Ubuntu Linux
  • A.2 Installing on OS X
  • B.1 Forums for help
  • B.4 Data visualization and recording
  • Buy the paperback
  • Redis in Action – Home
  • Foreword
  • Preface
  • Part 1: Getting Started
  • Part 2: Core concepts
  • 1.3.1 Voting on articles
  • 1.3.2 Posting and fetching articles
  • 1.3.3 Grouping articles
  • 4.2.1 Configuring Redis for replication
  • 4.2.2 Redis replication startup process
  • 4.2.3 Master/slave chains
  • 4.2.4 Verifying disk writes
  • 5.1 Logging to Redis
  • 5.2 Counters and statistics
  • 5.3 IP-to-city and -country lookup
  • 5.4 Service discovery and configuration
  • 5.1.1 Recent logs
  • 5.1.2 Common logs
  • 5.2.2 Storing statistics in Redis
  • 5.3.1 Loading the location tables
  • 5.3.2 Looking up cities
  • 5.4.1 Using Redis to store configuration information
  • 5.4.2 One Redis server per application component
  • 5.4.3 Automatic Redis connection management
  • 8.1.1 User information
  • 8.1.2 Status messages
  • 9.1.1 The ziplist representation
  • 9.1.2 The intset encoding for SETs
  • Chapter 11: Scripting Redis with Lua
  • 11.1.1 Loading Lua scripts into Redis
  • 11.1.2 Creating a new status message
  • 11.2 Rewriting locks and semaphores with Lua
  • 11.3 Doing away with WATCH/MULTI/EXEC
  • 11.4 Sharding LISTs with Lua
  • 11.5 Summary
  • 11.2.1 Why locks in Lua?
  • 11.2.2 Rewriting our lock
  • 11.2.3 Counting semaphores in Lua
  • 11.4.1 Structuring a sharded LIST
  • 11.4.2 Pushing items onto the sharded LIST
  • 11.4.4 Performing blocking pops from the sharded LIST
  • A.1 Installation on Debian or Ubuntu Linux
  • A.2 Installing on OS X
  • B.1 Forums for help
  • B.4 Data visualization and recording
  • Buy the paperback

    3.4 Hashes

    As introduced in chapter 1, HASHes in Redis allow you to store groups of key-value pairs in a single higher-level Redis key. Functionally, the values offer some of the same features as values in STRINGs and can be useful to group related data together. This data grouping can be thought of as being similar to a row in a relational database or a document in a document store.

    In this section, we’ll talk about the most commonly used commands that manipulate HASHes. You’ll learn more about the operations for adding and removing key-value pairs to HASHes, as well as commands to fetch all of the HASH contents along with the ability to increment or decrement values. When finished with this section, you’ll better understand the usefulness of storing your data in HASHes and how to do so. Look at table 3.7 to see some commonly used HASH commands.

    Table 3.7 Operations for adding and removing items from HASHes
    Command Example use and description
    HMGET HMGET key-name key [key …] — Fetches the values at the fields in the HASH
    HMSET HMSET key-name key value [key value …] — Sets the values of the fields in the HASH
    HDEL HDEL key-name key [key …] — Deletes the key-value pairs in the HASH, returning the number of pairs that were found and deleted
    HLEN HLEN key-name — Returns the number of key-value pairs in the HASH

    Some of those commands should be familiar from chapter 1, but we have a couple of new ones for getting and setting multiple keys at the same time. These bulk commands are mostly a matter of convenience and to improve Redis’s performance by reducing the number of calls and round trips between a client and Redis. Look at the next listing to see some of them in action.

    Listing 3.7 A sample interaction showing some common HASH commands in Redis
    >>> conn.hmset('hash-key', {'k1':'v1', 'k2':'v2', 'k3':'v3'})
    True
    

    We can add multiple items to the hash in one call.

    >>> conn.hmget('hash-key', ['k2', 'k3'])
    ['v2', 'v3']
    

    We can fetch a subset of the values in a single call.

    >>> conn.hlen('hash-key')
    3
    

    The HLEN command is typically used for debugging very large HASHes.

    >>> conn.hdel('hash-key', 'k1', 'k3')
    True
    

    The HDEL command handles multiple arguments without needing an HMDEL counterpart and returns True if any fields were removed.

    The HMGET/HMSET commands are similar to their single-argument versions that we introduced in chapter 1, only differing in that they take a list or dictionary for arguments instead of the single entries.

    Table 3.8 shows some other bulk commands and more STRING-like operations on HASHes.

    With the availability of HGETALL, it may not seem as though HKEYS and HVALUES would be that useful, but when you expect your values to be large, you can fetch the keys, and then get the values one by one to keep from blocking other requests.

    Table 3.8 More bulk operations and STRING-like calls over HASHes
    Command Example use and description
    HEXISTS HEXISTS key-name key — Returns whether the given key exists in the HASH
    HKEYS HKEYS key-name — Fetches the keys in the HASH
    HVALS HVALS key-name — Fetches the values in the HASH
    HGETALL HGETALL key-name — Fetches all key-value pairs from the HASH
    HINCRBY HINCRBY key-name key increment — Increments the value stored at the given key by the integer increment
    HINCRBYFLOAT HINCRBYFLOAT key-name key increment — Increments the value stored at the given key by the float increment

    HINCRBY and HINCRBYFLOAT should remind you of the INCRBY and INCRBYFLOAT operations available on STRING keys, and they have the same semantics, applied to HASH values. Let’s look at some of these commands being used in the next listing.

    Listing 3.8 A sample interaction showing some more advanced features of Redis HASHes
    >>> conn.hmset('hash-key2', {'short':'hello', 'long':1000*'1'})
    True
    >>> conn.hkeys('hash-key2')
    ['long', 'short']
    

    Fetching keys can be useful to keep from needing to transfer large values when we’re looking into HASHes.

    >>> conn.hexists('hash-key2', 'num')
    False
    

    We can also check the existence of specific keys.

    >>> conn.hincrby('hash-key2', 'num')
    1L
    >>> conn.hexists('hash-key2', 'num')
    True
    

    Incrementing a previously nonexistent key in a hash behaves just like on strings; Redis operates as though the value had been 0.

    As we described earlier, when confronted with a large value in a HASH, we can fetch the keys and only fetch values that we’re interested in to reduce the amount of data that’s transferred. We can also perform key checks, as we could perform member checks on SETs with SISMEMBER. And back in chapter 1, we used HINCRBY to keep track of the number of votes an article had received, which we just revisited.

    Let’s look at a structure that we’ll be using fairly often in the remaining chapters: sorted sets.