默认

如何保证IM实时消息的“时序性”与“一致性”?

查看数: 271915 | 评论数: 38 | 收藏 24
关灯 | 提示:支持键盘翻页<-左 右->
    组图打开中,请稍候......
发布时间: 2017-02-17 12:09

正文摘要:

本文作者沈剑,原创发表于“架构师之路”公众号,原题“消息“时序”与“一致性”为何这么难?”,本次内容有修订和改动。 1、前言 我们都知道,一个典型的分布式系统中,很多业务场景都需要考虑消息投递的时序, ...

评论

Frank 发表于 11 个月前
引用:JackJiang 发表于 2018-12-27 19:32
im这种产品很讲究现实情况。

我们回归到现实:假设你现在正在一个QQ群里,一般正常的群聊,大家都是你 ...

确实,看直播类的 超过20,就开始分级别丢了
Frank 发表于 11 个月前
引用:JackJiang 发表于 2023-03-16 11:54
其实从产品的角度来说,单个单聊或单聊群聊之内,消息不可能那么活跃(正常的聊天几秒一条就算是刷的很厉 ...

qq 应该就是按照一个会话一个seq
JackJiang 发表于 1 年前
引用:一剑开天 发表于 2023-03-16 11:45
以下是我的理解,如有误欢迎指出。

方案一:客户端seq字段        生成位置:客户端        作用:确定来自同一设备发 ...

其实从产品的角度来说,单个单聊或单聊群聊之内,消息不可能那么活跃(正常的聊天几秒一条就算是刷的很厉害了),所以这单个单聊或单聊群聊之内发生id碰撞或错乱的可能性不大。何况万一出现,im聊天这种工具也是能容忍万有一失的,qq也是这样的设计逻辑
一剑开天 发表于 1 年前
以下是我的理解,如有误欢迎指出。

方案一:客户端seq字段        生成位置:客户端        作用:确定来自同一设备发出消息的时序(先发的消息,序号在前)        适用场景:单聊
方案二:全局单调递增唯一消息id        生成位置:服务端        作用:确定来自不同设备发出消息的时序(先到server的消息,id在前)        适用场景:群聊

针对群聊时序问题的优化
问题描述:
如果使用全局单调递增唯一消息id,当活跃用户过多时,就会有大量请求密集到生成消息id的服务器,虽然这里也可以搞多个机器,但是这一步与db交互,时间成本与硬件成本都会比较高,从而成为系统瓶颈。
优化方案:
让来自同一个群聊的消息命中到同一个server,"全局单调递增唯一消息id"就变成了"局部单调递增唯一消息id",这样一来,各个服务就可以通过缓存来维护消息id,减轻了系统负担。
JackJiang 发表于 1 年前
引用:Frank 发表于 2023-02-23 22:03
这里请教下,假定按照 seq 排序,那时间怎么显示,会不会有乱序的?

时间这个东西,你观察一下大厂的im,尤其是淘宝的那个旺旺你就知道,这东西真没你想的那种绝对严格。
必须im聊天就是人说话,不是发射火箭,并没有要求一定要做到高精尖,不影响产品体验的前提下,是允许万有一失的
Frank 发表于 1 年前
引用:JackJiang 发表于 2018-12-27 19:32
im这种产品很讲究现实情况。

我们回归到现实:假设你现在正在一个QQ群里,一般正常的群聊,大家都是你 ...

这里请教下,假定按照 seq 排序,那时间怎么显示,会不会有乱序的?


或者说:返回seq的时候包含了时间,这样就没有问题了
Frank 发表于 1 年前
引用:JackJiang 发表于 2017-06-12 10:13
你可以在客户端进行处理,你观察一下微信和qq,不过可能会因为国内的网络太好而很难碰到这种情况的话,你 ...

wx_OdEsBIyL 发表于 2 年前
引用:weixiaoyao 发表于 2018-12-27 17:55
群聊时当多个发送者A,B都发送群消息时,服务端序列方式也无法保证多个发送者的消息序列,假设A先发,B后发 ...

A的家里用的是10M带宽, B的家里用的是千兆光纤, 那B的速度快先展示也没办法啊, 谁叫A的家里穷呢
Monkey 发表于 3 年前
不错的文章
JackJiang 发表于 4 年前
引用:916422 发表于 2020-05-21 16:42
可能我没描述清楚,是每个会话都要生成独有seq空间么?

理论上是的
916422 发表于 4 年前
引用:JackJiang 发表于 2020-05-20 13:36
会话间不一定要唯一,但会话内一定要唯一

可能我没描述清楚,是每个会话都要生成独有seq空间么?
夏日里的春天 发表于 4 年前
JackJiang 发表于 4 年前
引用:916422 发表于 2020-05-20 10:37
是每个会话都要有一组唯一的seq么?

会话间不一定要唯一,但会话内一定要唯一
916422 发表于 4 年前
是每个会话都要有一组唯一的seq么?
七海的游风 发表于 4 年前
这篇很赞!我们目前是读扩展的timeline模型,群聊和单聊统一,都是严格单调递增的position标记消息,用mysql分片表事务保证position的原子性
妮子 发表于 4 年前
沈剑老师,给力啊
JackJiang 发表于 4 年前
引用:shi553210541 发表于 2019-09-11 11:23
学习了,不过要做到全一致性真的很困难

允许万有一失
shi553210541 发表于 4 年前
学习了,不过要做到全一致性真的很困难
JackJiang 发表于 5 年前
引用:weixiaoyao 发表于 2018-12-27 17:55
群聊时当多个发送者A,B都发送群消息时,服务端序列方式也无法保证多个发送者的消息序列,假设A先发,B后发 ...

im这种产品很讲究现实情况。

我们回归到现实:假设你现在正在一个QQ群里,一般正常的群聊,大家都是你一句我一句,按打字速度,和大家的理解速度,再频繁的聊天,基本上都是几秒才出现一条,且很有规律,因为对话总是你一句我一句。这种情况下,每条消息的间隔,至少有几秒钟,按照服务器的处理效率来说,本身也比较难以出现后一条消息先于前一条送达。

你可能坚持认为,肯定会存在消息一条接一条,而且间隔极短,那不就有很大几率出现了吗?但:那就是如果是这样情况,那还是聊天吗?不可能这个在收到那个人发出的消息瞬间就发出了自已的消息,因为他需要理解时间、需要打字时间。你可能还坚持说,肯定有这种情况,但换个思路想想,极短的时间内群内出现大量消息,那不这就是刷屏吗,哪还是聊天?既然是刷屏消息,它到底有没有乱序,你作为群员怎么判断的出来(因为没有上下文关联意义)?或者有什么意义要判断出来?

所以。我的个人观点是,群聊消息顺序这种事情要想保证理论上的绝对正确,难度很高,但回归现实,这种问题可以很简单的处理,不需要纠结绝对的理论。

评分

2

查看评分

weixiaoyao 发表于 5 年前
群聊时当多个发送者A,B都发送群消息时,服务端序列方式也无法保证多个发送者的消息序列,假设A先发,B后发,接收方C收到并显示的消息,可能是先B后A,仍是乱序,服务端序列化只能保证多个接收方C,D,E收到并显示的都是先B后A。这该如何能保证接收方显示的百分百和发送方的顺序一致呢?或者是否有必要保证这种顺序呢?

返回顶部