转转平台IM系统架构设计与实践(二):详细设计与实现

简介: 以转转IM架构为起点,介绍IM相关组件以及组件间的关系;以IM登陆和发消息的数据流转为跑道,介绍IM静态数据结构、登陆和发消息时的动态数据变化;以IM常见问题为风景,介绍保证IM实时性、可靠性、一致性的一般方案;以高可用、高并发为终点,介绍保证IM系统稳定及性能的小技巧。

本文由转转 梁会彬、杜云杰分享,原题“转转IM的实践与思考”,下文进行了排版和内容优化。

1、引言

接上篇《整体架构设计》,笔者将以转转IM架构为起点,介绍IM相关组件以及组件间的关系;以IM登陆和发消息的数据流转为跑道,介绍IM静态数据结构、登陆和发消息时的动态数据变化;以IM常见问题为风景,介绍保证IM实时性、可靠性、一致性的一般方案;以高可用、高并发为终点,介绍保证IM系统稳定及性能的小技巧

技术交流:

- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM

- 开源IM框架源码:https://github.com/JackJiang2011/MobileIMSDK备用地址点此

本文已同步发布于:http://www.52im.net/thread-4773-1-1.html

2、系列文章

本文是系列文章中的第2篇,本系列文章的大纲如下:

3、本文作者

梁会彬:转转架构部资深Java工程师,主要负责服务治理平台、Docker云平台、IM、分布式ID生成器、短域名服务等,有丰富的线上实战经验。

4、 IM架构回顾

应用层:使用IM服务的上游业务方,包括app(ios和android)、小程序/PC/m页、push、业务方等。

接入层:

  • 1)tcp entry:使用TCP协议,主要用于长连接保持、会话管理、协议解析;
  • 2)http entry:使用http协议,采用long pull技术,主要用于长连接保持、会话管理、协议解析;
  • 3)mq:接收电商推广等系统消息。推送量具有脉冲特点,使用mq削峰填谷;
  • 4)rpc-server:业务查询用户聊天数据、发送实时系统消息等。

逻辑层:

  • 1)logic:核心逻辑服务,负责登陆信息管理、在线消息管理、离线消息管理、在线推送管理等;
  • 2)ext-logic:扩展逻辑服务,负责子母账号推送、登陆信息统计、系统消息管理等。

数据层:

  • 1)MySQL:联系人数据、消息数据、系统消息数据等;
  • 2)Redis:登陆信息等。

5、IM消息收发

5.1场景说明

数据流中以用户A和用户B的对话为例,其中用户A的uid为1,用户B的uid为2。

下图为用户聊天场景图:

下图为用户聊天IM系统的数据流转图:

5.2数据结构

登陆信息存储在Redis中,联系人和消息数据放在TiDB中。

1)登陆信息:

key:uid

value:{entryIp:"127.0.0.1",entryPort:5000,loginTime:23443233}

2)联系人:

说明:

  • 1)recent_msg_content:最近一条对话消息的内容,用于联系人列表中展示最近的消息内容;
  • 2)recent_read_time:最近一次读取该会话消息的时间,用于控制已读状态,小于该时间的所有消息,都为已读状态。

3)消息:

说明:

  • 1)client_msg_id:客户端生成的id,客户端幂等设计,防重复;
  • 2)direction:消息方向(0代表较大uid向较小uid发送消息,1则反之)。

数据流=数据+流。上面部分讲数据,即联系人和消息表,从静态的角度介绍了IM的数据结构;下面部分讲流(IM中最重要的两个流程),即登陆和发消息,从动态的角度来阐述IM系统中数据的流转。

5.3主要流程

5.3.1 )登陆:

1)问题:entry地址发现:app直接访问vip,由vip转发到entry。

2)流程(下面的数字为图中数字的说明):

  • 1)建连:app通过vip发起与entry连接;
  • 2)转发:entry转发登陆信息到logic,获取用户uid并管理该用户的连接;
  • 3)入库:logic记录用户登陆信息到redis。

3)数据:

Redis中数据如下:

key:1

value:{entryIp:"127.0.0.1",entryPort:5000,loginTime:23443233}

5.3.2 )发消息(下面的数字为图二中数字的说明):

1)流程处理:

  • 1)发送:通过用户与entry的长连接发送文字"hello world";
  • 2)转发:entry转发文字信息"hello world"到logic;
  • 3)入库:logic存入数据库,即更新联系人表和消息表,其中联系人表更新recent_msg_content字段,消息表增加一条新消息记录;
  • 4)推送:从Redis中获取用户B登陆entry,如果未登录,走离线逻辑(发送push、推送微信、短信唤起);
  • 5)送达:用户B收到消息;
  • 6)确认:发送ack到entry;
  • 7)完成:logic收到ack,取消定时器;如果没有收到ack,logic会定时重发(用户在线时)。

2)数据:

联系人数据如下:

消息表数据如下:

5.3.3)关于数据的几个问题:

1)消息和联系人是如何分库分表的?使用TiDB,无需分库分表(现在的表设计支持根据uid_a分表,也就是无缝支持以MySQL为存储)。

2)联系人表一条消息为什么记录了两条数据?业务逻辑上,考量支持已读、删除联系人;索引性能上,考虑用户查询联系人时,sql条件为where uid_a=?,联系人表索引为uid_a,如果存单条数据,无法有效利用索引。

3)消息表一条消息记录一条数据,用户B与用户A的消息怎么查询?该表索引为<big_uid, small_uid>联合索引,无论是用户A查询与用户B的聊天信息,还是用户B查询用户A的聊天信息,其sql统统为where big_uid =max(uid_a,uid_b) and small_uid =min(uid_a,uid_b),然后根据direction字段展示聊天方向,这样就可以用一条消息,无需和联系人表一样存储两份数据,满足两种查询,节省一半的消息存储。

6、IM常见问题

6.1消息的实时性

1)是什么:

用户A给用户B发送消息"hello world",用户B怎么第一时间感知到?这里说的实时性,就是指用户如何实时获取发送的消息。

2)io模型带来的启示:

  • 1)poll、select、epoll;
  • 2)poll/select相比epoll最大的劣势在于轮询,轮询就需要轮询间隔,间隔小会浪费cpu,间隔大会不实时。epoll具有don't call me i will call you的特点,保证实时性;
  • 3)IM也面临着轮询还是通知的问题,也就是pull和push的问题。

3)怎么办:

  • 1)向epoll致敬:epoll_create、epoll_ctl、epoll_wait(此三者是epoll系统调用api);
  • 2)整个IM系统和epoll模型类似,app和entry保持长连接(epoll_create);entry session管理(即长连接管理epoll_ctl);logic等待用户A发送给用户B消息,获取用户B所登陆entry,触发推送消息(epoll_wait);综述,entry扮演着(epoll_create,epoll_ctl),logic扮演着(epoll_wait)这样IM系统就解决了消息实时性问题。

6.2消息的可靠性

1)是什么:

  • 1)用户A给用户B发送消息"hello world",用户B在线,怎么保证用户B确实收到了消息。这里说的可靠性,就是指用户如何可靠发送的消息。

2)tcp模型带来的启示:

  • 1)失败重传、ack确认。

3)怎么办:

  • 1)失败重传:图二中(1、发送2、转发3、入库)失败,告知客户端失败,由客户端重传;
  • 2)ack确认:图二中(4、推送5、送达6、确认7、完成)失败,即ack处理失败,启动重新通知逻辑。

6.3消息的一致性

1)是什么:

  • 1)现象:本来用户A给用户B发送了一个"hello world",而用户B确收到了两个"hello world";
  • 2)原因:由于可靠性逻辑中的重传逻辑,可能造成客户端认为失败了,但是服务端却成功了;推送ack返回错误,造成重推。

2)身份证带来的启示。

3)怎么办:

  • 1)client_msg_id:客户端发送消息时生成客户端id,对于单个客户端,该id具有唯一性,像身份证一样;
  • 2)客户端去重:如果客户端发现相同client_msg_id的消息,则仅仅展示一条数据。

7、IM高可用、高并发

1)扩缩容:

依托公司rpc服务注册发现能力,借助docker快速扩容,核心处理逻辑logic服务实现秒级扩容。扩容依据为各种监控指标,包括机器性能指标、 entry/logic qps指标、jvm指标、sql监控等综合考量。

2)熔断:

当大流量进入时,如果核心服务依赖的服务(比如母子账号服务)出现不可用的情况。这时,我们是直接使IM服务不可用吗?是不是有更好的选择?答案是肯定的,我们可以牺牲母子账号功能,也就是熔断不重要的依赖服务,做到柔性可用。

3)限流:

如果遇到瞬时高流量,仅仅扩容有可能适得其反。如果db处理能力达到极限,扩容就不是明智的选择,扩容反而会导致db连接增多,增加db的压力,导致服务崩溃。这时退一步采用限流,应用“fast fail”策略,让部分流量快速失败,减小服务压力,达到部分可用的效果。

4)总结:

IM作为电商应用中的一个重要节点,其重要性不言而喻,对其怎么重视都不为过。我们使用监控工具定义IM的核心metrics,根据指标进行扩缩容,这样做到了高可用;

高可用是万能的吗?IM依赖了很多服务,比如用户,母子账号,风控等服务,如果这些服务出现不可用的情况呢?这个时候就要学习一下古人的智慧,壮士断腕,牺牲小我,换取大我了,也就是柔性可用;

仅仅这样还是不够的,如果遇到突发流量,db(不可瞬时扩大处理能力)等处理能力达到极限时这个时候就要牺牲部分请求了,也就要做到部分可用。从“高可用”到“柔性可用”再到“部分可用”,面对不同case,IM要做到游刃有余。

其实,这种思想又何止IM呢,任何重要的服务都要面对这些问题吧,推而广之,面对自己负责的服务,怎么精细小心都不为过。

8、本文小结

诚然,这篇文章给大家对IM系统简单的认识,阐述了IM的一般架构、主要业务逻辑、常见问题和解决方案以及服务治理相关应用,IM还有很多业务逻辑和技术挑战。

在业务上,如未读数、群聊、多端登陆、母子账号等;在技术上,entry长连接100k问题优化、时间轮计时器实现、海量数据拆分与存储选型等。

路漫漫其修远兮,吾将上下而求索。

9、参考资料

[1] 零基础IM开发入门(二):什么是IM系统的实时性?

[2] 零基础IM开发入门(三):什么是IM系统的可靠性?

[3] 零基础IM开发入门(四):什么是IM系统的消息时序一致性?

[4] IM消息送达保证机制实现(一):保证在线实时消息的可靠投递

[5] IM消息送达保证机制实现(二):保证离线消息的可靠投递

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

[7] 阿里IM技术分享(四):闲鱼亿级IM消息系统的可靠投递优化实践

[8] 阿里IM技术分享(五):闲鱼亿级IM消息系统的及时性优化实践

[9] 一套亿级用户的IM架构技术干货(下篇):可靠性、有序性、弱网优化等

[10] 融云技术分享:全面揭秘亿级IM消息的可靠投递机制

[11] 一套海量在线用户的移动端IM架构设计实践分享(含详细图文)

[12] 一套原创分布式即时通讯(IM)系统理论架构方案

[13] 从零到卓越:京东客服即时通讯系统的技术架构演进历程

[14] 蘑菇街即时通讯/IM服务器开发之架构选择

[15] 现代IM系统中聊天消息的同步和存储方案探讨

[16] 一套高可用、易伸缩、高并发的IM群聊、单聊架构方案设计实践

[17] 马蜂窝旅游网的IM系统架构演进之路

[18] 一套分布式IM即时通讯系统的技术选型和架构设计

[19] 微信团队分享:来看看微信十年前的IM消息收发架构,你做到了吗

[20] 携程技术分享:亿级流量的办公IM及开放平台技术实践

(本文已同步发布于:http://www.52im.net/thread-4773-1-1.html)

目录
相关文章
|
5天前
|
人工智能 运维 Cloud Native
2025年国内工单系统推荐:技术架构、场景适配与行业实践
分析了智能化升级、大数据驱动、云原生架构及全渠道融合四大技术趋势,从功能适配性、易用性、集成能力、安全性和性价比五个维度指导企业选型,并推荐合力亿捷等三家系统的优劣对比,结合电商和制造行业的实际案例,帮助企业提升客户服务水平与竞争力。
40 11
2025年国内工单系统推荐:技术架构、场景适配与行业实践
|
3天前
|
运维 安全 弹性计算
基于阿里云的开源应用智能管理架构设计与工程实践
本文以Websoft9技术方案为例,探讨企业级应用管理的范式。通过解析开源应用管理面临的部署复杂性、运维低效性和知识碎片化三大挑战,提出基于阿里云的三层架构:智能应用管理门户、核心功能层和基础设施层。文章详细阐述了应用编排标准化(IaC实践)、智能运维体系构建及知识资产数字化的技术实现路径,并结合金融与制造行业的案例,展示解决方案的实际效果。最后提供开发者资源与工具链支持,助力企业高效管理应用。
67 1
|
4天前
|
存储 消息中间件 缓存
支持百万人超大群聊的Web端IM架构设计与实践
本文将回顾实现一个支持百万人超大群聊的Web端IM架构时遇到的技术挑战和解决思路,内容包括:通信方案选型、消息存储、消息有序性、消息可靠性、未读数统计。希望能带给你启发。
19 0
支持百万人超大群聊的Web端IM架构设计与实践
|
6天前
|
人工智能 运维 监控
领先AI企业经验谈:探究AI分布式推理网络架构实践
当前,AI行业正处于快速发展的关键时期。继DeepSeek大放异彩之后,又一款备受瞩目的AI智能体产品Manus横空出世。Manus具备独立思考、规划和执行复杂任务的能力,其多智能体架构能够自主调用工具。在GAIA基准测试中,Manus的性能超越了OpenAI同层次的大模型,展现出卓越的技术实力。
|
12天前
|
机器学习/深度学习 人工智能 自然语言处理
DeepSeek 实践应用解析:合力亿捷智能客服迈向 “真智能” 时代
DeepSeek作为人工智能领域的创新翘楚,凭借领先的技术实力,在智能客服领域掀起变革。通过全渠道智能辅助、精准对话管理、多语言交互、智能工单处理、个性化推荐、情绪分析及反馈监控等功能,大幅提升客户服务效率和质量,助力企业实现卓越升级,推动智能化服务发展。
71 1
|
15天前
|
消息中间件 人工智能 自然语言处理
基于 RocketMQ 事件驱动架构的 AI 应用实践
基于 RocketMQ 事件驱动架构的 AI 应用实践
|
3月前
|
弹性计算 API 持续交付
后端服务架构的微服务化转型
本文旨在探讨后端服务从单体架构向微服务架构转型的过程,分析微服务架构的优势和面临的挑战。文章首先介绍单体架构的局限性,然后详细阐述微服务架构的核心概念及其在现代软件开发中的应用。通过对比两种架构,指出微服务化转型的必要性和实施策略。最后,讨论了微服务架构实施过程中可能遇到的问题及解决方案。
|
4月前
|
Cloud Native Devops 云计算
云计算的未来:云原生架构与微服务的革命####
【10月更文挑战第21天】 随着企业数字化转型的加速,云原生技术正迅速成为IT行业的新宠。本文深入探讨了云原生架构的核心理念、关键技术如容器化和微服务的优势,以及如何通过这些技术实现高效、灵活且可扩展的现代应用开发。我们将揭示云原生如何重塑软件开发流程,提升业务敏捷性,并探索其对企业IT架构的深远影响。 ####
95 3
|
4月前
|
Cloud Native 安全 数据安全/隐私保护
云原生架构下的微服务治理与挑战####
随着云计算技术的飞速发展,云原生架构以其高效、灵活、可扩展的特性成为现代企业IT架构的首选。本文聚焦于云原生环境下的微服务治理问题,探讨其在促进业务敏捷性的同时所面临的挑战及应对策略。通过分析微服务拆分、服务间通信、故障隔离与恢复等关键环节,本文旨在为读者提供一个关于如何在云原生环境中有效实施微服务治理的全面视角,助力企业在数字化转型的道路上稳健前行。 ####
|
3月前
|
Java 开发者 微服务
从单体到微服务:如何借助 Spring Cloud 实现架构转型
**Spring Cloud** 是一套基于 Spring 框架的**微服务架构解决方案**,它提供了一系列的工具和组件,帮助开发者快速构建分布式系统,尤其是微服务架构。
363 69
从单体到微服务:如何借助 Spring Cloud 实现架构转型