默认
发表评论 11
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
服务端的Session可以存放在Redis中实现集群吗?
阅读(23776) | 评论(11 收藏 淘帖
看当前的代码实现中,Session默认是从本机的ConcurrentMap获取的;

如果用户量足够大,是不是ConcurrentMap会出现OOM?

另外一个问题就是当部署多台机器的时候,每台机器存储的是部分用户信息,看全局发送使用的是RabbitMQ,但是感觉MQ也不能保证消息路由到有目标用户Session的机器上啊。

能不能考虑吧RabbitMQ替换为Redis,多机访问同一个Redis从而实现用户会话共享,在获取用户会话的时候直接从Redis中获取。

总结下,两个问题:
1、本次使用ConcurrentMap会不会有OOM问题?
2、部署集群的时候能不能使用Redis存储Session,Redis怎么存储Netty的Session对象?

即时通讯网 - 即时通讯开发者社区! 来源: - 即时通讯开发者社区!

上一篇:接入层如果使用websocket还需自已实现心跳机制吗?下一篇:求教关于IM用户信息和群聊信息缓存的差异更新和拉取问题
推荐方案
评论 11
1、ConcurrentMap存的只是channel引用,相当于指针,地个内存地址而已,要是因为它搞出OOM,那这里面存的数据量那大的吓人。。。

2、不能,IM的连接是长连接,是不能存在集中式的redis这样的东西里面。

如果想写im集群的话,你可以从下面的文章和代码中先学习一下:

跟着源码学IM(四):拿起键盘就是干,教你徒手开发一套分布式IM系统
跟着源码学IM(九):基于Netty实现一套分布式IM系统
跟着源码学IM(十):基于Netty,搭建高性能IM集群(含技术思路+源码)
跟着源码学IM(十一):一套基于Netty的分布式高可用IM详细设计与实现(有源码)

我这里有一个方案,使用Bitmap数据结构保存用户的在线状态,读取状态时间复杂度为o(1),空间复杂度一个用户占用1个bit位,也就是说在占用极低的内存的情况下又可以得到一个o(1)的时间复杂度,真是鱼和熊掌兼得。在这样的一个数据结构的加持下,立马可以为当前消息应该路由到哪一台IM服务器上提供了一个方案,IM集群的最大问题就解决了。我画个图(宿舍电脑没有visio,就用手画了)。



我觉得这个设计有一个弊端。你是一个多服务。如果其中一台服务挂了。在bitmap中的数据就不一致了。我觉得可以通过hash结构存redis。结构为<userId,userInfo>。设置一个有效时间。每次客户端心跳时候都主动去更新这个时间。利用redis中的hyperloglog统计存在的key值。即可统计目前在线的人数。
签名: 嘿嘿嘿
引用:JackJiang 发表于 2022-09-09 19:53
搞个集中式的key=userid,value=serverid,这样的列表管理在线用户

这又是空间换时间了
引用:LFC 发表于 2022-09-09 17:56
假设有n台服务器,判断用户在哪台机器上就是下面这个伪代码的逻辑
[mw_shl_code=java,true]for(IMServer ...

搞个集中式的key=userid,value=serverid,这样的列表管理在线用户
引用:JackJiang 发表于 2022-09-09 10:30
"在判断用户在哪台服务器上时,需要遍历服务器来判断用户到底在哪台服务器上":没明白,为什么要遍历?

假设有n台服务器,判断用户在哪台机器上就是下面这个伪代码的逻辑
for(IMServer server:servers){
       if(online(userid,server)){
            //用户在这台服务器上,转发消息
           return;
       }
} //用户不在线



引用:LFC 发表于 2022-09-09 01:02
我这里有一个方案,使用Bitmap数据结构保存用户的在线状态,读取状态时间复杂度为o(1),空间复杂度一个用 ...

"在判断用户在哪台服务器上时,需要遍历服务器来判断用户到底在哪台服务器上":没明白,为什么要遍历?
引用:aihe521 发表于 2022-08-30 23:12
Java存储几十几百G应该靠的是集群吧;

如果Session存在单机上,发送C2C消息的时候,首先用Redis获取到 ...

我这里有一个方案,使用Bitmap数据结构保存用户的在线状态,读取状态时间复杂度为o(1),空间复杂度一个用户占用1个bit位,也就是说在占用极低的内存的情况下又可以得到一个o(1)的时间复杂度,真是鱼和熊掌兼得。在这样的一个数据结构的加持下,立马可以为当前消息应该路由到哪一台IM服务器上提供了一个方案,IM集群的最大问题就解决了。我画个图(宿舍电脑没有visio,就用手画了)。 服务端的Session可以存放在Redis中实现集群吗?_7_)48C[2C)I6IZX9F61Y`U8.jpg
性能瓶颈:在判断用户在哪台服务器上时,需要遍历服务器来判断用户到底在哪台服务器上,这个操作会带来一个o(n)的时间复杂度,但这个Reactor的网络模型单机并发量很高,也就意味着n不会很大,我认为这个时间复杂度是完全可以接受的。

以上纯纯本人拙见,希望能帮到你。
引用:aihe521 发表于 2022-08-30 23:12
Java存储几十几百G应该靠的是集群吧;

如果Session存在单机上,发送C2C消息的时候,首先用Redis获取到 ...

老哥,做的啥系统,session可以占用几十、几百G的内存~
引用:aihe521 发表于 2022-08-30 23:12
Java存储几十几百G应该靠的是集群吧;

如果Session存在单机上,发送C2C消息的时候,首先用Redis获取到 ...

RPC、MQ都可以
引用:JackJiang 发表于 2022-08-30 11:29
1、评什么redis能存几十几百G的数据,java不能?
2、Redis里可以存用户id以及用户所连接im的实例信息,但 ...

Java存储几十几百G应该靠的是集群吧;

如果Session存在单机上,发送C2C消息的时候,首先用Redis获取到对方的用户session在哪一台机器上?然后再把数据路由到另外一台机器?  
如果是路由的话,路由到另外一台机器在IM中有什么好的实现方式吗?



1、评什么redis能存几十几百G的数据,java不能?
2、Redis里可以存用户id以及用户所连接im的实例信息,但不能直接存Netty的Session对象,因为存了也没意义。对于网络通信来说,能与客户端通信的,只能是直接与它连接的im实例,这是常识了。
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部