QQ是怎样创造出来的?

时间: 2019-12-08 07:29编辑:admin

本篇介绍笔者触摸的第一个后台体系,从本身见识动身,因而触及的内容相对比较根底,后台大牛请自觉略过。

什么是老友体系?

简略的说,老友体系是保护用户老友联系的体系。咱们最了解的老友体系事例当属qq,实践上qq是一款即时通讯东西,凭着老友体系沉积了海量的老友联系链,然后铸就了一个坚不可摧的商业帝国。老友体系的重要性可见一斑。

了解互联网产品的人都知道,当产品有了必定的用户量,往往会开发一个老友体系。其首要意图是添加用户粘性或许添加社区活跃度。

而我的后台开发作计便是从这样一个体系开端的。

那时分,老友体系关于咱们团队大部分人来说,都是一个全新的事物,由于咱们大部分人都是应届生。整个体系的架构天然不是咱们一群黄毛小孩所能发明。当年的架构图现已找不到了,可是凭着一点回忆和多年来的经历堆集,仍是能够把当年的架构勾勒出来。

 

如图,老友体系的架构是常见的3层结构,包括接入层、逻辑层和数据层。

咱们先从数据层讲起。

由于咱们对qq太了解了,咱们能够很容易地列出老友体系的数据首要包括用户材料、老友联系链、音讯、在线状况等。

互联网产品往往要面临海量的恳求并发,传统的联系型数据库比较难满意读写需求。在存储中,一般是读多写少的数据才会运用mysql等联系型数据库,并且往往还需求添加缓存来确保功用;nosql应该是现在的干流。

关于老友体系,用户材料和老友联系链都运用了kv存储,而音讯运用公司自研的tlist,在线状况下面再介绍。

接着是逻辑层。

在这个体系中杂乱度最高的应该是音讯服务。

音讯服务中,音讯按类型分为谈天音讯和体系音讯,按状况分为在线音讯和离线音讯。在完成中,保护3种list:谈天音讯、体系音讯和离线音讯。谈天音讯是两个用户同享的,体系音讯和离线音讯每个用户独占。当用户在线时,谈天音讯和体系音讯是直接发送的;假如用户离线,就把音讯往离线音讯list存入一份,等用户再次登录时拉取。

这样看来,音讯服务并不杂乱?其实不然,体系规划中惯例的流程规划往往是比较简略的,可是关于互联网产品,反常状况才是常态,当把各种反常状况都考虑进来时,体系就会十分杂乱。

这个比方中,音讯发送丢包是一种反常状况,怎样确保在丢包状况下,还能正常运转便是一个不小的问题。

常见的处理方法是收包方回复承认包,发送方假如没收到承认包就重发。可是承认包又或许丢包,那又能够给承认包添加一个承认包,这是一个永无止境的承认。

处理方法能够参阅tcp的重传机制。那问题来了,咱们为什么不必tcp呢?由于tcp仍是比较慢的,谈天音讯的可靠性没有买卖数据要求那么高,丢几条音讯并不会形成严重后果,可是假如用户每次发送音讯后都要等好久才干被收到,那体会是很差的。

一个比较折中的计划是,收包方回复承认包,假如发送方在必定时刻内没有收到承认就重发;假如收包方收到两个相同的包,去重即可。

一个面试题引发的评论:

面试时我常常会问好选人一个问题:在分布式体系中怎样完成一个用户一起只能有一个终端在线?这是互联网产品中十分根底的一个功用,调查的是提名人根本的架构规划能力。

规划要先从接入服务器说起。接口机是老友体系对外的窗口,首要功用是保护用户衔接、登录鉴权、加解密数据和向后端服务透传数据等。用户衔接老友体系,首先是衔接到接口机,鉴权成功后,接口时机在内存中保护用户session,后续的操作都是根据session进行。

如图所示,用户假如测验登录两次,接口机经过session就能够将第一次的登录踢下线,然后确保只需一个终端在线。

问题处理了吗?

没有。由于实践体系必定不会只需一台接口机,在多台接口的状况下,上面的方法就不可行了。由于每个接口机只能保护部分用户的session,所以假如用户先后衔接到不同的接口机,就会形成用户多处登录的问题。

 

天然能够想到,处理的方法便是要保护一个用户状况的大局视图。在咱们的老友体系中,称为在线状况服务。

在线状况服务,望文生义便是保护用户的在线状况的服务。用户登录和退出会经过接口机触发这儿的状况改变。由于登录包和退出包都或许丢包,所以心跳包也用作在线状况保护。

一种常用的方法是,选用bitmap存储在线状况,详细是指在内存中分配一块空间,32位机器上的天然数一共有4294967296个,假如用一个bit来表明一个用户id,1代表在线,0代表离线,那么把悉数天然数存储在内存只需4294967296 / = 512mb。当然,完成中也能够根据需求给每个用户分配更多的bit。

所以,踢下线功用如图所示。

 

用户登录的时分,接口机首先查找本机上是否有session,假如有则更新session,接着给在线状况服务发送登录包,在线状况服务查看用户是否现已在线,假如在线则更新状况信息,并向前次登录的接口机ip发送踢下线包;接口机在收到踢下线包时会查看包中的用户id是否存在session,假如存在则给客户端发送踢下线包并删去session。

在实践中,踢下线功用还有许多细节问题需求留意。

又回到用户先后登录同一台接口机的状况:

 

图中踢下线流程是正确的,可是假如过程10和13调换了次序会发作什么?咱们能够自己推演一下,后到的踢下线包会把第2次登录的a 踢下线了。这不是咱们希望的。怎样办呢?

处理方法分几个细节,①接口机在收到13号登录成功包时,先将session a替换成session a ,然后给客户端a发作踢下线包;②踢下线包中有必要包括除用户id外的其他标识信息,session的仅有标识应该是id+xxx的方法,xxx是为了区别某次的登录;③接口机在收到踢下线包的时分只需判别id+xxx是否符合来决议是否给客户端发踢下线包。

现实状况,问题总是千奇百怪的,好在方法总比问题多。

比方我在项目中遇到过接口机和在线状况服务时刻漂移的状况。这样踢下线的仅有标识就不能是用户id+logintime的方法了。能够为每次的登录生成一个仅有的uuid处理。相似的问题还有许多,不再赘述。

总结一下,本篇首要介绍了老友体系的全体架构和部分模块的完成方法。分布式体系中各个模块的完成其实并不难,难点首要在于应对杂乱网络环境带来的问题和服务器反常带来的问题。

老友体系尽管简略,但麻雀虽小五脏俱全,架构规划的各种技能根本都有触及。例如分层结构、负载均衡、平行扩展、容灾、服务发现、服务器开发结构等方面,后边我会在各个不同的项目中介绍这些技能,敬请期待。

菠菜首存-菠菜网-菠菜信誉导航