腾讯IM SDK的群组的学习

群组是im系统里一个非常核心的功能,也是容易产生性能问题的部分,常见im在一对一的问题不多,这个也没啥可多说的,但是在群聊的时候却有很多不同的特征的。

我们可以在腾讯im sdk里看到对于群组共有5组不同的分类 https://cloud.tencent.com/document/product/269/1502

  1. 好友工作群(work): 这个其实类似于一个微信群,最大人数是6000人。这种就是一个全功能的群,我们也知道微信群是没法通过外部搜索来加入的,只能通过邀请制。这种群是可以没有群主和管理员的,但是因为是邀请制,理论上第一个人就是群主。
  2. 陌生人社交群(public):这个类似于qq群,最大人数也是6000人,可以通过群号来添加。然后群主可以来确认是否加入。所以这种群肯定是有群主和管理员的。
  3. 临时会议群(meeting):这种一般就是临时拉起的qq群,最大人数也是6000人,可以通过群号来加入。但是是无需邀请的,所以这种群完成任务后就尽快关闭。
  4. 直播群(acchatroom):这个就是直播场景,当然跟前面1,2,3种有特别大的区别,其实就是我们常说的聊天室。聊天室一般都是没有人数上限的,因为相比群来说阉割了很多功能。
  5. 社群(community) :这个一般认为是一个bbs的场景,人数理论上也是没有上限的。

同时我们可以看到腾讯的im sdk里支持3种消息的qos

  1. high:一般是红包和礼物信息
  2. normal:一般普通消息
  3. low:低优先级的消息比如点赞这样的消息

所以从研发角度来看,就是1,2,3这3种和4和5这两种群的差异,以及内部大概是如何实现的。

1,2,3这样的群我们一般就是标准的推拉模式,当人数小于多少的群我们一般使用推的模式,消息写入到每个人自己的消息队列里,而超过多少人的群,那消息一般就用拉的模式,在每个人的消息队列里只有这个群消息的seq,而不是存放对应的消息id.

聊天室一般都是人非常多的,所以一般都是拉取的模式,同时一般聊天室都不会存历史消息,而腾讯文档里可以看到,这里是不存放历史消息,但是可以获取另外一个设备的漫游消息,如果另外一个设备之前登陆了这个聊天室,并且拉取了对应的消息,那另外一个设备再登陆后应该是通过漫游来拉取这个聊天室的历史消息,所以腾讯im sdk的漫游消息是针对id来存放的。而且聊天室的消息就是即时拉取的,并不会去存放到历史消息的队列里。

同时腾讯im sdk为了保证可用性,它还特别限制了聊天室和群这些都是每秒最多发送40条消息,我理解这个应该是在端上sdk和服务器端两头都会控制的。

再来看下社群这个功能。虽然腾讯限制了10万人的上限,而且可扩充至百万级。但是我们又看到它是有离线消息的,不像聊天室那种是完全没有离线消息的。那它这个模型跟聊天室和群应该是不一样的。
而且腾讯特别注明了 社群(Community)功能支持终端 SDK 5.8.1668增强版及以上版本、Web SDK 2.17.0及以上版本

这个版本是2021年11月才发布的,那肯定是改了点什么才会支持的。

不过这个其实海外sendbird这些也都有 https://sendbird.com/docs/chat/sdk/v4/android/channel/overview-channel

因为人数太多,就算是拉的模型,那上百万人老是拉那肯定是不行的,必须要降低拉的人数,那怎么又能存历史消息,又保证同时拉取的人少呢。上面sendbird的介绍里提供了一个思路。
那就是只有用户聊天界面在这个社群里,这个时候才会去拉消息,而如果不在这个群的聊天界面里,去到了别的群里或者单人对话窗口里,那这个社群的消息就不会主动去拉取,而且腾讯应该会限制拉取这个社群的聊天记录条数或者天数,这样就大大降低了整体消息拉取的数量。

老实说这个确实是一个方法来降低消息扩散,点进那个社群里就算是bbs里手动刷新了一次。

再看看这个群组信息是怎么存的。


可以看到这里有4个字段是无法修改长度的,那应该就是数据库对应字段的长度了,这个一般修改起来很麻烦。 而LastInfoTime和LastMsgTime这些信息很明显用数据库存是很不值当的,这些信息变更频率非常高,那样明显会带来很大的操作压力。也有可能是存了,但是属于定时更新的。

同时我们也看到了群类型是无法变更的,这就是说创建的时候就要想好,这个无法后期再更改。如果是自定义群组id的话,也只能先删除再创建了。可见每种type创建的时候腾讯针对不同的type会有不同的存储形式和资源,这种变更就会非常麻烦。

再顺便看看单聊消息是怎么存的。

https://cloud.tencent.com/document/product/269/3571

对于单聊,未读消息默认保存7天,每个用户的未读消息最多保存250个单聊会话的未读消息,每个单聊会话最多保存100条未读消息。

首先我们可以看到腾讯对于离线消息是针对用户和用户的级别,就是会给他每个单聊都单独存放,而且缓存长度是100条。这个如果用kv存放的还是用list或者stream了。而且还会设置一个过期时间。

其次比较奇怪的一点是离线消息缓存和历史消息存储。显然这是两种不同格式的消息,我理解可能离线消息缓存估计是用kv这样的比较方便。而这里图片里的历史消息存储服务器,在下文中又变成了漫游服务器,那看来还是漫游和离线分开存。但是我还是觉得他们应该搞过历史服务器,而且可能不一定是腾讯自己存,也有可能是存放在客户自己服务器上,然后通过服务器去取,至于客户服务器怎么来的消息,不是有回掉嘛。