You've already forked node-redis
mirror of
https://github.com/redis/node-redis.git
synced 2025-08-10 11:43:01 +03:00
Added documentation for REDIS optimistic lock system.
This commit is contained in:
93
README.md
93
README.md
@@ -704,6 +704,99 @@ significantly compared to firing the same commands in a loop without waiting for
|
|||||||
the result! See the benchmarks for further comparison. Please remember that all
|
the result! See the benchmarks for further comparison. Please remember that all
|
||||||
commands are kept in memory until they are fired.
|
commands are kept in memory until they are fired.
|
||||||
|
|
||||||
|
## Optimistic Locks
|
||||||
|
|
||||||
|
Using `multi` you can make sure your modifications run as a transaction, but you
|
||||||
|
can't be sure you got there first. What if another client modified a key while
|
||||||
|
you were working with it's data?
|
||||||
|
|
||||||
|
To solve this, Redis supports the [WATCH](https://redis.io/topics/transactions)
|
||||||
|
command, which is meant to be used with MULTI:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var redis = require("redis"),
|
||||||
|
client = redis.createClient();
|
||||||
|
|
||||||
|
client.watch("foo", function( err ){
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
client.get("foo", function(err, result) {
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
// Process result
|
||||||
|
// Heavy and time consuming operation here
|
||||||
|
|
||||||
|
client.multi()
|
||||||
|
.set("foo", "some heavy computation")
|
||||||
|
.exec(function(err, results) {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If err is null, it means Redis successfully attempted
|
||||||
|
* the operation.
|
||||||
|
*/
|
||||||
|
if(err) throw err;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If results === null, it means that a concurrent client
|
||||||
|
* changed the key while we were processing it and thus
|
||||||
|
* the execution of the MULTI command was not performed.
|
||||||
|
*
|
||||||
|
* NOTICE: Failing an execution of MULTI is not considered
|
||||||
|
* an error. So you will have err === null and results === null
|
||||||
|
*/
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The above snippet shows the correct usage of `watch` with `multi`. Every time a
|
||||||
|
watched key is changed before the execution of a `multi` command, the execution
|
||||||
|
will return `null`. On a normal situation, the execution will return an array of
|
||||||
|
values with the results of the operations.
|
||||||
|
|
||||||
|
As stated in the snippet, failing the execution of a `multi` command being watched
|
||||||
|
is not considered an error. The execution may return an error if, for example, the
|
||||||
|
client cannot connect to Redis.
|
||||||
|
|
||||||
|
An example where we can see the execution of a `multi` command fail is as follows:
|
||||||
|
|
||||||
|
```js
|
||||||
|
let clients = {};
|
||||||
|
clients.watcher = redis.createClient({ ... } );
|
||||||
|
clients.alterer = clients.watcher.duplicate();
|
||||||
|
|
||||||
|
clients.watcher.watch('foo',function(err) {
|
||||||
|
if (err) { throw err; }
|
||||||
|
//if you comment out the next line, the transaction will work
|
||||||
|
clients.alterer.set('foo',Math.random(), (err) => {if (err) { throw err; }})
|
||||||
|
|
||||||
|
//using a setTimeout here to ensure that the MULTI/EXEC will come after the SET.
|
||||||
|
//Normally, you would use a callback to ensure order, but I want the above SET command
|
||||||
|
//to be easily comment-out-able.
|
||||||
|
setTimeout(function() {
|
||||||
|
clients.watcher
|
||||||
|
.multi()
|
||||||
|
.set('foo','abc')
|
||||||
|
.set('bar','1234')
|
||||||
|
.exec((err,results) => {
|
||||||
|
if (err) { throw err; }
|
||||||
|
if (results === null) {
|
||||||
|
console.log('transaction aborted because results were null');
|
||||||
|
} else {
|
||||||
|
console.log('transaction worked and returned',results)
|
||||||
|
}
|
||||||
|
clients.watcher.quit();
|
||||||
|
clients.alterer.quit();
|
||||||
|
});
|
||||||
|
},1000);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
**NOTE**: Redis WATCH does not work on fields of hashes and other objects. You can watch a hash
|
||||||
|
to see if anything inside it was modified, but you cannot watch a specific hash field for a
|
||||||
|
modification.
|
||||||
|
|
||||||
## Monitor mode
|
## Monitor mode
|
||||||
|
|
||||||
Redis supports the `MONITOR` command, which lets you see all commands received
|
Redis supports the `MONITOR` command, which lets you see all commands received
|
||||||
|
Reference in New Issue
Block a user