05 | 消息序号生成器:如何保证你的消息不会乱序?
该思维导图由 AI 生成,仅供参考
为什么消息的时序一致性很重要?
为什么保证消息的时序一致性很困难?
- 深入了解
- 翻译
- 解释
- 总结
消息序号生成器对于保证消息时序一致性非常重要。文章首先介绍了消息时序一致性的重要性,指出时序不一致可能导致语义不连贯、误解等问题。然后分析了保证消息时序一致性的困难之处,主要是由于实际场景中存在多发送方、多接收方、服务端多线程并发处理的情况。接着详细讨论了如何找到时序基准的问题,分别从发送方本地序号和本地时钟、IM服务器的本地时钟以及全局序列三个方面进行了分析。最后指出全局序列生成器可以作为时序基准,通过多种方式实现,如Redis的原子自增命令incr、DB自带的自增id、Twitter的snowflake算法等。文章内容深入浅出,为读者解决了消息时序一致性的问题提供了有益的指导。 文章还讨论了“时序基准”的可用性问题,以及在多发送方、多接收方、服务端多线程并发处理的情况下,保持消息时序一致的重要性及处理方法。对于即时消息收发场景,保证消息接收时序的序号生成器不一定需要是全局递增的,而是可以通过全局的序号生成器或分布式时间相关的ID生成服务来确定时序基准,以及通过服务端包内整流机制或消息接收端整流来保证消息的时序一致性。整体而言,本文深入探讨了消息时序一致性的重要性及解决方法,对于即时消息业务的开发和实践具有一定的指导意义。
《即时消息技术剖析与实战》,新⼈⾸单¥59
全部留言(61)
- 最新
- 精选
- 深藏Blue最近遇到IM相关需求,好像是第一个收下这个专栏的极客er。请教栏主:能否指导下具体的技术选型?跪急!服务端主要由spring cloud系列开发,终端应用有 win pc、安卓以及ios
作者回复: 具体的量级是多少呀?消息使用场景是写多读少还是读多写少?量级小的话存储用mysql就可以,量级大的话也可以考虑hbase。nio框架用netty就可以,离线缓存buffer可以用redis或者pika,未读数放redis的hash里就可以。手机端mqtt改造一下或者直接json也可以,浏览器端就websocket + json就行。
2019-09-10542 - Gojustforfun希望老师多补充一些流程图或代码来帮助理解,光看文字因经验不足,有时很难想象理解,甚至会引发歧义。谢谢
编辑回复: 感谢您的建议,已增加了两张流程图来具体说明一下在离线消息推送过程中服务端整流的实现机制。
2019-09-06736 - 王棕生问题: 在即时消息收发场景中,用于保证消息接收时序的序号生成器为什么可以不是全局递增的? 答: 这是由业务场景决定的,这个群的消息和另一个群的消息在逻辑上是完全隔离的,只要保证消息的序号在群这样的一个局部范围内是递增的即可; 当然如果可以做到全局递增最好,但是会浪费很多的资源,却没有带来更多的收益。
作者回复: 👍
2019-09-0624 - javaworker老师,请教几个问题 1.您文中说消息通过网关后,IM后台都是并发处理,所以先发的消息有可能后到达。 我想问如果同时发给一个人的消息,也要IM后台并发处理吗?如果这样路由如何控制?比如其中一条消息丢了,我需要查问题,我如何能知道这条消息是路由到哪台机器哪个线程处理的? 2.您文中说IM时序基准以IM服务器的时间为准也不行,因为是集群部署。我公司现有IM系统,就是按照IM服务器的时间做的时序基准,比如A和B两个用户都给C发送消息,系统会按照C的userid按照一定路由规则,最终路由到一台消息服务器(比如叫msgserver.1),我们会拿msgserver.1的本地时间作为时序基准,客户端接收到消息后显示就按照msgserver.1的这个时间顺序显示。 我个人理解公司的IM系统从宏观上看多人的消息是并发处理的,但是针对到某个人其实是单线程处理的,这样好处就是系统设计简单一些,不会遇到您文中说的某台机器GC导致某条消息慢,自然也不会有服务端客户端整流的问题,因为单线程中某条消息慢,后面的消息也别想发出去,呵呵。 我想问公司这个处理消息的逻辑会有什么问题吗?还想问一下如果针对个人消息也并发处理,一般这个服务端整流的时间设置成多长合适?如果服务端整流收到9条消息,但是还有1条消息由于GC慢了点,整流服务器怎么知道少收了一条消息?从而在这个整流的时间周期中选择不发送?这种情况下IM系统处理消息的服务器又是怎么处理(它怎么知道整流失败,它又怎么知道要重新发送哪些消息)?
作者回复: 1. 同一个接收人的消息个人感觉没必要用一个线程处理呀,这样还会让服务有状态,如果这个线程挂了后续消息处理的迁移啥的都会比较复杂。对于同一时间有多条消息发送给这个用户的情况,业务上实际也不需要严格区分这几条消息到底哪个先到服务端,只需要保证消息落地存储后时序性固定好就行。 2. 服务器集群规模太大的话依赖服务器时钟也是个问题,所以可以通过”全局的时间相关的序号生成器“来缓解。 3. 服务端整流一般用在离线消息处理的场景,因为这个时候会同时有很多条消息会推送给用户,需要保证时序性。比如一次离线消息的下推共用一个packageId,然后自增的针对每一条消息来绑定一个序号(0 1 2 3 ...),这样下推网关根据packageId来有序收集所有消息,如果序号有缺失就知道有消息丢失了(但至少是有序的),这个时候可以根据业务需要来决定直接下推已收集消息还是放弃这一次离线下推。
2019-09-2013 - javaworker老师,关于服务员消息整流和消息接收端整流 还有些不明白? 1.文中说的服务员消息整流是不是只能在网关整流吗? 2.在网关启动后订阅一个本IP的Topic,文中一直在说对离线消息整流,请问如果是在线消息需要服务端整流吗? 3.文中说每个消息包生成一个 packageID,意思是可以多条消息用一个包发送吗?packageID就是这个包的ID?您能简述下用户A给用户B发送一条消息,和用户A给用户B发送多条消息时,服务端和接收端都是怎么整流的吗?我理解当发送一条消息时,服务端当接收到一条消息后,会有个超时时间,比如2秒,2秒内没收到新消息的话,就把当前的消息发送出去,这时这个消息包中只有一条消息。当发送多条消息时,2秒内有新消息,就一直自增seqID,直到2秒内没收到消息,然后一起把这个消息包发出去,这时消息包可能有比如7条消息,每一条都按照seqID自增。 当发送给接收端,接收端在按照每个消息包中seqID顺序显示消息。 按照我上面的理解,每个消息包之间的顺序怎么保证?是每个消息包packageID也有顺序吗?感觉如果按照我的理解在线发送多条消息会有延时啊,因为服务端一直在整流啊,整完在发送一个大包出去
作者回复: 1. 是的,在最终推送前收集整流。 2. 在线消息由于基本上不会有同时多条消息和信令一起发送的场景,所以这种在服务端就大量乱序的情况比较少,一般不需要进行整流,交给端上就可以了。 3. 基本上理解正确,服务端整流一般用在离线消息推送时,如果上线的这个用户有多条消息,会把这多条消息通过同一个packageID来归类,并且从0自增的给每一条消息打上标记,离线推送的网关机通过这个packageID和seqID来识别这些离线消息的顺序,待消息全部到达后,按照seqID顺序再下推这些消息。但是这里的seqID并不会给到接收端,这里的seqID只是服务端这单次离线消息下推用到的,和接收到没关系。正常的在线消息推送没有这么多并发的情况,没必要整流。
2019-09-1229 - 卫江问题:为什么不需要全局自增id?原因:因为没有全局排序的需求。而且全局自增id肯定有单点和性能问题。我们目前的需求有两点:单聊和群聊。单聊我们可以通过针对于会话id的自增id解决,群聊通过基于群id的自增id解决,这样就拥有了不错的扩展性,避免单点和性能问题,当然了如果群很大也许也有问题,同时这种方式也可以控制某个id生成服务出问题影响的范围。
作者回复: 嗯,也考虑如果有“最近联系人列表”页的需求,需要按照多个群或者多个直播间的最新一条消息的产生先后来排序,这种情况可能还需要考虑使用其他属性来进行全局排序了(比如消息产生的时间戳)。
2019-09-0628 - Alpha生产者为每个消息包生成一个 packageID。 ——请问这里的消息包是什么概念,是指多个消息的集合吗?如果是的话,什么场景下会将多个消息作为一个包一起发送呢? 或者指的是包含 一条消息 + 一条指令 的集合吗?
作者回复: 比如离线消息推送时,用户的多条消息需要推送,这多条消息在服务端进行多线程处理时可能出现乱序的情况,通过在取离线消息时,给每条消息使用同一个packageId并自增一个seq,那么网关机在最终推送时,就可以根据这个packageId来进行一次整流,保证最终下推时消息的有序。
2019-09-0725 - 一个爱编程的胖子可不可以适当添加一些代码示例。单纯的文字描述比较干
作者回复: 加了两张流程图来说明一下服务端整流这一块的应用场景和过程,更新后再看下能不能理解。
2019-09-083 - 北北、Pepper对老师提的问题,提出一下自己的想法。 因为实时通信里是会存在多个会话的,如果用于保证消息接收时序的序号生成器是全局递增的,即用于保证所有会话的接收时序,那么会存在可用性和性能瓶颈问题。 其次,正如老师提到的,从业务层面考虑,对用户来说,只要保证单个会话里消息的时序是正确的即可,因为不同的会话相关性一般不强,不需要保证严格的时序同步,所以针对不同的会话,单独维护一个时钟序号生成器即可。
作者回复: 是这样的,会话内的排序只需要保证会话内序号递增就可以。当然,如果有“最近联系人列表”这种需求,还需要考虑跨多个会话进行排序的情况,这个可能需要其他属性来协助全局排序了。
2019-09-063 - 忘袁老师,在课程的最后是不是有实战的项目?我对这个IM几乎是一点不会,能听懂大概的意思,具体的代码我一点没有接触过,听着和看着您和同学们讨论,我很希望我以后也可以能有提问能力,我现在是想提问不知道问什😂 😂 😂 ,希望可以在您这里能入门!😁 😁 😁
作者回复: 没问题的,11篇开始会有一个简单的聊天系统的示例,可以边看边试试。
2019-09-252