Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js Redis没有';当一次有多个请求时,无法更新_Node.js_Redis - Fatal编程技术网

Node.js Redis没有';当一次有多个请求时,无法更新

Node.js Redis没有';当一次有多个请求时,无法更新,node.js,redis,Node.js,Redis,我有一个Node.js应用程序,我正在尝试使用Redis缓存来记录请求的数量。这只是一个概念证明,看看Redis是否是适合我的工具,但我对结果有点失望,我想知道Redis的性能是否真的很差,或者我的代码中是否有缺陷 我有以下代码: const express = require('express') const Redis = require('ioredis') const client = new Redis(6379, 'redis'); client.on('connect', fu

我有一个Node.js应用程序,我正在尝试使用Redis缓存来记录请求的数量。这只是一个概念证明,看看Redis是否是适合我的工具,但我对结果有点失望,我想知道Redis的性能是否真的很差,或者我的代码中是否有缺陷

我有以下代码:

const express = require('express')
const Redis = require('ioredis')

const client = new Redis(6379, 'redis');

client.on('connect', function() {
    console.log('Redis client connected');
});

client.on('error', function (err) {
    console.log('Something went wrong ' + err);
});

const getRedisCount = async (question_id) => {
    const count = await client.get('votes_' + question_id);

    if(count) {
        return count;
    }

    await setRedisCount(question_id, 0)
    return 0;
}

const setRedisCount = async (question_id, count) => {
    await client.set('votes_' + question_id, count)
}

const app = express();
app.use(express.json());

// post a vote
app.post('/vote', async (req, res) => {
    let count = await getRedisCount(req.body.question_id)
    count++
    await setRedisCount(req.body.question_id, count)

    res.status(200).send({ status: 200, data: count });

})

app.listen(5000, () => {
    console.log('Vote service listening on port 5000')
})
现在,当我在Postman中执行一个post请求时,所有这些都如预期的那样工作。计数器将按预期更新

但是当我在JMeter中运行一个测试,一次执行150个请求时,在最后一个请求之后,我得到的计数是20-30,而不是预期的150


所以我的问题是-这是预期的行为,还是我的代码中的错误?在这两种情况下-如何修复它?

这可能与您的redis服务器配置有关

您可以在主机上从redis cli运行监视器

通常通过cli进行连接,例如:

这应该给你一个问题的指示

您还可以从redis cli运行INFO命令,查看服务器统计信息和内存使用情况等信息

redis>INFO
#服务器
redis_版本999.999.999
redis_git_sha1:3c968ff0
redis\u git\u dirty:0
redis_build_id:51089de051945df4
redis_模式:独立
操作系统:Linux 4.8.0-1-amd64 x86_64
拱形位:64
多路复用api:epoll
atomicvar_api:原子内置
gcc_版本:6.3.0
进程id:8394
另外,在代码中使用redis客户端的INCRBY命令,否则需要在设置它之前增加您的计数值,这与异步模式不一致

我想你的问题是因为这是异步的,对吗

因此,当它们被发布时,计数是不同步的,因为一些计数可能会在其他计数之前等待


无论采用哪种方式,您都希望尝试同步发布它们,看看这是否会产生影响,然后您就知道这是问题所在,最好使用redis INCR命令来实现这一目的

听起来像是原子性问题

// post a vote
app.post('/vote', async (req, res) => {
    let count = await getRedisCount(req.body.question_id)
    count++
    await setRedisCount(req.body.question_id, count)

    res.status(200).send({ status: 200, data: count });

})
假设计数是20,那么您的150个请求中的许多请求将读取20作为其值

    let count = await getRedisCount(req.body.question_id)
下一条语句将递增并将count设置为21,下一行将尝试将其保存到redis

这是一个标准的比赛条件,更好的解释

您必须在代码中实现
,或者使用redis提供的锁来解决此问题


锁基本上会将每个请求排队,一个接一个地递增,以避免覆盖值。

不确定这是否可行,但可能会使用
GETSET
?我正在尝试这一点,因为我有同样的问题


谢谢!monitor命令告诉我,例如,在一行中执行了4次该命令:“set”“voates_1”“2”,这让我觉得这更像是一个代码问题-它不应该在一行中设置4次数字2,它应该将其设置为2、3、4、5等。因此,当前它没有在负载平衡器中运行,只有一个Vote服务实例,因此,它绝对不应该多次设置相同的数字。嗯,好的,如果你提交投票时查看浏览器调试工具,它是否每次单击只将其发布到web服务器一次?我没有使用我的浏览器。我用Postman做了一次投票,ApacheJMeter一次做了150次,我发现它错过了这一部分。谢谢。你的代码中肯定有一个缺陷。读/增量/写入算法不是原子算法,这意味着具有不同计数器值的不同读写可以以任何方式交错,并可能导致计数丢失-这正是您所经历的。我对node.js不太熟悉,所以我无法给出正确的答案,但您想使用的是redis增量操作:。您对这里的性能影响有何看法?
redis> INFO
 # Server 
 redis_version 999.999.999
 redis_git_sha1:3c968ff0
 redis_git_dirty:0
 redis_build_id:51089de051945df4
 redis_mode:standalone 
 os:Linux 4.8.0-1-amd64 x86_64 
 arch_bits:64 
 multiplexing_api:epoll
 atomicvar_api:atomic-builtin 
 gcc_version:6.3.0
 process_id:8394
 </snip>
// post a vote
app.post('/vote', async (req, res) => {
    let count = await getRedisCount(req.body.question_id)
    count++
    await setRedisCount(req.body.question_id, count)

    res.status(200).send({ status: 200, data: count });

})
    let count = await getRedisCount(req.body.question_id)