本文正文部分引用了58同城架师沈剑的文章,非常感谢他的分享。
1、前言
IM应用从服务端数据的角度来看,它是一种很特殊的应用场景,抛开基础数据、增值业务和附属功能不谈,单从IM聊天工具的立身之本——聊天数据来说,理论上是不需要在服务端存储的(或者说只需要短暂存储——比如离线消息,上线即拉走),这也是为什么微信在前段时间号称绝不存储用户聊天数据的原因(从技术上说这不是没有道理的,但到底有没有存储,这已经超越技术范畴了,不在此文讨论之列 ^_^)。
那么为什么说IM系统的服务端从技术上说,是不需要存储聊天数据的呢?
原因很简单,我们知道IM的聊天数据分两种:
1)一种是实时消息(就是你在线,对方也在线情况下的聊天数据交互);
2)一种是离线消息(就是你在线,对方不在线时,你发过去的消息,对于对方而言就是离线消息了)。
实时消息的收发:服务端只作为中转角色(关于中转的技术问题,很多人可能还在结纠老思维为何不用P2P,我已经论坛说烂了,说白了跟技术无关,其实一个很重要的原因就是为了运营的可控性:比如用户P2P去了,违法的锅你运营方来背好不好?),聊天消息在此时就相当于左手倒右手——即聊天数据的本质就是从A用户经过服务端到达B用户就完了,服务端完全没必要存储(当然,我们讨论的是技术理想情况,实际上抛开技术因素来说,这么多丰富的用户行为数据你是运营方你会放过吗?但,这跟技术无关对吧)。
离线消息的收发:当接收方不在线时,发送方的聊天数据在服务端只需要作短因果报应存储,因为接收方一旦上线就拉走了,服务器删除即可(注意:从技术上来说就是这样的哦)。对用户而言聊天消息的社会学的本质来说就像两个人在对话,我已经听见你说的就好了,干吗老像复读机一样一遍一遍一说给我听?
正如上述所言,IM系统中最重要的聊天数据从技术上不说其实是没有存储的必要的。不过话虽如此,但一个大型的IM系统的方方面面数据量也是很可观的,所以开发IM系统时讨论服务端数据库的读写分离、水平分表等,是很有必要的。因而通过本文快速理解服务端数据库的读写分离原理你不应错过,本文也同时建议您在正确理解它的前提下再慎重决定您的服务端架构方案是否需要数据库读写分离,因为很多时候增加缓存策略就能解决的问题,就没有必在大炮打蚊子了。
好了,费话多说了几句,我们开始阅读正文。
学习交流:
- 即时通讯开发交流群:320837163[推荐]
- 移动端IM开发入门文章:《新手入门一篇就够:从零开发移动端IM》
(本文同步发布于:http://www.52im.net/thread-1366-1-1.html)
2、相关文章
▼ 跟IM数据存储架构有关的文章,有如下几篇,或许对你有用:
《腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率》
《微信海量用户背后的后台系统存储架构(视频+PPT) [附件下载]》
▼ IM开发干货系列文章适合作为IM开发热点问题参考资料(本文是其第12篇):
《IM消息送达保证机制实现(一):保证在线实时消息的可靠投递》
《一种Android端IM智能心跳算法的设计与实现探讨(含样例代码)》
《IM开发基础知识补课(一):正确理解前置HTTP SSO单点登陆接口的原理》
《IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?》
《IM开发基础知识补课(三):快速理解服务端数据库读写分离原理及实践建议》(本文)
如果您是IM开发初学者,强烈建议首先阅读《新手入门一篇就够:从零开发移动端IM》。
3、什么是数据库读写分离?
如上图所示,一主多从、读写分离、主动同步,是一种常见的数据库架构。
一般来说:
1)主库——提供数据库写服务;
2)从库——提供数据库读服务。
3)主从库之间,通过某种机制同步数据,例如mysql的binlog。
4)像上述图中这样,一个主从同步集群通常被称为一个“分组”。
那么,数据库“分组”架构究竟解决什么问题?
大部分互联网业务读多写少,数据库的读往往最先成为性能瓶颈,如果希望:
1)线性提升数据库读性能;
2)通过消除读写锁冲突提升数据库写性能;
3)此时可以使用分组架构。
一句话总结:“分组”主要解决“数据库读性能瓶颈”问题,在数据库扛不住读的时候,用“分组”架构实现读写分离,通过增加从库线性提升系统读性能。
4、什么是数据库水平切分?
如上图所示,跟数据库“分组”架构实现读写分离一样,水平切分(也称大表拆分、分表),也是一种常见的数据库架构手段。
一般来说:
1)每个数据库之间没有数据重合,没有类似binlog同步的关联;
2)所有数据并集,组成全部数据;
3)会用算法,来完成数据分割,例如“取模”;
4)一个水平切分集群中的每一个数据库,通常称为一个“分片”。
水平切分架构究竟解决什么问题?
大部分互联网业务数据量很大,单库容量容易成为瓶颈,如果希望:
1)线性降低单库数据容量;
2)线性提升数据库写性能;
3)此时可以使用水平切分架构。
一句话总结:数据库水平切分架构主要解决“数据库数据量大”(或者更细一点说是单表数据量太大)问题,在数据库容量扛不住的时候,通常水平切分。
5、数据库读写分离虽好,但不应滥用
对于互联网大数据量、高并发量、高可用要求高、一致性要求高、前端面向用户的业务场景,如果数据库读写分离:
1)数据库连接池需要区分:读连接池,写连接池;
2)如果要保证读高可用,读连接池要实现故障自动转移;
3)有潜在的主库从库一致性问题。
实际上,如果您的系统面临的是“读性能瓶颈”问题,增加缓存可能来得更直接,更容易一点。
另外,从成本上说,从库的成本比缓存高不少。而且对于云上的架构,以阿里云为例,主库提供高可用服务,从库不提供高可用服务,实现方案上更主流。
所以,上述业务场景下,建议使用缓存架构来加强系统读性能,替代数据库主从分离架构。
当然,使用缓存架构的潜在问题:如果缓存挂了,流量全部压到数据库上,数据库会雪崩。不过幸好,云上的缓存一般都提供高可用的服务。
6、简单小结
典型的大型互联应用架构中,服务端数据库架构主要使用以下两种:
1)使用“分组”架构实现数据库读写分离:解决“数据库读性能瓶颈”问题;
2)使用“分片”架构实现数据库水平切分:解决“数据库数据量大”问题。
但对于互联网大数据量、高并发量、高可用要求高、一致性要求高、前端面向用户的业务场景,使用微服务缓存架构,很多时候可能比数据库读写分离架构更合适。
附录:更多IM开发文章
[1] 有关IM架构设计:
《一套海量在线用户的移动端IM架构设计实践分享(含详细图文)》
《IM开发基础知识补课(二):如何设计大量图片文件的服务端存储架构?》
>> 更多同类文章 ……
[2] 有关IM安全的文章:
《即时通讯安全篇(一):正确地理解和使用Android端加密算法》
《即时通讯安全篇(四):实例分析Android中密钥硬编码的风险》
《即时通讯安全篇(五):对称加密技术在Android平台上的应用实践》
《传输层安全协议SSL/TLS的Java平台实现简介和Demo演示》
《理论联系实际:一套典型的IM通信协议设计详解(含安全层设计)》
《微信新一代通信安全解决方案:基于TLS1.3的MMTLS详解》
《来自阿里OpenIM:打造安全可靠即时通讯服务的技术实践分享》
《Web端即时通讯安全:跨站点WebSocket劫持漏洞详解(含示例代码)》
>> 更多同类文章 ……
[3] IM开发综合文章:
《IM开发基础知识补课:正确理解前置HTTP SSO单点登陆接口的原理》
《IM消息送达保证机制实现(一):保证在线实时消息的可靠投递》
《开源IM工程“蘑菇街TeamTalk”的现状:一场有始无终的开源秀》
《QQ音乐团队分享:Android中的图片压缩技术详解(上篇)》
《QQ音乐团队分享:Android中的图片压缩技术详解(下篇)》
《腾讯原创分享(一):如何大幅提升移动网络下手机QQ的图片传输速度和成功率》
《腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(上篇)》
《腾讯原创分享(二):如何大幅压缩移动网络下APP的流量消耗(下篇)》
《如约而至:微信自用的移动端IM网络层跨平台组件库Mars已正式开源》
《基于社交网络的Yelp是如何实现海量用户图片的无损压缩的?》
>> 更多同类文章 ……
(本文同步发布于:http://www.52im.net/thread-1366-1-1.html)
本文同步分享在 博客“JackJiang2011”(JianShu)。
如有侵权,请联系 support@oschina.cn 删除。
本文参与“OSC源创计划”,欢迎正在阅读的你也加入,一起分享。