igo*_*lov 10 javascript redis node.js node-redis
我在RedisOnGo + node_redis上使用NodeJS + Express + Redis作为客户端.我期待很多并发,所以试图测试WATCH.这个例子不包含Express,只是必要的东西.
var redis = require("redis")
var rc = redis.createClient(config.redis.port, config.redis.host)
rc.auth(config.redis.hash, function(err) {
if (err) {
throw err
}
})
rc.on('ready', function () {
rc.set("inc",0)
for(var i=1;i<=10;i++){
rc.watch("inc")
rc.get("inc",function(err,data){
var multi = rc.multi()
data++ // I do know I can use rc.incr(), this is just for example
multi.set("inc",data)
multi.exec(function(err,replies){
console.log(replies)
})
})
}
})
Run Code Online (Sandbox Code Playgroud)
期待结果:在exec回调中得到N个错误,最后得到"inc"变量= 10-N.
意外的结果:在exec回调中得到0错误,但最终得到"inc"变量= 1.
Watch无法使用我的代码.
我发现这个线程redis和watch + multi允许并发用户.他们说这是因为唯一的redis客户端.
然后我发现这个线程我应该为每个连接创建一个新的Redis客户端吗?.他们说为每笔交易生成一个新客户"绝对不推荐".我搞不清楚了.
另请注意,我必须向Redis服务器进行身份验证.提前致谢!
第1版:
通过在每次WATCH-MULTI-EXEC迭代之前创建新的客户端连接,我能够使用本地Redis实例(因此我不使用client.auth).不确定它是否好,但结果现在是100%准确.
版本2 如果我在每次WATCH-MULTI-EXEC迭代之前创建一个新的客户端连接,然后执行client.auth并等待client.on,它就可以工作了.
问题仍然存在,我是否可以为每次迭代创建新的客户端连接?
mis*_*ion 18
您的结果完全可以预测.这是正确的.
请记住 - node.js是一个线程应用程序.Node.js使用异步输入输出,但命令应该在redis中严格按顺序发送"请求 - 响应".因此,当您只使用一个连接到redis服务器时,您的代码和请求将严格并行执行.
看看你的代码:
rc.on('ready', function () {
rc.set("inc",0)
for(var i = 1; i <= 10; i++){
rc.watch("inc")
//10 times row by row call get function. It`s realy means that your written
//in an asynchronous style code executed strict in series. You are using just
//one connection - so all command would be executed one by one.
rc.get("inc",function(err,data){
//Your data variable data = 0 for each if request.
var multi = rc.multi()
data++ //This operation is not atomic for redis so your always has data = 1
multi.set("inc",data) //and set it
multi.exec(function(err,replies){
console.log(replies)
})
})
}
})
Run Code Online (Sandbox Code Playgroud)
要确认这一步,请执行此步骤:
monitor命令.输出将是
SET inc 0
WATCH inc
GET inc
.... get command more 9 times
MULTI
SET inc 1
EXEC
.... command block more 9 times
Run Code Online (Sandbox Code Playgroud)
这样你就可以得到你上面写的结果:"在exec回调中得到0个错误,但最终得到"inc"变量= 1.".
您是否可以为每次迭代创建新的客户端连接?
对于这个样本 - 是的,它解决了你的问题.通常 - 它取决于您要运行多少"并发"查询.Redis仍然是一个线程,所以这个"并发"意味着只需要并发命令批处理到redis引擎.
例如,如果使用2个连接,则monitor可以给出如下内容:
1 SET inc 0 //from 1st connection
2 WATCH inc //from 1st connection
3 SET inc 0 //from 2nd connection
4 GET inc //from 1nd connection
5 WATCH int //from 2nd connection
6 GET inc //from 2nd connection
7 MULTI //from 1st connection
8 SET inc 1 //from 1st connection
9 MULTI //from 2nd connection
10 SET inc 1 //from 2nd connection
11 EXEC //from 1st failed becouse of 2nd connection SET inc 0 (line 3)
//was executed after WATCH (line 2)
12 EXEC //success becouse of MULTI from 1st connection was failed and SET inc 1 from first
//connection was not executed
-------------------------------------------------------------------------------> time
| | | | | | | | | | | |
connection 1 set watch | get | | multi set | | exec(fail) |
connection 2 set watch get multi set exec
Run Code Online (Sandbox Code Playgroud)
理解redis如何执行命令非常重要.Redis是单线程的,所有连接中的所有命令都是逐行执行的.Redis不保证来自一个连接的命令将连续执行(如果此处存在另一个连接),所以如果要确保您的命令执行一个块(如果需要),则应该是MULTI.但为什么需要WATCH呢?看看我上面的redis命令.您可以看到来自不同连接的命令是混合的.并且手表允许您管理这个.
这在文档中精美地解释了.请仔细阅读!
| 归档时间: |
|
| 查看次数: |
9522 次 |
| 最近记录: |