关于聊天场景中,消息状态的设计疑问
发布于 5 年前 作者 haozxuan 2687 次浏览 最后一次编辑是 4 年前 来自 问答

需求:需要服务器知道客户端是否收到消息 已完成(或以了解): 1、使用socketio通讯时,服务器给客户端一条消息可以通过最后一个回调函数的方式获取(目前没这么做,怀疑这样做会影响客户端收消息效率); 2、客户端收到消息后再回复服务器一条消息作为上一条消息的确认,当然该条确认消息可以不实时。

目前我使用的是第二种方式,回复确认消息的结构设计: untitled1.png 纠结点:学习了mongodb一条数据的存储模式后,知晓当进行 update时,如果仅仅是简单的替换比如把name:‘haozxuan’ -》 name:‘nodejs’这样是很快,但是如果把name:‘haozxuan’ -》 name:{age:20,address:XXX,…}这样的模式将会涉及到重新申请磁盘空间,这样的update将会相对比较耗时,当然,如果换种涉及思路将结构设计成这样的: untitled2.png 收到一条回复确认消息提出一个id这样的模式将不会设计重新申请磁盘空间的问题,随之产生的是磁盘碎片。 问题二: 与之逻辑相关的还有获取离线消息,因为如果使用表结构2,我就可以获得哪些用户还未收到某条消息,就可以将相应消息推给他,不过这种结构的弊端也显而易见,是以消息为主键而非用户,综上,欢迎有相关问题或需求的大神积极讨论,有相关经验的大神不吝赐教。

Thanks All

3 回复

虽然没有遇到这样的需求,从我本人对数据库的了解来看,消息和未接受的用户是多对多的关系吧,从表设计来说可以是 { messageId: messageId, unreachUserId : userId } 这样单独的一条来看待某一条消息某一个用户未接收到,设置对应的索引,这样对于查询效率讲都是比较好的,缺点是数据冗余度高。 关于poster和messageType这两个字段我觉得放在消息详情里比较好,因为这两个从字面来讲,就是消息详情的属性啊

@joney-pinkman 消息和未接受的确是多对多,这里面有区别的是单聊的话是单对单(一个messageId对应一个用户id),群里的话就是单对多(一个messageId对应群成员id),当然你所说的多对多中数据冗余度是这边不能允许的,所以才使用单对多的模式,另外poster是为了方便debug,比如客服收到投诉说没收到通知,我就可以通过发送者和时间定位到(主要是messageId和通知内容不能对应上)。至于messageType字段是考虑到群聊天记录和个人聊天记录分开存储,拿messageId去查询消息体时准备的。

针对于unreach模式的设计,让我感觉到对mongodb数据库的使用是否不当,我考虑过将这部分数据存储在redis中,24H后再刷到数据库中的结构。不过这样的话就复杂化了而且会出现由于刷新间隙过大造成的数据不同步问题。所以才停止走这条路。

回到顶部