原帖子是这样的 http://www.52im.net/thread-1230-1-1.html
问题是这个
主要的问题是用户在线情况下,收到一条消息(此时还有些离线消息没有同步), 那客户端消息数据的最新 seq 就是这条在线消息。这可能导致有些离线消息不能同步到客户端
想请问下针对这个问题,怎么解决
1
imn1 2022-03-06 17:43:30 +08:00
没做过,但以前看过前端同事做过类似的
异步或不同线程接收,然后前端排序刷新,注意刷新频率 “不能同步”这个应该是单线程的原因? |
2
awanganddong OP 可以理解为单单通过 seq 可以获取最新的消息标识,但是无法区分离线消息是否已经被拉取完毕。
|
3
Building 2022-03-06 17:54:39 +08:00 via iPhone
先放在客户端 Dispatch 队列里啊,等离线消息都拉完同步了再 Dispatch 。
|
4
awanganddong OP 这个文章是如何优雅的实现大量离线消息的可靠投递 和楼上的想呼应的。但是还是没解决我的问题。https://segmentfault.com/a/1190000023318638
|
5
Building 2022-03-06 18:08:00 +08:00 via iPhone
@awanganddong 大量离线消息为什么要同步到本地?一般只需要在注册推送前同步最后的几条消息和未读角标就行了,上拉的时候再去拿未读的消息。
|
6
documentzhangx66 2022-03-06 18:23:11 +08:00
1.客户端消息数据的最新 seq 可能导致有些离线消息不能同步到客户端,解决方案:
服务端,把每一条客户端需要接收的消息,加 4 个字段: 消息接收时间(此条数据的产生时间)、消息同步到客户端的时间、客户端确认已收到该消息的时间、客户端已阅读该消息的时间。 2.可靠投递的实现方式,是客户端以分布式事务的方式,从服务端获取消息。事务执行成功,则更新上述 4 个字段中的某个字段。你可以直接找个分布式事务的组件来用就行。 3.大量消息的优化投递方式:批量投递 + 分批投递 + 每批压缩。 4.你要做企业级 IM ,请拒绝 UDP ,因为很多企业级防火墙与网管,把 UDP 传输无脑当攻击。 |
7
awanganddong OP @Building 对,但是这里边有个点我没太明白,比如上线后,在线消息,直接推送本地,保存 sqlite 。同时起个线程,根据 seq 倒序拉数据到 sqlite 。然后主线程从 sqlite 取上翻数据是这样的吗?
|
8
awanganddong OP @documentzhangx66 设置这四个字段的深意我现在还不太理解。
|
9
des 2022-03-06 19:15:20 +08:00 via iPhone
你的意思是“最新 seq ”覆盖了?
这种一般会在 app 启动的时候就去启动同步的进程 |
10
documentzhangx66 2022-03-06 19:16:55 +08:00
@awanganddong
这 4 个字段,是解决你说的同步问题的的消息同步逻辑。 比如,客户端会先加载服务端数据库的 [消息同步到客户端的时间] 为 NULL 的数据,这个字段为 NULL ,意思是客户端还没把这些消息进行拉取。当客户端完成拉取这些消息后,这个字段会设置为客户端完成拉取的时间。 接着,此时客户端有可能会崩溃,因此 [客户端确认已收到该消息的时间] 这个字段的意思是,当客户端,把这些消息,完成落盘,并稳定地显示了一段时间后,该字段才会被设置为客户端的当前时间。否则,该字段为 NULL ,意思是,客户单已经拉取了消息,但在展示前,可能出现问题,需要客户端重新拉取这些消息。 其他字段也是差不多的意思,当整个流程要设计的完备,就需要这 4 个字段,也就能避免你说的 [有些离线消息不能同步到客户端] 的问题。 |
11
Building 2022-03-06 19:19:29 +08:00 via iPhone
@awanganddong 啊,主线程是不能参与数据处理工作的,主线程只能处理 UI 交互,所有的消息都由 Dispatch 经手,Dispatch 分发出来的消息顺序肯定是正确的,Dispatch 把消息分发给储存器,储存器储存后再分发给会话,会话加入消息列表,渲染 UI ,或者先分发给会话,会话再分发给储存器,或者同时分发,都可以,不是重点。如何保证 Dispatch 的顺序性,已经说过了,注册推送前已经拿过一次未读消息了,否则注册不了推送,推送开启后可以下一条消息带着上一条消息的 hash 来保证消息的连续性。至于刷历史消息,不是 Dispatch 的活,另外实现。
|
12
awanganddong OP |