如何在Node.js中使用redis WATCH?
How to use redis WATCH in Node.js?
背景
我有一个原子操作,我需要使用锁来防止其他客户端读取不稳定的值。
- 平台:节点 10.1.0
- 图书馆:redis
解决方案
根据官方文档,解决方法是将WATCH
与MULTI
一起使用:
问题
现在,MULTI
的用法已记录在案,我对如何使用它有了大致的了解。
var redis = require( "redis" );
var bluebird = require( "bluebird" );
var client = redis.createClient();
var multi = client.multi();
multi.hsetAsync( "test", "array", "[1, 2]" );
multi.hgetAsync( "test", "array" );
multi.execAsync( ).then( console.log ); // [ 0, "[1, 2]" ]
我知道这是 multi 的正确实现。首先我需要创建一个客户端,然后我创建一个多查询。
我知道 multi
和 client
共享相同的界面,但也不清楚我使用 hgetAsync
而不是 [=18 有什么好处(如果有的话) =] 在 multi
查询中,因为我假设 multi 所做的只是将所述请求同步添加到队列中(因此我不需要 Async 变量)。
调用 multi.execAsync( )
后,查询的执行将原子地。
但我不明白 WATCH
应该如何进入这里。我在文档中找不到任何关于它的参考,没有任何关于 REDIS 拥有的乐观锁系统的信息。
问题
所以我有以下问题:
MULTI
是否支持 WATCH
?
- 如果是这样,你能分享一个代码片段吗?
- 在此示例中使用
multi.hgetAsync( "test", "array" );
而不是 multi.hget( "test", "array" );
有意义吗?
答案
没有关于在 node-redis 中使用 WATCH 的文档。然而,我确实在 MDN 中找到了一组非常有用的技巧:
https://developer.mozilla.org/en-US/docs/Mozilla/Redis_Tips
总而言之,WATCH 应该像下面这样使用:
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
*/
});
});
});
所以,回答我的问题:
- 是的,虽然
watch
是在 RedisClient
原型上调用的,而不是在 Multi
原型上调用的。
- 上面提供的代码片段。
- 因为来自对象的每个方法都具有
Multi
原型 returns 对象本身,使用 Async
版本的方法没有任何好处,除了 execAsync
它允许您执行多个查询并处理 Promise 中的响应而不是回调。
重要提示
另一个非常重要的事情是 watch
仅适用于 KEYS,不适用于散列 。所以在我的例子中,你不能看散列 test
的字段 array
。您可以观看整个 test
集,但不能观看特定领域。
所以,因为在我的代码中,我实际上想查看哈希上的字段。这不可能。我必须改用一个允许这样做的密钥命名系统:
var redis = require( "redis" );
var bluebird = require( "bluebird" );
var client = redis.createClient();
var multi = client.multi();
client.watchAsync( "test_array" )
then( ( ) =>
multi.set( "test_array", "[1, 2]" )
.get( "test_array" )
.execAsync( )
)
.then( console.log ); // [ 0, "[1, 2]" ]
这方面的文档真的很少,但我希望这个问题对以后的人有所帮助。
你在读这篇文章吗from the future?
如果你是从未来阅读这篇文章,你现在可以享受我对 node_redis
项目的个人贡献并查看更新的文档:
背景
我有一个原子操作,我需要使用锁来防止其他客户端读取不稳定的值。
- 平台:节点 10.1.0
- 图书馆:redis
解决方案
根据官方文档,解决方法是将WATCH
与MULTI
一起使用:
问题
现在,MULTI
的用法已记录在案,我对如何使用它有了大致的了解。
var redis = require( "redis" );
var bluebird = require( "bluebird" );
var client = redis.createClient();
var multi = client.multi();
multi.hsetAsync( "test", "array", "[1, 2]" );
multi.hgetAsync( "test", "array" );
multi.execAsync( ).then( console.log ); // [ 0, "[1, 2]" ]
我知道这是 multi 的正确实现。首先我需要创建一个客户端,然后我创建一个多查询。
我知道 multi
和 client
共享相同的界面,但也不清楚我使用 hgetAsync
而不是 [=18 有什么好处(如果有的话) =] 在 multi
查询中,因为我假设 multi 所做的只是将所述请求同步添加到队列中(因此我不需要 Async 变量)。
调用 multi.execAsync( )
后,查询的执行将原子地。
但我不明白 WATCH
应该如何进入这里。我在文档中找不到任何关于它的参考,没有任何关于 REDIS 拥有的乐观锁系统的信息。
问题
所以我有以下问题:
MULTI
是否支持WATCH
?- 如果是这样,你能分享一个代码片段吗?
- 在此示例中使用
multi.hgetAsync( "test", "array" );
而不是multi.hget( "test", "array" );
有意义吗?
答案
没有关于在 node-redis 中使用 WATCH 的文档。然而,我确实在 MDN 中找到了一组非常有用的技巧:
https://developer.mozilla.org/en-US/docs/Mozilla/Redis_Tips
总而言之,WATCH 应该像下面这样使用:
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
*/
});
});
});
所以,回答我的问题:
- 是的,虽然
watch
是在RedisClient
原型上调用的,而不是在Multi
原型上调用的。 - 上面提供的代码片段。
- 因为来自对象的每个方法都具有
Multi
原型 returns 对象本身,使用Async
版本的方法没有任何好处,除了execAsync
它允许您执行多个查询并处理 Promise 中的响应而不是回调。
重要提示
另一个非常重要的事情是 watch
仅适用于 KEYS,不适用于散列 。所以在我的例子中,你不能看散列 test
的字段 array
。您可以观看整个 test
集,但不能观看特定领域。
所以,因为在我的代码中,我实际上想查看哈希上的字段。这不可能。我必须改用一个允许这样做的密钥命名系统:
var redis = require( "redis" );
var bluebird = require( "bluebird" );
var client = redis.createClient();
var multi = client.multi();
client.watchAsync( "test_array" )
then( ( ) =>
multi.set( "test_array", "[1, 2]" )
.get( "test_array" )
.execAsync( )
)
.then( console.log ); // [ 0, "[1, 2]" ]
这方面的文档真的很少,但我希望这个问题对以后的人有所帮助。
你在读这篇文章吗from the future?
如果你是从未来阅读这篇文章,你现在可以享受我对 node_redis
项目的个人贡献并查看更新的文档: