关于即时通讯:im即时通讯开发群聊消息是即扩散读还是即扩散写

5次阅读

共计 1766 个字符,预计需要花费 5 分钟才能阅读完成。

im 即时通讯开发:群聊音讯是即扩散读还是即扩散写?

最根本的计划:“在线的群友不存储音讯,离线的群友才存储”

群信息,用户信息,群成员关系都是根底数据:

group_info(gid, group_info);

user_info(uid, user_info);

group_members(gid, uid);

假如一个群 (gid) 里有 4 个成员,其中三个在线(A, uid1, uid2),一个不在线(uid3)。

A 发送了一条音讯,很容易想到,对于不同的群友音讯存多份,每个群友一个队列来存储。但因为在线的用户会实时的收到音讯,所以暂定只为离线的用户存储。

用户收到的群音讯,也是根底数据:

user_msgs(uid,msgid,gid,sender_uid,time,content);

1)发送音讯;

2)查问状态;

3)不在线的存储离线;

4)在线的实时推送。

“在线的群友不存储,离线的群友才存储”会带来的问题是,如果第四步产生异样,群友会失落音讯。

优化的计划:“不论群员是否在线,都要先存储音讯”

音讯的可达性是聊天零碎中最重要的因素(没有之一),故这个计划是不行的,须要优化为“不论是否在线,都要先存储”。

发送群音讯的流程优化为,

1)发送音讯;

2)所有人都存一份;

3)查问状态;

4)在线的实时推送。

先将音讯落地,可能保障音讯可达性,那何时能力删除曾经落地的群音讯呢?咱们持续往下看。

对于在线的群友:收到群音讯后,给个 ack 确认能力删除。

画外音:逻辑删除,还是物理删除,依据业务是否有音讯漫游决定。

对于离线的群友:在下次登陆后,拉取完离线音讯再给 ack 确认能力删除。

总之:为了保障音讯的可达性,不论是在线音讯还是离线音讯,必须接管方给 ack 确认,能力删除音讯。

不论群员是否在线,都冗余一份群音讯”带来的问题

“不论是否在线,都冗余一份群音讯”带来的问题是:同一条音讯存储了很屡次,对磁盘和带宽造成了很大的节约。

很容易想到的优化是:群音讯实体存储一份,用户只冗余音讯 ID。即时通讯聊天软件开发能够征询蔚可云。

故根底数据能够由:

user_msgs(uid,msgid,gid,sender_uid,time,content);

优化为:

group_msgs(msgid,gid,sender_uid,time,content);

user_msgs(uid, msgid, gid);

这个优化,对于音讯投递,以及音讯删除的外围流程没有影响,几个实际为:

在线用户投递音讯实体,ack 音讯 ID;

离线用户先拉取音讯 ID,再拉取音讯实体,再 ack 音讯 ID。

如此这般,如果在某个群友 A 期间,群里陆续发送了 N 条音讯,则 user_msgs(uid, msgid, gid)里,会有 uidA -> mid1,mid2, mid3, … midN 等 N 条离线记录,拉取离线音讯时,能够把这 N 条音讯一次性拉取出来,而后再删除:

delete from user_msgs where msgid in($mid1,$mid2…, $midN) and gid=$gid

终级计划:利用群音讯的“偏序”个性优雅地实现“只存 1 份”

然而,群音讯具备“偏序”个性,下面的一次性删除齐全能够优化为:

delete from user_msgs

where msgid >= $mid1 and gid=$gid

这就意味着,每个用户只须要记录“最近一次收到的音讯 ID”,而不必记录“所有未收到的音讯 ID 汇合”,每当收在线音讯 ack,以及拉离线音讯 ack 时,只须要更新这个“最近一次收到的音讯 ID”即可。

于是乎,根底数据能够由:

group_members(gid, uid);

group_msgs(msgid,gid,sender_uid,time,content);

user_msgs(uid, msgid, gid);

优化为:

group_members(gid, uid, last_ack_msgid);

group_msgs(msgid,gid,sender_uid,time,content);

user_msgs(uid, msgid, gid); // 不再须要

即:群音讯只存储一份,群友无需冗余任何音讯实体,或者音讯 ID 了。

对于在线的群友:收到群音讯后,批改这个 last_ack_msgid。

对于离线的群友:拉取群音讯后,也批改这个 last_ack_msgid。

正文完
 0