融云QCon大会深度解析超大规模IM系统优化问题一带一路·共建繁荣中国网

关键词:算法复杂度,异步通讯,缓存策略,双数组,LRU

融云首席架构师李淼演讲

火爆的演讲现场

会议结束后参会嘉宾与李淼继续沟通

数据存储方面,在即时通讯保证消息可靠性的情况下,优先进行消息存储,通过这种方式保证消息不丢失、不乱序、不重复。对于数据存储而言,其实和I/O有点类似,对于一般的业务来讲,如果数据存储优化的好,平台优化方面就完成了60%左右的工作。

下面通过三个阶段介绍一下融云关于性能问题的定位。第一个阶段融云刚刚成立,那个时候性能问题的定位主要是通过系统监控,配合着系统日志以及诊断工具,主要监控服务器里面的CPU、内存及I/O指标。

实际上对于性能问题的定位来讲,第一个阶段是最有效的,后面的手段都是辅助研发人员对于线上问题的定位,这些都是相辅相成的:你判断问题、定位问题需要工具,工具也可以提高你判断问题、定位问题的速度。

高并发系统技术要点

对于高并发系统来讲,其实技术要点很多,我罗列了四条:异步通讯、缓存策略、数据结构及算法、数据存储。对于性能优化来讲,这四点仅仅是一部分,但如果把这四点做好,平台就能得到一个很大的提升。

首先是异步通讯,对于现在的分布式系统来讲,都需要对服务进行拆分,服务拆分以后我们需要通过一种方式将服务串联起来,现在有很多开源的解决方案或框架,但是对于RPC来讲,一般都是同步调用,有点类似于访问数据库,当前的工作线程需要等待调用端反馈结果。

如果说某个服务的响应时长十毫秒,对于调用端来讲就需要等待十毫秒,为了解决这个问题,现在很多RPC都支持异步RPC的方式,通过回调的方式解决同步RPC工作线程占用以及等待的问题。

最后一个是Actor模型,Actor模型实际上在整个软件系统上是一个属于多线程数据协调的模型。所有的请求以及返回结果会以消息的方式进行传递,融云也是使用了Actor模式作为服务间调用。

第二个是缓存策略,我们对于数据分为四层:首先是原始数据,这个数据是保存在数据库里面的;第二个是分布式缓存,对于很多无状态的服务而言,性能优化大部分依赖于分布式缓存来完成;第三个为了对数据访问进行加速,可能会使用一些本地进程内缓存,由于没有网络访问,同时直接的内存访问速度更快,所以本地缓存策略也会作为服务加速的方式;最后就是客户端缓存了,现在无论是App开发,PC客户开发都可以使用用户侧的数据存储,Web上的H5也可以使用类似localstorage解决方案,但是一旦使用了客户端存储,我们就需要设计一个健壮的数据同步模型。刨除客户端缓存的问题,为了尽可能达到使热数据离用户近一些这个目的,我们就需要想尽一切办法提高缓存的命中率。

第四数据存储,我们依然要提场景的问题。对于一般系统开发来讲,一个关系型数据库基本上就可以满足业务需求开发了,但实际上如果仅仅通过关系型数据库来做的话,即使能满足业务需求也不一定可以满足性能需求。所以说要熟知你的业务场景,根据业务场景选择合适的数据存储。除此之外,还需要了解这些存储的原理。

性能优化案例

性能优化案例内存优化篇。这个场景对于key缩短问题,对于系统当中的用户ID本身来讲长度不可控。我们通过一个哈希算法转变进制,变成64进制,这样对于超过22个字节的数据进行压缩,最终优化效果把内存的利用率降低了大概10%。

第二个内存优化主要是LRU缓存优化,如果有大量冷数据访问到系统中之后,会把热数据冲掉,这对于系统的吞吐量有很大影响。我们优化的方式是做了一个二级LRU缓存,将冷热数据按照配比进行隔离,冷数据40%,热数据60%,这样系统里热数据被淘汰的问题便得以缓解了。

性能优化案例。数据状态的延迟写入,这个场景中消息里会记录每个用户的状态。如果用户收了一千条消息,数据就要被写入一千次,我们通过另外一种模式,消息状态数据一直是在本地内存当中进行写入,待多次写入直到数据不活跃后,我们才将数据写入真实的存储里。通过这种优化,将之前的多次数据写入变成了一次数据写入。

之前监控数据每天有几千亿次需要存储和写入,通过添加缓存区,让将监控数据传输量降低了两个数量级。

数据存储。首先对于消息来讲,他的写入和读取场景是比较特殊,通过自研的存储引擎,将存储的设备降低了一半的数据量,同时保证了整个系统的响应速度。另外,调整了数据库的业务引擎,对于业务数据占用磁盘比较高的问题,优化之后的结果大概只有之前的30%左右,即存储降低了70%。

系统设计把控

另外,技术选型需要充分考虑团队对技术的接受能力,同时一定要对每个你所选东西的原理有充分认识,这样的话才能做出一个比较好的选择。

THE END
1.字典树算法(C/C++)字典树算法(C/C++) 本文介绍了字典树(Trie)算法,一种用于高效存储和检索字符串的数据结构。文章详细阐述了字典树的基本概念,包括插入、查询操作,并提供了一个C++实现示例。此外,文章还讨论了在删除和修改操作上的挑战,并给出了一种可能的解决方案。最后,通过一个例题展示了字典树在解决字符串查找问题中的应用。https://blog.csdn.net/gaoqiandr/article/details/131033556
2.算法学习:字典树算法学习:字典树 一、概念 字典树,即 Trie 树,又称单词查找树或键树,是一种树形结构。 典型应用是用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。 优点:最大限度地减少无谓的字符串比较,查询效率比哈希表高。https://www.jianshu.com/p/724b805999bb
3.Trie树(字典树或者前缀树)算法详解算法简介 Trie树,即字典树,也有的称为前缀树,是一种树形结构。广泛应用于统计和排序大量的字符串(但不仅限于字符串),所以经常被搜索引擎系统用于文本词频统计。它的优点是最大限度地减少无谓的字符串比较,查询效率比较高。 Trie的核心思想是空间换时间,利用字符串的公共前缀来降低查询时间的开销以达到提高效率的目的https://leetcode.cn/circle/discuss/mv8GnX/
4.《Java数据结构与算法》第7章:字典树腾讯云开发者社区字典树 Trie 这个词来自于 retrieval,于 1912 年,Axel Thue 首次抽象地描述了一组字符串数据结构的存放方式为 Trie 的想法。这个想法于 1960 年由 Edward Fredkin 独立描述,并创造了 Trie 一词。你看看,多少程序员为了一个词、方法名、属性名,想破脑袋!https://cloud.tencent.com/developer/article/2191777
5.字典树&01字典树算法笔记51CTO博客字典树&01字典树算法笔记 1】学习了字典树之后,觉得它很明显的就是用空间来换时间,空间复杂度特别大,比如字典数单单存26个小写字母,那么每个节点的孩子节点都有26个孩子节点,字典树中的每一层都保留着不同单词的相同字母。 2】01字典树主要用于解决求异或最值的问题https://blog.51cto.com/u_15067244/3900256
6.python算法图解提要文摘附注:本书系统论述了Python编程的理论与方法,全书共分11章,包括数据结构的分类和基本运算、递归、栈和队列、链表、数组、树结构、堆结构、散列表、字典树、图和排序算法。 预约委托 49 浏览 纸本馆藏(1) 收起 索书号 条码号 馆藏地/书架号 书刊状态 导航 TP311.561/H32D A0460959 总馆- C-2https://oleopac.lib.sztu.edu.cn/space/searchDetailLocal/m17da2133e62cbd9111a4fe6337e49fd0
7.一文搞懂字典树!字典树,是一种空间换时间的数据结构,又称Trie树、前缀树,是一种树形结构(字典树是一种数据结构),典型用于统计、排序、和保存大量字符串。所以经常被搜索引擎系统用于文本词频统计。它的优点是:利用字符串的公共前缀来减少查询时间,最大限度地减少无谓的字符串比较,查询效率比哈希树高。 https://zhuanlan.zhihu.com/p/420663173
8.Trie树(字典树)的介绍及Java实现javaTrie树,又称字典树或前缀树,关于它的结构就不详细介绍了。Trie树在单词统计、前缀匹配等很多方面有很大用处。下面这篇文章主要介绍了Trie树,以及Java实现如何Trie树,有需要的朋友可以参考借鉴,下面来一起看看吧。简介Trie树,又称为前缀树或字典树,是一种有序树,用于保存关联数组,其中的键通常是字符串。与二叉查找https://www.jb51.net/article/104543.htm
9.字典树(trietree)专注于c++字典树(trie tree) 今天AC了两题trie tree的题目,感觉trie的性质真的是相当的好,而且实现比较简单。它使在字符串集合中查找某个字符串的操作的复杂度降到最大只需O(n),其中n为字符串的长度。trie是典型的将时间置换为空间的算法,好在ACM中一般对空间的要求很宽松。http://www.cppblog.com/bellgrade/archive/2009/10/08/98097.html