11

Redis can be used either directly as a key-value store, where the value is string. Or, in more sophisticated way, the value can be a data structure, for example hash or list. Assuming we have the second case and under the key "H", there is a hash. Items can be added to the hash and removed. Eventually, the hash can be empty, and it can be re-populated again.

I have found out that if we remove the last item from the data structure, our hash "H", Redis removes it from current keys, for some reason.

Example:

HSET "H" "key1" "value1"
HSET "H" "key2" "value2"
HDEL "H" "key1"
 <-- Here, "H" is in the list of current keys, whereby HLEN returns 1
HDEL "H" "key2"
 <-- Here, for some reason, "H" is not shown among existing keys, 
     not even as an empty hash (HLEN 0)
HSET "H" "key3" "value3"
 <-- Hash is back in the list of keys

My question is: Is it possible to configure Redis so it does still keep showing the value (empty hash, in our example) of the given key ("H", in our example) as an empty non-trivial data structure?

Pavel S.
  • 11,892
  • 18
  • 75
  • 113

2 Answers2

18

Short answer: No

Redis 'creates the hash' when first item is inserted and 'removes the hash' when last item is removed. I'm using Redis 2.8 and there is no option to 'let an empty hash be'.

Addendum: Same is true for Redis 6 as well.

Manu Manjunath
  • 6,201
  • 3
  • 32
  • 31
  • Can you please have a look https://stackoverflow.com/questions/52712982/storing-data-into-redis-through-cron-job –  Oct 09 '18 at 13:32
4

Manu is right. You have no way of doing that.

But if you explain why you would want to do it, then we might help you better. As you know, in Redis you can set an attribute on a Hash even if it doesn't exist previously, so you don't not need to first create the Hash and then set the attributes. With that on mind, there is no need to keep an empty Hash that would just be wasting memory.

What is your use case?

update: after reading your use case, I am improving the answer.

For your problem of "volatile" hashes, you can do something easy. After you run your KEYS (or SCAN) command, you can create a SET containing all the names of the hashes that existed in this iteration. You can call this something like "last_seen_keys". What you want to do now is, after you call KEYS, you create a set that you call "current_keys". Now you just run a diff between the two sets, so you can see which keys were present in the last pass and not in this one. You can set your values in statsd to zero for those keys. After that, you delete the "last_seen_keys" SET and you rename the "current_keys" SET to "last_seen_keys". That should do the trick

Javier Ramirez
  • 3,446
  • 24
  • 31
  • What I want is to monitor lengths of various hashes in Redis. I am using statsd, but it does not matter. The point is that each minute, I dump length of all _existing_ Redis structures (hashes) to statsd. The names of hashes are dynamic, that's why I cannot just enumerate them. I need to run "KEYS hash-*" and then iterate over these. However, if the hash disappeared, I have the last non-zero value in statsd, but is should be replaced by zero - obviously, length of empty hash is zero. – Pavel S. Jan 22 '14 at 13:18
  • There is no command to do that directly, but you can do something. First, stop using KEYS, as it is highly inefficient. Starting from redis 2.8 you can use SCAN, which is much more efficient and specially designed for users who need to deal with dynamic keys. – Javier Ramirez Jan 22 '14 at 13:30
  • I just improved my answer to include my proposed solution – Javier Ramirez Jan 22 '14 at 13:36
  • Thank you, Ramirez. Although I am aware of inefficiency of KEYS, it's not a big deal when there are only tens of keys, not more. And your solution with last_seen_keys would probably work, but that's exactly the kind of overkill I did not want to do... I could also hack statsd to process the data in the similar fashion, but I want the "cleanest" solution. – Pavel S. Jan 22 '14 at 13:38