Comments (5)
I totally share the point of @lucaong, the WATCH message should be sent before entering into the transaction. In my view it protects a key from concurrent modification between the WATCH call and the execution of the transaction. WATCH takes a snapshot of the current state of a key and when the transaction updates the key then it can do a compare and fire exception if not. So the timing of the WATCH is important!
After looking into the code it turns out that you can manually send the WATCH to redis.
watch <- redis.send(redis.api.transactions.Watch(Set("foo")))
I'm not sure about the drawbacks of this workaround but it seems working.
from rediscala.
I understand your use case.
In rediscala, you can't read inside a transaction, because you will be blocking the client for other requests.
I suggest you try to look if you can do your check in a LUA script. (transform the transaction in a lua script)
from rediscala.
First of all thanks for the great rediscala :)
Was this closed because it is not implementable or not advisable to implement?
I might be missing something, but In Redis you can implement optimistic locking this way (pseudocode, variable assignment and arithmetic would not really work in the cli):
WATCH foo
current = GET foo
MULTI
SET foo + 1
EXEC
The problem is that in rediscala, I can see no way of sending the watch
and making sure it is processed before proceeding. It looks to me, also as suggested by @dlangdon, that this could be accomplished by having watch
and exec
both return a future. It would enable optimistic locking of the sort:
for {
watch <- redis.watch("foo")
original <- redis.get("foo")
updated = original + "baz"
result <- redis.multi().set("foo", updated).exec()
} yield result
If the future returned by exec
would fail because of race conditions, one could retry the whole thing.
Am I missing something? This would be incredibly useful. In case this is feasible, I will try to get accustomed to rediscala source and see if I can help on this.
from rediscala.
From what I understood from @etaty the problem is a mismatch on session semantics and blocking. (have not verified exactly what the actual code does so take this with a grain of salt). The issue is that redis has blocking sessions.
In the scala client, each request opens a connection, sends the call, and returns a future. When there is a reply from redis the future is completed, callbacks called and the connection freed. While this happens, any new call will work on a separate session and the client itself will not block. You could, I guess, run out of connections in the pool, which is a risk when your code is going ahead at full speed while previous calls might be slower to finish.
Transactions are apparently implemented as an aggregation of commands that are then executed one by one by the TransactionManager in a single session, after exec() is called, completing futures as it goes. So, while the transaction might LOOK asynchronous, it is blocking all the time. YOUR scala code knows nothing of this though, as it works on the futures as they are completed, not blocking.
If this interpretation is correct (and I will leave it to @etaty to validate hehe) then IMHO the issue is the way the TransactionBuilder works. The only thing needed to execute code like the one you mention is to be able to refer to the same session you had when you sent the watch command, and to be able to make multiple calls on it on each future, finally making a call that frees the entire thing.
This is in practice the ability to make redis calls synchronously one after the other, even from async code (like your example). The risk is in a single connection being blocked for a long period, especially if YOUR code takes a while to do its stuff.
IMHO, if the tradeoffs are well explained, I would like this alternate approach as it would provide better semantics than the actual blocking client.
from rediscala.
It is closed because not advisable to implement
You should use http://redis.io/commands#scripting
You can even do your task in the example with one command : http://redis.io/commands/setrange
@dlangdon your are almost correct
Transaction cmd are sent in a batch (watch multi cmds exec). You need to call exec
to sent the batch.
A transaction in rediscala is only useful :
- if you want to perform the transaction only if no other client modified any of the WATCHed keys.
- if you want to be sure no other command (from rediscala) is inserted between your transaction commands.
from rediscala.
Related Issues (20)
- can update akka 2.5.10+? HOT 2
- stop() not part of a trait
- Question: How to distinguish between operation failures
- Timeouts for RedisClientPool
- rediscala endless retry loop when connection fails
- Redis streams support? HOT 1
- This is a mistaken issue..deleted.
- UnsupportedClassVersionError HOT 8
- Redis Protocol error: Got 43 as initial reply byte
- Please make a patch release, with fixes for RedisCluster
- Smembers is set as isMasterOnly = true HOT 1
- [Question] why sentinel not support sentinel auth?
- [Question] Should RedisClientPool extend Transactions?
- [Question] Use SSL to Authenticate
- creating a RedisClient from a typed akka behavior
- [Question] Akka Dispatch error when using rediscala.
- How we can do health check for redis cluster using `redisscala`?
- Null pointer exception at redis.RedisCluster.$anonfun$onConnectStatus$1
- A new connection is getting created every time
- Support for pekko HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from rediscala.