X

Redis for .NET Developer – Redis Hash Datatype

Redis

Redis Hash Datatype are similar in C# world as Dictionary e.g Dictionary<string, string>. Just like in C# redis stores map of attributes using key value pair. One thing to note is in Redis a Hash both the field name and the value are strings. Therefore, a Hash Datatype is a mapping of a string to a string.

Memory Optimized

Redis Hashes are memory-optimized. Their optimization is based on the hash-max-ziplist-entries and hash-max-ziplist-value configurations. Internally in Redis, a Hash can be a ziplist or a hash table. So what does it mean for a ziplist? Basically it is designed to be memory efficient dually linked list and integers are stored as real integers rather than a sequence of characters.

Speed

Something to note is a hashtable in Redis has a constant time lookup, the down side is it is not memory optimized, while the ziplist is memory optimized but the lookup time are not constant. To read more on Redis Memory Optimization please view Redis documentation.

So which one is used when?

  • The ziplist is by default when the number of fields do not exceed the configuration ones in hash-max-ziplist-entries
  • The hashtable is used when a the size or any of its values exceeds

Redis Hash Datatype – Operations

  • HSET: Sets the value of a field for a key O(1).
  • HGET: Gets the value of a field for a key O(1).
  • HLEN: Gets the number of fields for the key O(1).
  • HMGET: Gets the values for the fields for a key O(N), where N is the number of fields and O (1) if N is small.
  • HMSET: Sets multiple values for respective fields for a key O(N), where N is the number of fields and O (1) if N is small.
  • HGETALL: Gets all the values and fields for a key O(N). Where N is the size of the hash
  • HKEYS: Gets all the fields in the Hash for the key O(1).
  • HEXISTS: Checks for the existence of a field for a key O(1).
  • HVALS: Gets all the values in the Hash for the key O(N), where N is the number of fields and O(1) if N is small.
  • HSETNX: Sets the value against the field for the key provided the field does not exist O(1).
  • HDEL: Deletes the fields for a key O (N), where N is the number of fields and O(1) if N is small.
  • HINCRBY: Increments the value (provided the value is an integer) of a field for a key O(1).
  • HINCRBYFLOAT: Increments the value if value is a float of a field for a key O(1).

C# code using Redis Hash Datatype

  var hashKey = "hashKey";

  HashEntry[] redisBookHash = {
    new HashEntry("title", "Redis for .NET Developers"),
    new HashEntry("year", 2016),
    new HashEntry("author", "Taswar Bhatti")
  };

  redis.HashSet(hashKey, redisBookHash);

  if (redis.HashExists(hashKey, "year"))
  {
    var year = redis.HashGet(hashKey, "year"); //year is 2016
  }

  var allHash = redis.HashGetAll(hashKey);

  //get all the items
  foreach (var item in allHash)
  {
    //output 
    //key: title, value: Redis for .NET Developers
    //key: year, value: 2016
    //key: author, value: Taswar Bhatti
    Console.WriteLine(string.Format("key : {0}, value : {1}", item.Name, item.Value));
  }

  //get all the values
  var values = redis.HashValues(hashKey);

  foreach (var val in values)
  {
    Console.WriteLine(val); //result = Redis for .NET Developers, 2016, Taswar Bhatti
  }

  //get all the keys
  var keys = redis.HashKeys(hashKey);

  foreach (var k in keys)
  {
    Console.WriteLine(k); //result = title, year, author
  }

  var len = redis.HashLength(hashKey);  //result of len is 3
            
  if (redis.HashExists(hashKey, "year"))
  {
    var year = redis.HashIncrement(hashKey, "year", 1); //year now becomes 2017
    var year2 = redis.HashDecrement(hashKey, "year", 1.5); //year now becomes 2015.5
  }

For the code please visit
https://github.com/taswar/RedisForNetDevelopers/tree/master/4.RedisHashes

So this covers the basic usage of Redish Hash Datatype, in the next blog post I will cover using List Datatype.

For previous Redis topics

  1. Intro to Redis for .NET Developers
  2. Redis for .NET Developer – Connecting with C#
  3. Redis for .NET Developer – String Datatype
  4. Redis for .NET Developer – String Datatype part 2
Taswar Bhatti:

View Comments (10)

  • Hey,I lean this a few days and i can't find some good tutorials for me.Although I bought a book,but it's Python,it's hard for me.
    Your tutorial is great for me,if you have time,Please continue to write,Like Sortedset.It will be very useful to me,to everyone.
    I will keep watching this series,Thank you very much!

  • taswar:
    var year2 = redis.HashDecrement(hashKey, "year", 1.5); //year now becomes 2015.5

    above cmd runs into error -->
    'Err unknown command 'HINCRBYFLOAT

    • are you running the code or using redis-cli, I have run the code using redis 4.0.1 and did not see any issues. Also running StackExchange.Redis version 1.2.6

  • I have a scenario where I have to get all the keys (string type) matching some prefix. For example, I have below keys
    1. ABC.10
    2. ABC.11
    3. ABC.12
    4. XYZ.10
    5. XYZ.11
    6. XYZ.12
    And I need to get all keys matching XYZ using Stackexchange.Redis C#.

    • In redis-cli to get keys you will do something like this with the wildcard search "*"

      e.g
      127.0.0.1:6379> set title 1
      OK
      127.0.0.1:6379> set title2 2
      OK
      127.0.0.1:6379> get title*
      (nil)
      127.0.0.1:6379> keys title*
      1) "title"
      2) "title2"

      For StackExchange.Redis its more of a work but I would suggest that you look at the extensions project
      https://github.com/imperugo/StackExchange.Redis.Extensions

      which allows you to searching for keys call using wildcards
      var keys = myCacheClient.SearchKeys("myCacheKey*");

  • How to create a tree like structure using Redis in C#?
    For Example-
    C/Folder/Foder2/Folder3/Values1, /Values2, /Values3
    where Each folder and values should be keys.

    • The easiest way to solve this is to use 2 data structures in Redis, The Hash for the the folder information and a List for the children.
      e.g
      P1 {
      "name": "principle",
      "parent": null
      }

      P2 {
      "name": "teacher",
      "parent": "P1"
      }

      P1.children = List.LPush(P2)

      I could do a blog post maybe later this or next week to explain the concepts in more details maybe.

Related Post