标签:记录 开放 客户端 不同 个人 sequence 推送 场景 先来
作为一个IM系统,核心场景为单聊、群聊。单聊是1对1聊天;群聊是,多个人在一个群里聊天。
无论是单聊还是群聊,抽象出会话确实不错,单聊就是两个人在一个会话中聊天,群聊就是多个人在一个会话中聊天。假设会话模型叫做session,则应该有如下的特征:
对于单聊场景,
A发送消息给B,AB构成的会话ID由A/B两个账号ID确定,比如叫做session-a-b,则A发送消息给B可以理解为往会话session-a-b中新增一条消息。
无论是A发送消息给B,还是B发送消息给A,都是将消息放入session-a-b。
单聊会话数据模型设计:
session_id,为会话ID;
sender_account_id,为消息发送人账号ID;
receiver_account_id,为消息接收人账号ID;
假设不考虑消息查看功能,则理论上,只需要使用一个queue,将会话中的消息按照先来先进的顺序,逐个放入queue即可;
但因为考虑到消息查询,所以我们不能用queue存储,而是要使用比如RDS这种关系型数据库存储,
单聊会话消息的数据模型为:
session_id,会话ID;
message_id,为消息ID,全局唯一;
message_type,为消息类型;
message_body,为消息内容;
sequence,为消息在会话中的序号,全局自增;
time,为消息产生时间;
单聊会话的消息查询实现逻辑:
A/B中任何一个人要查询和对方的聊天记录,
1、客户端传给服务端session_id、要拉取会话消息的起始sequence,调用网关接口查询消息;
2、服务端通过session_id、sequence到上面的单聊会话消息数据表中查询session_id匹配,sequence大于给定sequence的消息记录,可以一次只返回有限的记录,客户端分批查看,因为有可能未读消息很多;
对于群聊场景,
是所有群成员都在向同一个群聊会话中发送消息,且群聊会话中的消息对所有群成员开放,也就是所有群成员看到的都是群聊会话中的同一份消息。
群聊会话数据模型:
session_id,为会话ID;
group_id,为群组ID;
群会话消息的数据模型:
我们发现,群会话消息模型和单聊会话的消息模型是一样的,只是会话类型不同,故我们扩展一下单聊会话消息的数据模型,增加一个会话类型,如下所示:
通用会话消息数据模型:
session_type,会话类型:单聊、群聊;
session_id,会话ID;
message_id,为消息ID,全局唯一;
message_type,为消息类型;
message_body,为消息内容;
sequence,为消息在会话中的序号,全局自增;
time,为消息产生时间;
群聊会话的消息查询实现逻辑:
群组中的任何一个群成员要查询群聊会话的聊天记录,
1、群成员客户端传给服务端session_id、要拉取会话消息的起始sequence,调用网关接口查询群会话消息;
2、服务端通过session_type、session_id、sequence到上面的群会话消息数据表中查询session_type、session_id匹配,sequence大于给定sequence的消息记录,可以一次只返回有限的记录,客户端分批查看,因为有可能未读消息很多;
关于群成员的数据模型设计:
group_id,群组ID;
group_member_account_id,群成员的账号ID,单个群内唯一;
通过以上的模型设计,无论是单聊还是群聊,客户端发送消息到服务端,服务端的处理逻辑只是在当前的会话中持久化一条消息即可。会话消息持久化完成后,通过消息推送服务(如个推),
对于单聊场景,如果收消息的人在线,则推送一条通知消息给收消息的人的所有在线的客户端设备;
对于群聊场景,则推送通知消息给群里所有其他在线成员的所有在线的客户端设备;
当然,服务端为了削峰填谷,我们可以在服务端收到客户端的发送消息的请求后,先发把消息发送到MQ(比如rocketmq),然后MQ的消费者异步的方式去持久化会话消息,以及推送通知给客户端设备。客户端设备收到通知后,向服务端发起新消息的查询请求,请求逻辑上面已经描述。
标签:记录 开放 客户端 不同 个人 sequence 推送 场景 先来
原文地址:https://www.cnblogs.com/netfocus/p/11249066.html