【系统设计】聊天系统

580 阅读2分钟

Scene

设计一个聊天系统,具备如下功能:

  1. 两个用户互相发消息
  2. 群聊
  3. 用户在线状态

Service

  • Message service 存储,读取消息
  • Push Service 推送消息

Storage

  • Thread Table 会话表,存储会话基本信息 | column | notes | | --------- | ----------- | | id | primary key | | avatar | 头像| | name | 群聊名称|

  • User Thread Table 用户会话表,存储与用户相关的会话信息 | column | notes | | --------- | ----------- | | id | primary key | | thread_id | 会话id| | unread_cnt | 未读消息数量| | is_muted | 是否免打扰|

  • Message Table 消息表 | column | notes | | --------- | ----------- | | id | primary key | | thread_id | 会话id| | user_id | 用户id| | content | 内容| | publish_at | 消息发送时间|

用户读取Message

select * from message_table
where thread_id = xx
order by publish_at desc 
limti 20

消息的发送与消息的读取 image.png

  1. 客户端A请求推送系统地址
  2. 客户端A与推送吗系统建立连接
  3. B发送消息给A
  4. 消息系统存储B的消息后,通知推送系统
  5. 推送系统推送消息通知(可以直接将消息推送过去或A在收到消息后主动pull数据)

Scale

推送系统优化

当群了人数较多时,如何不向哪些不在线的客户端发推送消息通知。 增加一个channel服务,维护用户的存活信息。

  1. 每个Thread对应一个Channel
  2. 用户上线时,订阅相关Channel;如果用户下线,push服务会得知用户掉线,通知channel service将用户从某个channel移除
  3. Message service收到消息后,通知Channel Service。
  4. Channel Service 查询某个channel当前订阅用户,将数据推送给push service
  5. Push service push通知消息

image.png

多机登陆限制

在session中记录客户端信息 用户从新的客户端登录时,查询是否有其他设备处于登陆态

  1. 如果没有,直接创建session
  2. 如果有,将已存在的session设置为过期或删除,并push消息让已登陆的设备logout

好友在想状态

  • Pull :用户主动告诉服务器是否在想

  • Push :服务器查询用户是否在线

建议使用 Pull ,客户端定期向服务端发送心跳。Pull模型的实现会更加简单。