默认
发表评论 9
想开发IM:买成品怕坑?租第3方怕贵?找开源自已撸?尽量别走弯路了... 找站长给点建议
求分布式IM集群系统中,用户在线状态的存储、读取等方案的建议
阅读(66327) | 评论(9 收藏 淘帖1
大家好,求助一个问题,目前我这边im的架构是   维持长连接的接入层----->业务分发层-----> 业务层 -----> 数据代理层------->数据存储层。除了底层的数据存储层,其他的服务使用腾讯开源的Tars RPC框架,服务都是多点部署,客户端目前支持安卓、IOS、WEB三种客户端 连接到接入层,对于离线的APP用户,要根据上传的Push deviceToken推送,长远来看,最多同时在线用户可能是10W左右。目前遇到的问题是如何保存客户端在线状态,我现在的做法是把所有的用户在线状态保存在redis集群的一个hash表,field是 imid+clientType 中,value是接入层信息及客户端版本号等信息,但是对于群聊业务,消息风暴系数很大。比如500人群,每一条消息,我要去这个这个hash表中hmget 500人*3客户端类型/人=1500 个 filed 去获取群成员在线信息,这个hash是一个bigKey,又频繁存取(上下线要hset或者hdel,发消息要hmget),目前导致redis集群开销较大,是不小的瓶颈。同时在线状态存储又要考虑到如果某个接入层down了以后,要能够把该接入层所有的用户下线。

目前我的一个设想方案不知是否能优化。现在我是将一个大hash按照用户id 取模N(比如100)分成N个小hash表,然后推消息的时候,把现在查询一次在线状态的操作分成用户id取模(不妨设成M)个查询小hash的操作,不知道这样是否可以提高redis集群的吞吐量,目前还没有实验,另外一个问题是这样把RPC调用的次数极大的增加了,本来我一次查询就可以拿到所有用户的在线状态,业务层只需要调用一次分发层,即可将消息由分发层拼装后转给接入层,但是现在分成M个操作后,读取redis集群的RPC的次数都要变成M倍,RPC次数相应增加很多。
另一个方案是将用户所有的心跳每次传到redis,同时设置过期时间,每次心跳重新expire时间,如果接入层挂掉的话,过期后用户自然不在接入层中,这样可以将接入层信息存在key->value结构中,key是 imid+clientType,value是接入层信息

求问各位,在项目中这种是如何处理用户连接管理的,还请不吝赐教! 也求版主大大能给一些建议。

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

上一篇:求教怎么向所有的IM客户端发送消息下一篇:哪里获取BAT等公司关于IM的博客或论文原文?尤其是微信和钉钉的技术文章

本帖已收录至以下技术专辑

推荐方案
评论 9
是的,你方案中,这个redis恰恰又变成了单点瓶颈了。

你仔细读一下这篇文章,应该可以给你启发:
一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践
引用:JackJiang 发表于 2019-04-23 17:44
是的,你方案中,这个redis恰恰又变成了单点瓶颈了。

你仔细读一下这篇文章,应该可以给你启发:

好的,谢谢版主大大,我先研究下。从项目刚开始调研就经常看52im,不过最终各种原因废弃了看到的许多优秀方案,做的东西质量大打折扣,现在已经上线几个月了,功能迭代基本完善之后,扩量遇到很大的问题。
引用:Ray_vm1f2 发表于 2019-04-23 18:01
好的,谢谢版主大大,我先研究下。从项目刚开始调研就经常看52im,不过最终各种原因废弃了看到的许多优秀 ...

是的,im这种系统很不标准,千人有千种思路,所以只能是遇到什么问题就按照自已场景来优化和解决,不存在完美的方案的。
你们的系统设计用户量是多大?就是个通用的im系统吗?
引用:Shahala 发表于 2019-04-23 18:32
你们的系统设计用户量是多大?就是个通用的im系统吗?

目标是未来要同时在线10W+。目前只提供给仿照钉钉的一款内部办公im在使用,人数较少,未来想融入其他im业务
引用:JackJiang 发表于 2019-04-23 18:16
是的,im这种系统很不标准,千人有千种思路,所以只能是遇到什么问题就按照自已场景来优化和解决,不存在 ...

嗯,不过方案还是有好坏之分,目前算不上多坏,但离好还差得远。技术实力也差,完全没有大项目经历,用C++,很多东西也没有技术支持,还需要多学习
和我们的架构相似度极高,也是用redis hash 哈哈哈。
用hash就是因为有手机(安卓 苹果) 和 web + pc(mac windows) 3端,用一个key就可以保存所有端,问题也特别明显,和你说的一样。
直接存储到接入层的内存里可不可以,发送消息的时候因为不知道用户在哪个接入层的机器,那就广播,根据UID去发消息,各个接入层收到请求后,判断这个用户ID在本机是否在线,如果在线就推送,否则不推送
打赏楼主 ×
使用微信打赏! 使用支付宝打赏!

返回顶部