IM数据库的设计在移动端,往往和业务是高度耦合的,换句话说就是,数据库的结构直接决定你的业务怎么实现,所以在IM开发中,数据库的设计直接关系到整个IM的实现方式。
我们可以明确一下,在客户端中哪些需要使用数据库的场景或者说条件有哪些,这有助于我们决定数据库的设计逻辑。当然,我们可以设计很复杂的数据库,当设计后的数据库出现在你面前时,你或许能知道你不需要哪些,此时你可以删除不需要的。
客户端使用数据库的条件
- 数据需要持久化。如果业务数据需要长期保存,且不能随着程序的结束而消失,那么需要使用数据库进行持久化存储。
- 数据需要频繁查询。如果业务数据需要频繁查询,例如通过某些关键字进行搜索,那么需要使用数据库进行高效的查询。
- 数据需要修改。如果业务数据需要频繁修改,例如添加、删除、更新等操作,那么需要使用数据库进行数据的修改。
- 数据需要跨越多个用户和系统。如果业务数据需要跨越多个用户和系统,那么需要使用数据库进行数据的共享和传递。
在进行数据库设计时,需要根据业务需求进行设计,并考虑数据结构、数据访问、性能等因素,确保数据的安全性、完整性和可用性。同时,也需要考虑数据库的扩展性,确保能够应对业务发展的需要。
我们可以以此为参考决定是否需要一张表。
分析
以微信为例
首先我们分析一下IM客户端的业务有哪些,然后再结合业务梳理 哪些需要落库,然后再设计数据库。 我们分析时要紧扣它的业务场景和数据来源。
1.1 客户端聊天列表
我们记为im_chat_list.
-
用途:用于展示IM 聊天记录
-
数据来源:在线数据 + 离线数据
- 在线数据: 当用户在线时,数据通过长连接推送,此时数据称为在线数据
- 离线数据: 当用户不在线时,消息会缓存到服务器,当用户在此在线时,需要同步离线消息,此时称为离线数据
-
分析: 这个列表的数据是增量增长的,也是批量增长的,也有可能是一次性的,对应以下几个状态,
- 当本地存在数据时,我们希望只更新新增的数据
- 当本地没有数据时,我们需要全部的数据(按需求而定)
但归结起来,我们需要一张表,一张用于储存聊天列表的表,该表中的数据元素有:
- 头像
- 用户名
- 最新一条聊天内容
- 时间
- 未读数
- 群、订阅号、私聊(类型)
表1 消息列表
然后我们分析一下这个表,从面向对象的角度来看,他是不符合单一指责原则的,因为它既有用户消息又有聊天内容,还有消息列表。所以我们需要精简一下这张表,解析分析,看怎么精简。
- 服务端面对上述“既有用户消息又有聊天内容,还有消息列表”的状况是更加糟糕的,因为他需要查询多张表才能拼出一条对应的数据,
- 我们发现,每创建一条消息列表,不论是什么类型,都会出现对应的“用户概念”:
- 私聊: 用户就是对方的信息
- 群聊: 用户就是群的信息(群头像、昵称)
- 订阅号: 用户就是订阅号的信息
当用户信息发生变化时,我们需要更新用户信息,这是一个很独立的概念,所以我们需要一张表,用以存储用户信息(当然,就微信而言,存在好友关系时,我们必须有一张表用来存储所有用户的信息)
那怎么优化上述表呢?,很简单,我们将在表中添加一个聊天对方的id, 这个id 就是用户的id,在整个系统中,它是能表示用户的唯一属性,然后我们利用id 关联两个表,
更新消息列表
表2 消息列表
1.2 用户表
建立用户表
这样操作后,消息列表的职责变为消息列表和会话信息了,我们是为消息列表设计的,所以直接去分析消息,怎么去除它。
消息在IM项目中,肯定是需要单独存储的,因为用户聊天是增量的,我们必须持久化,才能避免大量的网络请求。此时我们分析消息列表和消息的关系,他们共同的元素是:
-
消息列表id
-
会话方id(用户id)
所以我们可以直接用消息列表中的user_id 关联聊天消息的表,以此完成最后一条消息的显示。此时消息列表变为:
1.3 聊天记录表
聊天记录表:
部分业务流程
更新的核心思想就是主要处理聊天记录表,其他表在聊天记录表的驱动下被动更新,但是同步离线消息场景需要单独处理。
流程图
首先明确一下需要参与的对象
- 发送者A,接收者B
- 消息表
- im_chat_list: 列表
- im_chat_0: 聊天记录表(如果涉及到群聊,聊天记录表可以分表处理,按照用户属性分表,后续有机会分享)
- im_user: 聊天与话方用户信息表
这个文章智能分析到此,这是最简单的一个场景,在IM中,离线消息,消息连续检测等都需要处理,有需要详细了解的可以直接私我。