redis select 插入出错
发布于 9 年前 作者 mengda1027 3540 次浏览 最后一次编辑是 8 年前 来自 问答

初学redis,写了个小demo,预想目标:db0-db9每个插入一条数据,现实情况是全部都插入到db9了,请帮忙看下,谢谢。

app.js提供服务:

var express = require("express");
var bodyParser = require('body-parser');
var redis = require("redis");
var client = redis.createClient("6379","192.168.205.161");
var app = express();
app.use(bodyParser());
app.post("/",function(req,res){
    client.SELECT(req.body.id,function(){
        client.HMSET(req.body.id,req.body,function(err){
            if(err){
                console.log("插入失败");
                return false;
            }
            console.log("插入成功");
            client.EXPIRE(req.body.id,86400);
        });
    })
});
app.listen("3001");

利用request模拟post请求

var request = require("request");

for(var i = 0;i<10;i++){
    (function(i){
        request.post({
            url:'http://127.0.0.1:3001/',
            json:{'id':i}
        });
    })(i);
}

2002063907-5719ef4121bcb_articlex.jpg

4 回复

应该for循环的原因,i直接就是9了,你调试下看你req.body.id是多少

把 var client = redis.createClient(“6379”,“192.168.205.161”); 放到路由函数里面

模拟请求的部分是正确的,问题出在 select 命令和 hmset 命令不是同时执行上。具体来说,10 个请求同时发生,这是会同时执行 10 个 select 命令,所有最后一个是 select 9,接下来会执行 10 个 hmset 命令,这样所有的数据都会写入到 9 号 db 中了。当然这个顺序和网络时延有关,你可以在 redis-cli 中执行 monitor 来查看所有命令的顺序。

解决方法是使用 Redis 的 transaction 或者客户端的 pipelining。使用 pipelining 的例子是:

var express = require('express');
var bodyParser = require('body-parser');
var Redis = require('ioredis');
var client = new Redis('6379', '192.168.205.161');
var app = express();
app.use(bodyParser());
app.post('/',function(req,res){
  client.pipeline()
  .select(req.body.id)
  .hmset(req.body.id,req.body)
  .exec(function (err) {
    if(err){
      console.log('插入失败');
      return false;
    }
    console.log('插入成功');
    client.pipeline().select(req.body.id).expire(req.body.id, 86400).exec();
    res.json({ success: true });
  });
});
app.listen('3001');

@luinlee 明白了,非常感谢

回到顶部