4 ms·
Maybe you missed the point ;-) I said this and later showed how the Redlock unique token per lock can be used to guarantee the same. So it's equivalent, but yet
by antirez 11y ago
Maybe you missed the point ;-) I said this and later showed how the Redlock unique token per lock can be used to guarantee the same. So it's equivalent, but yet very non credible model in production. When you have a way to avoid a mess when a race condition happens, it's better to avoid a distributed lock at all, to start with.
- tptacek 11y agoCan you further explain your "check" and "set" storage example? I feel like you might be begging the question. "check" and "set" seem like they describe another lock. How does that lock time out?
- antirez 11y agoWhatever you can mount with a random token is always simpler than checking if Token_ID_A < Token_ID_B which needs a linearizable store. But basically this is how it works: You want to modify locked resource X. You set X.currlock = token. Then you read, do whatever you want, and when you write, you "write-if-currlock == token". If another client did X.currlock = somethingelse, the transaction fails. Edit: note that I noticed some confusion about this. Any other client is free to replace X.currlock even if set to a past value.
- deleted 11y ago[deleted]
- kapitalx 11y agoThe problem with this solution is that if A writes Token_A to resource, and then A dies, then the resource can never be written to again. How do you avoid not needing to time out the 'curr_lock'
- SomeCallMeTim 11y agoNo, when you acquire a lock, you are allowed to write to currlock immediately. It's AFTER you've done whatever processing you need to do that you do a compare-and-set transactional write that verifies no one else has written to currlock between your acquisition and the completion of your task.
- bogdando 11y agoThis pseudo code for random fence tokens should work as well safe as Martin's scenario with incremental IDs in the original article: try token=lock.aquire val=raw(shared, key, token) do_things awar(shared, key, val, token) except fail("Can't do!") finally lock.release Where a shared object has: 1) a key to store a value being changed in the critical section; 2) a currlock to store a random fence token associated with a lock. The raw reads the shared key's value after the currlock was written to the shared object. The awar does an atomic write of the value to the key, only if the currlock has an expected token (i.e. is unchanged). When things go wrong, the do_things may be executed more than once, in parallel, but the key is safe and guaranteed to have no lost updates to its value.
- viraptor 11y agoBut your "write" action is separate from the "X.currlock" operations, right? Doesn't it mean that this can happen? A: X.currlock = Token_ID_A A: resource read A: is X.currlock still Token_ID_A? yes B: X.currlock = Token_ID_B B: resource read B: is X.currlock still Token_ID_B? yes B: resource write A: resource write Is there anything that makes the "write-if-currlock == token" operation atomic?
- tptacek 11y agoYes: it turns out, he's stipulating a single server, in which case this is a trivial feature to build. The problem then is, if you're willing to have that single point of failure, you don't need a lock service at all.
- w8rbt 11y agoPerhaps he means test and set? https://en.wikipedia.org/wiki/Test-and-set Or the more efficient test and test and set? https://en.wikipedia.org/wiki/Test_and_test-and-set
- eternalban 11y agoIssue here is detection of conflicting ops vs. fact of conflicting ops. The monotonic sequence provides that detection means. So in the example you gave, the tardy (expired) tx commit would abort since its lock id would break the monotonic sequence of accepted lock-ops (which clearly can have gaps, 1, 2, 4, 6, 7, ... etc.[)]