Redis creating a Set with expiry - redis

When I create a new Set (using SADD) I need to set the expiration for that Set.
Is there any way to create a Set key with expiry?
Note: I need to do that in one command, because my program checks if the set exists before going to update it - so if its existing with no expiration no update will occur.
My program runs on AWS so if I split it to 2 commands, only the creation can be executed without the expiration (happened to me in the past).
Thanks!
I couldn't find a way to set expiry on a Set other than using the EXPIRE command - risking in the program crashing before the EXPIRE command (i.e. AWS service restarting for any reason) and the Set existing with no expiration.
Edit: I found a work-around, when I can check if the TTL of the key is < 0 instead of EXISTS, so if the EXPIRE didn't work for some reason I will update the Set anyway. This can help but I prefer to also save traffic when expiring the Set, and send one command (i.e. SADD with expiry) instead of SADD and EXPIRE.

What about using transactions? For example:
multi
sadd key member1 member2 ...
expire key seconds
exec
It is guaranteed that the sadd and expire will be executed as a single unit on the node and on replicas if you use any. If you use pipelining you don't need to do it in multiple rounds from the client so perf will have minimal / no impact.

Related

Avoid distributed lock when executing an update transaction on Redis?

I have the following Redis read/writes needs to be run in a transaction (atomically).
Read key 1
Read key 2
Read key 3
Write key X
And,
When a transaction is running, other processes are not allowed to write key 1, 2, 3, or X.
The transaction is atomic, no two transactions can be run at the same time.
I can use Redis lock (distributed lock) to achieve this. However, I heard that a lot of time it cannot acquire the lock from another team. Is it a way to avoid Redis lock?

How do I ensure I have TTL for every key in Redis?

I insert values to Redis, with the following code :
await this.redisClient.rpushAsync(namespaceKey, value);
await this.redisClient.expireAsync(namespaceKey, TTL);
If code fails after the first command, I'll have an entry in Redis without TTL -> forever.
How can I ensure I have TTL for every key in Redis?
Will using MULTI-EXEC solve my problem? from Redis documentation I see that Redis does not support rollbacks, so in that case, the first command (rpush) succeed but the second command fail, and there is no rollback, so I'll have key without TTL.

Redis - keys disappear

Is it possible to disappear keys in Redis without reason? I'm adding keys to redis:
Transaction transaction = jedis.multi();
transaction.incrBy(positionsQuantityKey, positionQuantity);
transaction.expire(positionsQuantityKey, 24 * 3600);
transaction.exec();
but after few minutes I ran command:
jedis.keys("*");
and the key disappeared. What could delete this key? I'm sure that expire time was succesfully set, because result of this command was 1.
I'm using redis 2.6
If you're not doing anything else with Redis during that time, open a MONITOR session with redis-cli and look what goes on - another process could be deleting your key.
Alternatively, perhaps you're running low on RAM and Redis' eviction policy is configured to evict volatile keys.

Is MGET atomic?

If I fetch the value of multiple keys with MGET, is it guaranteed that nothing will be able to modify any of the keys requested while the command is being processed and until redis returns them? The documentation unfortunately says nothing about the atomicity of this command.
Yes - MGET is atomic. All of Redis' commands are.

Voluntary transaction priority in Oracle

I'm going to make up some sql here. What I want is something like the following:
select ... for update priority 2; // Session 2
So when I run in another session
select ... for update priority 1; // Session 1
It immediately returns, and throws an error in session 2 (and hence does a rollback), and locks the row in session 1.
Then, whilst session 1 holds the lock, running the following in session 2.
select ... for update priority 2; // Session 2
Will wait until session 1 releases the lock.
How could I implement such a scheme, as the priority x is just something I've made up. I only need something that can do two priority levels.
Also, I'm happy to hide all my logic in PL/SQL procedures, I don't need this to work for generic SQL statements.
I'm using Oracle 10g if that makes any difference.
I'm not aware of a way to interrupt an atomic process in Oracle like you're suggesting. I think the only thing you could do would be to programmaticaly break down your larger processes into smaller ones and poll some type of sentinel table. So instead of doing a single update for 1 million rows perhaps you could write a proc that would update 1k, check a jobs table (or something similar) to see if there's a higher priority process running, and if a higher priority process is running, to pause its own execution through a wait loop. This is the only thing I can think that would keep your session alive during this process.
If you truly want to abort the progress of your currently running, lower priority thread and losing your session is acceptable, then I would suggest a jobs table again that registered the SQL that was being run and the session ID that it is run on. If you run a higher priority statement it should again check the jobs table and then issue a kill command to the low priority session (http://www.oracle-base.com/articles/misc/KillingOracleSessions.php) along with inserting a record into the jobs table to note the fact that it was killed. When a higher-priority process finishes it could check the jobs table to see if it was responsible for killing anything and if so, reissue it.
That's what resource manager was implemented for.