热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

socket未读消息如何设计_揭秘!现代IM系统的消息架构如何设计?

阿里妹导读:IM全称是『InstantMessaging』,中文名是即时通讯。在高度信息化的移动互联网时代,生活中IM类产品已经成为必备品

44b9249b7b0224b06913e2424dac2b53.png

阿里妹导读:IM全称是『Instant Messaging』,中文名是即时通讯。在高度信息化的移动互联网时代,生活中IM类产品已经成为必备品,像“钉钉”以IM为核心功能的产品。还有一些非以IM系统为核心的应用,最典型的如一些在线游戏、社交应用,IM也是其重要的功能模块。可以说,IM系统已经是任何一个带有社交属性的应用需要具备的基础功能,网络上对于这类系统的设计与实现的讨论也越来越多。今天,阿里巴巴高级技术专家木洛,就为你揭秘现代 IM 系统中的消息系统架构。

前言

IM系统在互联网初期即存在,其基础技术架构在这十几年的发展中更新迭代多次,从早期的CS、P2P架构,到现在后台已经演变为一个复杂的分布式系统,涉及移动端、网络通信、协议、安全、存储和搜索等技术的方方面面。IM系统中最核心的部分是消息系统,消息系统中最核心的功能是消息的同步、存储和检索:

  • 消息的同步:将消息完整、快速地从发送方传递到接收方,就是消息的同步。消息同步系统最重要的衡量指标就是消息传递的实时性、完整性以及能支撑的消息规模。从功能上来说,一般至少要支持在线和离线推送,高级的IM系统还支持『多端同步』。

  • 消息的存储:消息存储即消息的持久化保存,传统消息系统通常只能支持消息在接收端的本地存储,数据基本不具备可靠性。现代消息系统能支持消息在服务端的在线存储,功能上对应的就是『消息漫游』,消息漫游的好处是可以实现账号在任意端登陆查看所有历史消息。

  • 消息的检索:消息一般是文本,所以支持全文检索也是必备的能力之一。传统消息系统通常来说也是只能支持消息的本地检索,基于本地存储的消息数据来构建。而现在消息系统在能支持消息的在线存储后,也具备了消息的『在线检索』能力。

本篇文章内容主要涉及IM系统中的消息系统架构,会介绍一种基于阿里云表格存储 Tablestore 的 Timeline 模型构建的消息系统。基于 Tablestore Timeline 构建的现代消息系统,能够同时支持消息系统的众多高级特性,包括『多端同步』、『消息漫游』和『在线检索』。在性能和规模上,能够做到全量消息云端存储和索引,百万 TPS 写入以及毫秒级延迟的消息同步和检索能力。

之后我们会继续发表两篇文章,来更详细介绍 Tablestore Timeline 模型概念及使用:

  • 模型篇:详细介绍 Tablestore Timeline 模型的基本概念和基础数据结构,并结合 IM 系统进行基本的建模。

  • 实现篇:会基于 Tablestore Timeline 实现一个具备『多端同步』、『消息漫游』和『在线检索』这些高级功能的简易IM系统,并共享我们的源代码。

传统架构 vs 现代架构

535b623444c80d9440a2fb0eaab0e90d.png

传统架构下,消息是先同步后存储。对于在线的用户,消息会直接实时同步到在线的接收方,消息同步成功后,并不会在服务端持久化。而对于离线的用户或者消息无法实时同步成功时,消息会持久化到离线库,当接收方重新连接后,会从离线库拉取所有未读消息。当离线库中的消息成功同步到接收方后,消息会从离线库中删除。传统的消息系统,服务端的主要工作是维护发送方和接收方的连接状态,并提供在线消息同步和离线消息缓存的能力,保证消息一定能够从发送方传递到接收方。服务端不会对消息进行持久化,所以也无法支持消息漫游。消息的持久化存储及索引同样只能在接收端本地实现,数据可靠性极低。

现代架构下,消息是先存储后同步。先存储后同步的好处是,如果接收方确认接收到了消息,那这条消息一定是已经在云端保存了。并且消息会有两个库来保存,一个是消息存储库,用于全量保存所有会话的消息,主要用于支持消息漫游。另一个是消息同步库,主要用于接收方的多端同步。消息从发送方发出后,经过服务端转发,服务端会先将消息保存到消息存储库,后保存到消息同步库。

完成消息的持久化保存后,对于在线的接收方,会直接选择在线推送。但在线推送并不是一个必须路径,只是一个更优的消息传递路径。对于在线推送失败或者离线的接收方,会有另外一个统一的消息同步方式。接收方会主动的向服务端拉取所有未同步消息,但接收方何时来同步以及会在哪些端来同步消息对服务端来说是未知的,所以要求服务端必须保存所有需要同步到接收方的消息,这是消息同步库的主要作用。

对于新的同步设备,会有消息漫游的需求,这是消息存储库的主要作用,在消息存储库中,可以拉取任意会话的全量历史消息。消息检索的实现依赖于对消息存储库内消息的索引,通常是一个近实时(NRT,near real time)的索引构建过程,这个索引同样是在线的。

以上就是传统架构和现代架构的一个简单的对比,现代架构上整个消息的同步、存储和索引流程,并没有变复杂太多。现代架构的实现本质上是把传统架构内本地存储和索引都搬到云上,最大挑战是需要集中管理全量消息的存储和索引,带来的好处是能实现多端同步、消息漫游以及在线检索。可以看到现代架构中最核心的就是两个消息库『消息同步库』和『消息存储库』,以及对『消息存储库』的『消息索引』的实现,接下来我们逐步拆解这几个核心的设计和实现。

基础模型

在深入讲解消息系统的设计和实现之前,需要对消息系统内的几个基本概念和基础模型有一个理解。网上分析的很多的不同类型的消息系统实现,实现差异上主要在消息同步和存储的方案上,在消息的数据模型上其实有很大的共性。围绕数据同步模型的讨论主要在『读扩散』、『写扩散』和『混合模式』这三种方案,目前还没有更多的选择。而对于数据模型的抽象,还没有一个标准的定义。

本章节会介绍下表格存储 Tablestore 提出的 Timeline 模型,这是一个对消息系统内消息模型的一个抽象,能简化和更好地让开发者理解消息系统内的消息同步和存储模型,基于此模型我们会再深入探讨消息的同步和存储的选择和实现。

Timeline模型

Timeline是一个对消息抽象的逻辑模型,该模型会帮助我们简化对消息同步和存储模型的理解,而消息同步库和存储库的设计和实现也是围绕Timeline的特性和需求来展开。

421340c3f65ad7ba116f74df5167f50f.png

如图是 Timeline 模型的一个抽象表述,Timeline 可以简单理解为是一个消息队列,但这个消息队列有如下特性:

  • 每条消息对应一个顺序ID:每个消息拥有一个唯一的顺序ID(SequenceId),队列消息按 SequenceId 排序。

  • 新消息写入能自动分配递增的顺序 ID,保证永远插入队尾:Timeline 中是根据同步位点也就是顺序 ID 来同步消息,所以需要保证新写入的消息数据的顺序 ID 绝对不能比已同步的消息的顺序 ID 还小,否则会导致数据漏同步,所以需要支持对新写入的数据自动分配比当前已存储的所有消息的顺序 ID 更大的顺序 ID 。

  • 新消息写入也能自定义顺序 ID,满足自定义排序需求:上面提到的自动分配顺序 ID,主要是为了满足消息同步的需求,消息同步要求消息是根据『已同步』或是『已写入』的顺序来排序。而消息的存储,通常要求消息能根据会话顺序来排序,会话顺序通常由端的会话来决定,而不是服务端的同步顺序来定,这是两种顺序要求。

  • 支持根据顺序 ID 的随机定位:可根据 SequenceId 随机定位到 Timeline 中的某个位置,从这个位置开始正序或逆序的读取消息,也可支持读取指定顺序ID的某条消息。

支持对消息的自定义索引:消息体内数据根据业务不同会包含不同的字段, Timeline 需要支持对不同字段的自定义索引,来支持对消息内容的全文索引,或者是任意字段的灵活条件组合查询。

消息同步可以基于 Timeline 很简单的实现,图中的例子中,消息发送方是A,消息接收方是B,同时B存在多个接收端,分别是B1、B2和B3。A向B发送消息,消息需要同步到B的多个端,待同步的消息通过一个 Timeline 来进行交换。A向B发送的所有消息,都会保存在这个 Timeline 中,B的每个接收端都是独立的从这个 Timeline中拉取消息。每个接收端同步完毕后,都会在本地记录下最新同步到的消息的SequenceId,即最新的一个位点,作为下次消息同步的起始位点。服务端不会保存各个端的同步状态,各个端均可以在任意时间从任意点开始拉取消息。

消息存储也是基于 Timeline 实现,和消息同步唯一的区别是,消息存储要求服务端能够对 Timeline 内的所有数据进行持久化,并且消息采用会话顺序来保存,需要自定义顺序 ID。

消息检索基于 Timeline 提供的消息索引来实现,能支持比较灵活的多字段索引,根据业务的不同可有自由度较高的定制。

消息存储模型

822f27920e12fe5db9348526275a0f5a.png

如图是基于 Timeline 的消息存储模型,消息存储要求每个会话都对应一个独立的 Timeline 。如图例子所示,A与B/C/D/E/F均发生了会话,每个会话对应一个独立的 Timeline,每个 Timeline 内存有这个会话中的所有消息,消息根据会话顺序排序,服务端会对每个 Timeline 进行持久化存储,也就拥有了消息漫游的能力。

消息同步模型

消息同步模型会比消息存储模型稍复杂一些,消息的同步一般有读扩散(也叫拉模式)和写扩散(也叫推模式)两种不同的方式,分别对应不同的 Timeline 物理模型。

571ea2ce9b9e7055f625fb06352a2830.png

如图是读扩散和写扩散两种不同同步模式下对应的不同的 Timeline 模型,按图中的示例,A作为消息接收者,其与B/C/D/E/F发生了会话,每个会话中的新的消息都需要同步到A的某个端,看下读扩散和写扩散两种模式下消息如何做同步。

读扩散:消息存储模型中,每个会话的 Timeline 中保存了这个会话的全量消息。读扩散的消息同步模式下,每个会话中产生的新的消息,只需要写一次到其用于存储的 Timeline 中,接收端从这个 Timeline 中拉取新的消息。优点是消息只需要写一次,相比写扩散的模式,能够大大降低消息写入次数,特别是在群消息这种场景下。但其缺点也比较明显,接收端去同步消息的逻辑会相对复杂和低效。接收端需要对每个会话都拉取一次才能获取全部消息,读被大大的放大,并且会产生很多无效的读,因为并不是每个会话都会有新消息产生。

写扩散:写扩散的消息同步模式,需要有一个额外的 Timeline 来专门用于消息同步,通常是每个接收端都会拥有一个独立的同步 Timeline(或者叫收件箱),用于存放需要向这个接收端同步的所有消息。每个会话中的消息,会产生多次写,除了写入用于消息存储的会话 Timeline,还需要写入需要同步到的接收端的同步 Timeline。在个人与个人的会话中,消息会被额外写两次,除了写入这个会话的存储 Timeline,还需要写入参与这个会话的两个接收者的同步 Timeline。而在群这个场景下,写入会被更加的放大,如果这个群拥有N个参与者,那每条消息都需要额外地写N次。写扩散同步模式的优点是,在接收端消息同步逻辑会非常简单,只需要从其同步 Timeline 中读取一次即可,大大降低了消息同步所需的读的压力。其缺点就是消息写入会被放大,特别是针对群这种场景。

Timeline 模型不会对选择读扩散还是写扩散做约束,而是能同时支持两种模式,因为本质上两种模式的逻辑数据模型并无差别,只是消息数据是用一个 Timeline 来支持多端读还是复制到多个 Timeline 来支持多端读的问题。

针对 IM 这种应用场景,消息系统通常会选择写扩散这种消息同步模式。IM 场景下,一条消息只会产生一次,但是会被读取多次,是典型的读多写少的场景,消息的读写比例大概是10:1。若使用读扩散同步模式,整个系统的读写比例会被放大到100:1。一个优化的好的系统,必须从设计上去平衡这种读写压力,避免读或写任意一维触碰到天花板。所以 IM 系统这类场景下,通常会应用写扩散这种同步模式,来平衡读和写,将100:1的读写比例平衡到30:30。当然写扩散这种同步模式,还需要处理一些极端场景,例如万人大群。

针对这种极端写扩散的场景,会退化到使用读扩散。一个简单的IM系统,通常会在产品层面限制这种大群的存在,而对于一个高级的IM系统,会采用读写扩散混合的同步模式,来满足这类产品的需求。采用混合模式,会根据数据的不同类型和不同的读写负载,来决定用写扩散还是读扩散。

典型架构设计

c5d2d6954ef2f836bbee0425497451f4.png

如图是一个典型的消息系统架构,架构中包含几个重要组件:

  • 端:作为消息的发送和接收端,通过连接消息服务器来发送和接收消息。

  • 消息服务器:一组无状态的服务器,可水平扩展,处理消息的发送和接收请求,连接后端消息系统。

  • 消息队列:新写入消息的缓冲队列,消息系统的前置消息存储,用于削峰填谷以及异步消费。

  • 消息处理:一组无状态的消费处理服务器,用于异步消费消息队列中的消息数据,处理消息的持久化和写扩散同步。

  • 消息存储和索引库:持久化存储消息,每个会话对应一个 Timeline 进行消息存储,存储的消息建立索引来实现消息检索。

  • 消息同步库:写扩散形式同步消息,每个用户的收件箱对应一个 Timeline,同步库内消息不需要永久保存,通常对消息设定一个生命周期。

新消息会由端发出,通常消息体中会携带消息ID(用于去重)、逻辑时间戳(用于排序)、消息类型(控制消息、图片消息或者文本消息等)、消息体等内容。消息会先写入消息队列,作为底层存储的一个临时缓冲区。消息队列中的消息会由消息处理服务器消费,可以允许乱序消费。消息处理服务器对消息先存储后同步,先写入发件箱 Timeline (存储库),后写扩散至各个接收端的收件箱(同步库)。消息数据写入存储库后,会被近实时的构建索引,索引包括文本消息的全文索引以及多字段索引(发送方、消息类型等)。

对于在线的设备,可以由消息服务器主动推送至在线设备端。对于离线设备,登录后会主动向服务端同步消息。每个设备会在本地保留有最新一条消息的顺序ID,向服务端同步该顺序ID后的所有消息。

总结

本篇文章主要介绍了现代 IM 系统中消息系统所需要具备的能力,对比了传统架构和现代架构。为方便接下来的深入探讨,介绍了表格存储 Tablestore 推出的 Timeline 模型,以及在 IM 系统中消息存储和消息同步模型的基本概念和策略,最后介绍了一个典型的架构设计。希望和同仁共同探讨、交流。

dba6554d069b500963f6c070c8002241.png

你可能还喜欢

点击下方图片即可阅读

d98946e68951e58f7d1caf610f69a4ce.png

贾扬清:我对人工智能方向的一点浅见

64ec8ab2f4ca1681b4c3bc46513c4af6.png

如何搞定技术面试?阿里大牛为你选了8本必备好书

29201726d53cc5127bccf1bc95043be8.png

在阿里做了五年技术主管,我有话想说

275dacd4003570d98532107af7735678.gif




推荐阅读
  • 掌握PHP框架开发与应用的核心知识点:构建高效PHP框架所需的技术与能力综述
    掌握PHP框架开发与应用的核心知识点对于构建高效PHP框架至关重要。本文综述了开发PHP框架所需的关键技术和能力,包括但不限于对PHP语言的深入理解、设计模式的应用、数据库操作、安全性措施以及性能优化等方面。对于初学者而言,熟悉主流框架如Laravel、Symfony等的实际应用场景,有助于更好地理解和掌握自定义框架开发的精髓。 ... [详细]
  • 智能制造数据综合分析与应用解决方案
    在智能制造领域,生产数据通过先进的采集设备收集,并利用时序数据库或关系型数据库进行高效存储。这些数据经过处理后,通过可视化数据大屏呈现,为生产车间、生产控制中心以及管理层提供实时、精准的信息支持,助力不同应用场景下的决策优化和效率提升。 ... [详细]
  • 比特币的成功为区块链技术构建了可信货币的基石,标志着区块链1.0时代的到来。以太坊通过引入智能合约,极大地推动了去中心化应用的开发和普及,开启了区块链2.0时代。本文深入探讨了侧链技术在提升区块链扩展性方面的潜力和应用,分析了其在提高交易速度、降低成本和增强安全性等方面的优势,并讨论了当前面临的技术挑战和未来的发展方向。 ... [详细]
  • 在iOS平台上,应用的流畅操作体验一直备受赞誉。然而,过去开发者往往将更多精力集中在功能实现上,而对性能优化的关注相对较少。本文深入探讨了iOS应用性能优化的关键要点与实践方法,旨在帮助开发者提升应用的响应速度、降低功耗,并改善整体用户体验。通过具体案例分析和技术解析,文章提供了实用的优化策略,包括代码层面的改进、资源管理优化以及界面渲染效率的提升等。 ... [详细]
  • 在《PHP应用性能优化实战指南:从理论到实践的全面解析》一文中,作者分享了一次实际的PHP应用优化经验。文章回顾了先前进行的一次优化项目,指出即使系统运行时间较长后出现的各种问题和性能瓶颈,通过采用一些通用的优化策略仍然能够有效解决。文中不仅详细阐述了优化的具体步骤和方法,还结合实例分析了优化前后的性能对比,为读者提供了宝贵的参考和借鉴。 ... [详细]
  • 作为140字符的开创者,Twitter看似简单却异常复杂。其简洁之处在于仅用140个字符就能实现信息的高效传播,甚至在多次全球性事件中超越传统媒体的速度。然而,为了支持2亿用户的高效使用,其背后的技术架构和系统设计则极为复杂,涉及高并发处理、数据存储和实时传输等多个技术挑战。 ... [详细]
  • 本题库精选了Java核心知识点的练习题,旨在帮助学习者巩固和检验对Java理论基础的掌握。其中,选择题部分涵盖了访问控制权限等关键概念,例如,Java语言中仅允许子类或同一包内的类访问的访问权限为protected。此外,题库还包括其他重要知识点,如异常处理、多线程、集合框架等,全面覆盖Java编程的核心内容。 ... [详细]
  • 本文介绍了使用 Python 编程语言高效抓取微博文本和动态网页图像数据的方法。通过详细的示例代码,展示了如何利用爬虫技术获取微博内容和动态图片,为数据采集和分析提供了实用的技术支持。对于对网络数据抓取感兴趣的读者,本文具有较高的参考价值。 ... [详细]
  • ylbtech-进销存管理解决方案:进销存管理,即购销链管理,涵盖企业从采购(进)、库存(存)到销售(销)的全流程动态管控。其中,“进”涉及从市场询价、供应商选择、采购执行直至货物入库及支付流程;“销”则包括产品定价、客户报价、订单处理及销售出库等环节。该解决方案旨在通过信息化手段,提升企业运营效率,优化库存结构,增强市场响应速度。 ... [详细]
  • 负载均衡基础概念与技术解析
    随着互联网应用的不断扩展,用户流量激增,业务复杂度显著提升,单一服务器已难以应对日益增长的负载需求。负载均衡技术应运而生,通过将请求合理分配到多个服务器,有效提高系统的可用性和响应速度。本文将深入探讨负载均衡的基本概念和技术原理,分析其在现代互联网架构中的重要性及应用场景。 ... [详细]
  • Java中高级工程师面试必备:JVM核心知识点全面解析
    对于软件开发人员而言,随着技术框架的不断演进和成熟,许多高级功能已经被高度封装,使得初级开发者只需掌握基本用法即可迅速完成项目。然而,对于中高级工程师而言,深入了解Java虚拟机(JVM)的核心知识点是必不可少的。这不仅有助于优化性能和解决复杂问题,还能在面试中脱颖而出。本文将全面解析JVM的关键概念和技术细节,帮助读者全面提升技术水平。 ... [详细]
  • 在处理分享功能时,以往通常会首先考虑使用第三方SDK,如友盟等。然而,通过实际项目经验发现,利用iOS原生的UIActivityViewController不仅可以实现高效、稳定的分享功能,还能更好地控制用户体验。本文将详细介绍如何利用iOS原生技术缓存HTML内容,并结合URL分享的最佳实践,帮助开发者在实际开发中提升应用性能和用户满意度。 ... [详细]
  • 本文深入探讨了Spring Cloud Eureka在企业级应用中的高级使用场景及优化策略。首先,介绍了Eureka的安全配置,确保服务注册与发现过程的安全性。接着,分析了Eureka的健康检查机制,提高系统的稳定性和可靠性。随后,详细讨论了Eureka的各项参数调优技巧,以提升性能和响应速度。最后,阐述了如何实现Eureka的高可用性部署,保障服务的连续性和可用性。通过这些内容,开发者可以更好地理解和运用Eureka,提升微服务架构的整体效能。 ... [详细]
  • 视觉图像的生成机制与英文术语解析
    近期,Google Brain、牛津大学和清华大学等多家研究机构相继发布了关于多层感知机(MLP)在视觉图像分类中的应用成果。这些研究深入探讨了MLP在视觉任务中的工作机制,并解析了相关技术术语,为理解视觉图像生成提供了新的视角和方法。 ... [详细]
  • 西北工业大学作为陕西省三所985和211高校之一,虽然在农业和林业领域不如某些顶尖院校,但在航空航天领域的实力尤为突出。该校的计算机科学专业在科研和教学方面也具有显著优势,是考研的理想选择。 ... [详细]
author-avatar
SHARK
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有