本文由转转 梁会彬、杜云杰分享,原题“转转IM的实践与思考”,下文进行了排版和内容优化。
接上篇《整体架构设计》,笔者将以转转IM架构为起点,介绍IM相关组件以及组件间的关系;以IM登陆和发消息的数据流转为跑道,介绍IM静态数据结构、登陆和发消息时的动态数据变化;以IM常见问题为风景,介绍保证IM实时性、可靠性、一致性的一般方案;以高可用、高并发为终点,介绍保证IM系统稳定及性能的小技巧。
本文是系列文章中的第2篇,本系列文章的大纲如下:
梁会彬:转转架构部资深Java工程师,主要负责服务治理平台、Docker云平台、IM、分布式ID生成器、短域名服务等,有丰富的线上实战经验。
应用层:使用IM服务的上游业务方,包括app(ios和android)、小程序/PC/m页、push、业务方等。
接入层:
逻辑层:
数据层:
数据流中以用户A和用户B的对话为例,其中用户A的uid为1,用户B的uid为2。
下图为用户聊天场景图:
下图为用户聊天IM系统的数据流转图:
登陆信息存储在Redis中,联系人和消息数据放在TiDB中。
1)登陆信息:
key:uid value:{entryIp:"127.0.0.1",entryPort:5000,loginTime:23443233}
2)联系人:
说明:
3)消息:
说明:
数据流=数据+流。上面部分讲数据,即联系人和消息表,从静态的角度介绍了IM的数据结构;下面部分讲流(IM中最重要的两个流程),即登陆和发消息,从动态的角度来阐述IM系统中数据的流转。
1)问题:entry地址发现:app直接访问vip,由vip转发到entry。
2)流程(下面的数字为图中数字的说明):
3)数据:
Redis中数据如下:
key:1 value:{entryIp:"127.0.0.1",entryPort:5000,loginTime:23443233}
1)流程处理:
2)数据:
联系人数据如下:
消息表数据如下:
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字段展示聊天方向,这样就可以用一条消息,无需和联系人表一样存储两份数据,满足两种查询,节省一半的消息存储。
1)是什么:
用户A给用户B发送消息"hello world",用户B怎么第一时间感知到?这里说的实时性,就是指用户如何实时获取发送的消息。
2)io模型带来的启示:
3)怎么办:
1)是什么:
2)tcp模型带来的启示:
3)怎么办:
1)是什么:
2)身份证带来的启示。
3)怎么办:
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呢,任何重要的服务都要面对这些问题吧,推而广之,面对自己负责的服务,怎么精细小心都不为过。
诚然,这篇文章给大家对IM系统简单的认识,阐述了IM的一般架构、主要业务逻辑、常见问题和解决方案以及服务治理相关应用,IM还有很多业务逻辑和技术挑战。
在业务上,如未读数、群聊、多端登陆、母子账号等;在技术上,entry长连接100k问题优化、时间轮计时器实现、海量数据拆分与存储选型等。
路漫漫其修远兮,吾将上下而求索。
(本文已同步发布于:http://www.52im.net/thread-4773-1-1.html)
[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及开放平台技术实践
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文系转载,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。