How to put a TTL/expiration on an HSET - redis

An HSET is like so:
HSET myhash field1 "Hello"
is there a way to put an expiration/TTL on the "field1" key. It's trivial to put an expiration on myhash tmk, but I don't know how to put a TTL on key of a hash.
https://redis.io/commands/expire
Otherwise, I am stuck using:
SET field1 "Hello"
EXPIRE field1 10
and putting all my keys at the top-level instead of a hash :(

See https://github.com/antirez/redis/issues/1042
Currently it's not possible.

Related

How to get all 'key namespaces' (object types) in Redis?

As we may know, good naming convention for Redis keys is "object-type:id"
How to get all key namespaces (symbols before :)?
E.g.
127.0.0.1:6379> KEYS *
1) "bar:1"
2) "baz:1"
3) "baz:3"
4) "foo:1"
5) "foo:2"
6) "baz:2"
I want a command like
127.0.0.1:6379> SCAN 0 MATCH "(^\w+):" COUNT 10
1) "6"
2) "foo"
3) "bar"
4) "baz"
But seems like MATCH option of SCAN command does not support PCRE pattern syntax.
In real, I got
127.0.0.1:6379> SCAN 0 MATCH "(^\w+):" COUNT 10
1) "6"
2) (empty list or set)
Any ideas ?
You could create an index key and add each namespace to it every time you add a new key:
SADD "namespaces" "foo". But there would be problem with deleting them, as you'd have to check if the deleted object was the last of it's type.
The second option would be creating a module (if you're using Redis >= 4.0) with a command that you could use to add and remove said keys, that would have it's own type in which it would store object-type counters (so it wouldn't have to call KEYS * which is quite slow). The problem here would be if you had key expiration, or oom key deletion configured. The counter would be incorrect once a key gets deleted by Redis itself.
The third option is to create a module with one command that would call KEYS *, then get the first part of the key and add it to a hash map/dictionary (using RedisModuleDict) and then return it using RedisModule_ReplyWithString(ctx, str) in a loop
I think that you could also write it in Lua instead of creating a module, but a module written in C is probably going to be faster... and I don't know Lua so I won't be able to help you there.
You could always write a simple script in bash that would get the object-type from each key and SADD it to a temporary key then read it, print and delete afterwards, but that's the same as the third option but slower and has to use a temporary key which might be used by some other script or something.

Redis Module - Accessing Multiple Keys with Clustering in Mind

I have a Redis module with a custom command that issues commands to two different keys at once.
The custom commands receives a key (e.g. myKey), and some values, and issues HSET myKey_sd1 ... and ZADD myKey_sd2 ... commands.
I wonder what would happen in a cluster configuration, where each key could exist in a separate node.
Right now, inside the module's custom command I enclosure the key that is given to me in { and }, so I end up issuing HSET {myKey}_sd1 and ZADD {myKey}_sd2
Which works but I wonder if it's necessary.
I also wonder what happens if I receive a key that is already enclosed in curly brackets (because the user of the module wants to control the hash slot by himself) - e.g. 123_{myKey}
Right now, I would still enclose this key in my own curly brackets when I issue the HSET and ZADD - HSET {123_{myKey}}_sd1 ... and ZSET {123_{myKey}}_sd2
In this case, as far as I know, Redis would compute the hash for 123_{myKey which undermines the input of the user (since they didn't wish to enclose the 123_ part)
To fix it, I could have my custom command look for a { in the key that it received, if it didn't find a {, it would enclose the key in { and }, like I described above.
However, if it did find a {, it would leave the key as is, resulting in (in the case of the example above) HSET 123_{myKey}_sd1 ... and ZADD 123_{myKey}_sd2 - which works both for the user and for the inner workings of the module.
So I wonder
Is enclosing the keys that I receive from the user in { and } the right way to support clustering?
If so, am I handling the case where the user provides a key which is already enclosed in { and } in the right way?
Is enclosing the keys that I receive from the user in { and } the right way to support clustering?
The Redis Module cluster documentation is "missing", but I believe it's the case that your module must make sure to use the same node as the key that was passed as an argument.
So, yes, you must use hash tags to ensure that your keys are using the same hash slot as the passed key.
If so, am I handling the case where the user provides a key which is already enclosed in { and } in the right way?
Your proposed fix (not your current implementation) is right. You must hash to the same slot as the key that is passed, which means respecting any specified hash slot.
Just make sure you're following the exact algorithm for interpreting hash tags. You don't want any edge cases here.

Why is the nxxx parameter of set() in Jedis exclusive?

In Jedis, I want to set some key and value with expiring time by a single invocation.
I can do this by combination of set() and expire() but it needs two invocations.
I found the following method:
set(final String key, final String value, final String nxxx, final String expx, final long time)
But I have to choose nx (Only set the key if it does not already exist.) or xx (Only set the key if it already exist.).
I want to cover both cases.
Any suggestion? Or any reason to be written like this?
Redis has a SETEX command, which sets the key with an expiry.
jedis.setex(key, expireAfter, value);
This question is so misleading. nx and xx are indeed for different use cases and mutually exclusive. If you want to simply overwrite any expiry, simply don't pass in none of below:
NX -- Set the key only when the key doesn't exist
XX -- Set the key only when the key has existed

In Redis, command for retrieving values from sorted-set

I tried adding some sample score-value pairs to redis sorted set using below code:
String key = "set";
redis.zadd(key, 5, "1034");
redis.zadd(key, 2, "1030");
redis.zadd(key, 1, "1089");
and tried retrieving it using byteArray and BitSet
byte[] byteArr = redis.get(key.getBytes());
BitSet bitSet = fromByteArrayReverse(byteArr);
System.out.println(bitset.toString()));
also i tried executing
System.out.println(redis.get(key.getBytes()));
which is supposed to give me an address of the byte-array
But for both of these commands i get the error
" ERR Operation against a key holding the wrong kind of value"
So can anyone please tell me why does this error occur in the first place and also the correct redis command/code to retrieve values from a redis sorted-set??
What you want is calling
ZSCORE key "1034"
Or in the case of wanting only elements between two particular scores
ZRANGEBYSCORE key lower upper
Since you also have "rank" (position or index, as in a list) you can also ask for example for the first three elements in your set
ZRANGEBYRANK key 0 2
The error you are getting is because once you assign a value to a key, that value defines the type of the internal structure on redis, and you can only use commands for that particular structure (or generic key commands such as DEL and so on). In your case you are trying to mix sorted sets with byte operations and it doesn't match.
To see all sorted set commands, please refer to http://redis.io/commands#sorted_set

How Redis represents String as bits internally?

I'm trying to understand the bit representation of a String (most specifically in Redis)
I tried this:
redis> SET mykey3 hello
OK
redis> SETBIT mykey3 7 0
(integer) 0
redis> SETBIT mykey3 7 1
(integer) 0
redis> GET mykey3
"iello"
redis> SET mykey4 5
OK
redis> SETBIT mykey4 7 0
(integer) 1
redis> GET mykey4
"4"
So what is the bit representation of "hello" and "5" in this case?
Also how the other Redis types, List, Set, Sorted Set are represented as binary bit? Such that bit operations can work for it? Or this is not the case?
From what is seems everything is stored as binary-safe String? If so, how does a List, Set, Sorted Set are represented as safe String?
If you look at bitops.c you'll see that indeed bit commands only work with string key type.
From redis.io:
All the following data types are supported as values:
Binary-safe strings.
Lists of binary-safe strings.
Sets of binary-safe
strings, that are collection of unique unsorted elements. You can
think at this as a Ruby hash where all the keys are set to the 'true'
value.
Sorted sets, similar to Sets but where every element is
associated to a floating number score. The elements are taken sorted
by score. You can think of this as Ruby hashes where the key is the
element and the value is the score, but where elements are always
taken in order without requiring a sorting operation.
So only the lists and sets values are stored in binary-safe strings. This is also true for the keys and hash values as well as sorted set members.