redis获取并设置竞态条件问题

svujldwt  于 2021-06-08  发布在  Redis
关注(0)|答案(1)|浏览(448)

我已经审查了每一个主题,我可以在这个,似乎不能得到答案,我在寻找,所以这里是问题。
(使用node.js)
我有一个群集的聊天服务器。当一个用户加入一个房间时,把他们的数据放在redis中

redis.get(room, function(err, results){
if ( results !== null)
{

var myData {socket:socket.id,name:nickName};
results.push(myData)
myData = JSON.stringidy(myData);
redist.set(room,myData)
}
}

我不确定这是否是最好的方法,但我的目标是在房间里保留一个简单的人员列表。
但是,如果用户离开房间,我将执行与上述类似的任务,获取redis键,序列化并将用户从数组中弹出,然后将其字符串化并放回。
我的问题是,如果说一个用户同时离开和加入,我会遇到竞争条件吗。所以情况是这样的
用户加入聊天室,密钥会用他们的信息更新,但是与此同时,另一个用户离开聊天室并更新密钥,本质上,离开的用户可能会从加入中得到较旧的集,所以joinroom可能不是最新的?
我已经读到redis是set和get的原子,但是我也看到了种族条件的提及,所以我很困惑这是如何工作的?
我会遇到问题还是redis会阻塞直到操作完成并移动到下一个调用?我也不相信我的方法是最好的方法,因为我必须字符串化etc从列表中删除项目,什么不是,但我没有看到一个更好的选择?
不管怎样,帮助或指导将不胜感激

2lpgd968

2lpgd9681#

我知道在考虑比赛条件问题之前,你有一个问题要解决!
你的网络聊天服务器是群集的,所以你需要告诉 Socket.IO 在内存中保存socket id,否则示例a中的socket客户机将无法与示例b中的socket客户机通信。聊天服务器的每个示例都运行一个独立的套接字服务器,这使得它们之间无法通信。
要解决此问题,请使用 Socket.IO redis适配器:socket.io-redis
请注意 socket.io-redis 适配器使用 PUBLISH/SUBSCRIBE 因此,您应该建立一个新的redis连接,以避免阻塞,而不是传递现有的redis客户端。
只需将您的redis信息传递给适配器,如下所示:

io.adapter(redisAdapter({ host: 'localhost', port: 6379 }));

回到竞赛条件主题。
为了避免那里的比赛情况,你必须打电话 get 以及 set 原子的。为了实现这一点,您应该使用lua脚本和 EVAL 命令以确保并发客户端将按顺序修改文件室数据。

相关问题