我已经审查了每一个主题,我可以在这个,似乎不能得到答案,我在寻找,所以这里是问题。
(使用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从列表中删除项目,什么不是,但我没有看到一个更好的选择?
不管怎样,帮助或指导将不胜感激
1条答案
按热度按时间2lpgd9681#
我知道在考虑比赛条件问题之前,你有一个问题要解决!
你的网络聊天服务器是群集的,所以你需要告诉
Socket.IO
在内存中保存socket id,否则示例a中的socket客户机将无法与示例b中的socket客户机通信。聊天服务器的每个示例都运行一个独立的套接字服务器,这使得它们之间无法通信。要解决此问题,请使用
Socket.IO
redis适配器:socket.io-redis请注意
socket.io-redis
适配器使用PUBLISH/SUBSCRIBE
因此,您应该建立一个新的redis连接,以避免阻塞,而不是传递现有的redis客户端。只需将您的redis信息传递给适配器,如下所示:
回到竞赛条件主题。
为了避免那里的比赛情况,你必须打电话
get
以及set
原子的。为了实现这一点,您应该使用lua脚本和EVAL
命令以确保并发客户端将按顺序修改文件室数据。