登录
/
注册
首页
论坛
其它
首页
科技
业界
安全
程序
广播
Follow
关于
博客
发1篇日志+1圆
记录
发1条记录+2圆币
发帖说明
登录
/
注册
账号
自动登录
找回密码
密码
登录
立即注册
搜索
搜索
关闭
CSDN热搜
程序园
精品问答
技术交流
资源下载
本版
帖子
用户
软件
问答
教程
代码
VIP网盘
VIP申请
网盘
联系我们
道具
勋章
任务
设置
我的收藏
退出
腾讯QQ
微信登录
返回列表
首页
›
业界区
›
业界
›
高性能分布式计算与存储系统设计概要——暨2012年工作3 ...
高性能分布式计算与存储系统设计概要——暨2012年工作3年半总结(上)
[ 复制链接 ]
孓访懔
2025-5-29 18:52:47
高性能分布式计算与存储系统设计概要(上篇)
2012年底,末日之后,看到大家都在写年末总结,我也忍不住想一试。工作已经3年半了,头一次写总结。虽然到现在仍是无名小码农一名,但工作这些年,技术着实有不少积累。成长最大的,当然就是这篇文章标题提到的——高性能分布式计算与存储系统的设计和研发过程,这也是我自2010年供职于国内最大的某著名网站之后,和这个系统一起成长,亲眼见证和伴随着它的发展,从一个婴儿一样的"Demo"程序,成长为现在可以处理千万级日PV的强大系统,直到2012年我离开。我也顺势积累了Unix/Linux服务器、多线程、I/O、海量数据处理、注重高性能与效率的C/C++编程等宝贵的码农财富,当然,遗憾和不足,仍然是有许多的。
2012年,其实是自工作以来,技术积淀最多的一年。因为,在2012年,我终于学会了独立思考,我不再像以前一样,许许多的技术只是需要用到的时候,匆忙的google(有时候还要先匆忙的先FQ
),我发现,“好记性不如烂笔头”,古训确实毋庸置疑,有大量的、琐碎的技术经验、编程细节、技巧,需要积淀下来,可能单条的细节与技巧,并不会对一个人的职业生涯产生什么影响,但把它们都积聚起来,就会强大许多,很实际的,带来的技术提升,能带来更高的Offer。所以,2012年,我开始到博客园写技术博客,和众多园友分享我对技术的一知半解,共同进步;也终于耐下心,为自己做了一个简单的个人主页,虽然10年前,我就可以做出这样的东西……;我成为了更忠实的苹果粉,所以我尝试去做iOS创业,虽然这和我的主要工作研究方向并不一致,当我看到自己做的demo在自己iPhone 4s上跑起来,我突然又有一了一种久违的兴奋——那是每一个程序员,都体会过的,小小的成就感;2012年,我开始接触和了解许多以前从来不懂的技术:Hadoop、GoogleFS、JVM、XCode、ARC……小到如何将vim打造成一个IDE……。
接下来,该进入这篇文章的正题了, 就是简单地谈谈,我这两年,主要做的东西——高性能分布式计算与存储系统。
这个系统看名字十分牛比,所涉足的目前互联网最领先的技术领域。具体有什么用途? 在我之前供职的公司,它主要是作为中间层,给网站页面提供缓存服务的,并且,它对付的难题,是大数据、海量数据,相信,每一个日PV超过千万级的网站,都必须会有类似的系统存在,如果,你曾经看过,博客园里的《淘宝技术发展》等类似文章,就一定不会对我接来将要提到的许多概念和术语感到陌生。对于这样大流量,需要处理大数据的网站而言,由Web的逻辑直接调用管理数据存储,是非常不科学的,实际上也是不可能的,大数据、高并发的对数据库进行读写,通常数据库都会挂掉,从而使网站也挂掉,必须要在Web和数据库之间,通过技术手段实现一种“转换”或“控制”,或“均衡”或“过渡”,我不知道这样用词是否正确,你只要明白其中的意思就好了。这样的技术手段有许多,所实现的东东也有许多,我们用到的,就是被称为“中间层”的一个逻辑层,在这个层,
将数据库的海量数据抓出来,做成缓存,运行在服务器的内存中,同理,当有新的数据到来,也先做成缓存,再想办法,持久化到数据库中,就是这样简单的思路
,但实现起来,从零到有,可以说难如登天,但是,任何事物,都是在曲折中,不断发展前进的,这是中学我们就学过的哲学理论。这个系统,就被我们称简为“缓存系统”,它最大的好处,就是砍掉了每天上千万次的数据库读写操作,取代而之的,是读取服务器中提供缓存服务的进程所控制的内存,所以你知道,这里面节省了多少的资源申请、竞争、I/O……当然,后面你也会发现,它会带来许多新的问题,最显著的问题,就是数据的同步和一致性,后面我会讲到。
现在,让我们先看看, 这个系统,发展到我离开它的时候,长什么样子?(由于涉及到商业机密,具体的技术不能提供)
就是这样的一张架构图,代表着可以处理每日上千万PV的系统,涉及到许多的技术,让我们一个部分一个部分解读它。
首先,从当我有一个web请求到达时,将会发生怎样的事情说起。比如,我是一个用户,我在这个网站登陆,我的“个人”页面上,将会加载许许多多的东西,有许许多多的图片、文字、消息等,我们举其中一个例子,我将要得到我的好友列表——friend list。通过常识可以知道,这个friend list,不是随机的、临时的,而肯定是一个(一组)持久化存储于数据库里的数据,我们就是一个用户请求得到他的friend list说起,来解读这张架构图。如果我的网站流量很小,每天不超过10万PV,峰值可能就几百个上千个用户,同时请求他们的friend list,那么,现今任何一种语言配上任何一种数据库的搭配,只要稍做处理,都可以很好的完成这个工作——从数据库中,读出该用户的friend list,然后访回给web,如果用户对好友列表作了任何修改,web马上将修改内容写入数据库,形成新的friend list。然而,当访问流量持续提升,达到千万级、甚至亿级PV的时候,刚才说的方法就不可行了。因为,同时可能有几十万甚至上百万用户,通过web请求从数据库中读(如果写将会更糟糕)上百条万数据,数据库将不堪重负,形成巨大的延迟甚至挂掉。通过上面的系统,来解决这样的问题。
现在,我们要设计和研发的上述系统,当一个web页面提交一个获取friend list的请求后,它首先将根据一定的规则,通过负载均衡,然后到达相应的master节点。上面我们提到的是DNS负载均衡,这得众多负载均衡技术中的一种方法。也就是说,我有许许多多的master节点(上图的scalabe表明,我是可扩展的,只要有条件,可随意横向扩展节点,以提高速度、容灾、容量等指标),每个master节点的IP地址(域名)当然不一样,通过DNS负载均衡,合理地把该请求,送到相对“空闲”的master节点服务器。现在解释一下master节点服务器和slave节点服务器的功能:slave节点,主要用于"Running services",即,实际处理请求的缓存服务进程,通常运行在slave节点上;master节点,主要用于分发通过负载均衡的请求(当然,master节点上也可以运行一些“缓存服务进程”,即并发流量不高、较辅助的一些服务),找到用于处理实际请求的合适的slave节点,将该请求交给它处理,再次实现了一道“负载均衡”,同时,需要分布式计算的内容,将可能同时分发到几个slave节点,之后再对结果进行合并返回(Map-Reduce原理)。
好了,现在我们已经知道,一个friend list请求已经通过DNS负载均衡、通过master节点进行分配,到达了相应的slave节点上。我们还知道,所说的“缓存”
,正是slave节点中所运行的services进程中所管理的内存,提供同样功能的service可能会有很多份,同时运行在不同slave节点上,以提供高并发和分布式计算的功能。例如,获得friend list就是这样的service,因为这个功能太常用了,所以,在我们的系统中,这样的服务可能同时提供5份、10份甚至更多,那么我这个获取friend list的请求,究竟被分配到哪个slave节点上的service处理呢?这正是刚才提到的master节点来完成这一工作。再比如,我现在需要获取“二度关系”的列表(关于六度人脉理论,可google),所谓“二度关系”,就是好友的好友,那么我要取这样的列表,即friend's every friend list,这样的请求,将会把取每个friend list分配(Map)到不同slave节点上去做(根据一定的规则),然后再进行合并(Reduce)(当然,熟悉算法的同学可能已经发现,这样去获取请求,非常的笨拙,有没有更好的方法呢?当然有!因为好友的好友,其实就是好友的friend list与我和好友的共同好友common friend list的“差集”,对吗?
,所以我不用去取好友的每个好友的friend list,而只用取2次就可以通过计算完成请求,这又节省了多少资源呢?假如我有100个好友,1000个,10000万个?会节省多少次计算呢?这也证明,一个良好的算法,对改善程序性能,有多么大的帮助!)
好,我们继续。现在,我的获取friend list的请求,已经在被某个slave节点中的负责这一功能的service进程处理,它将根据一定规则,给出两种可能的处理方式:
1、 我这个用户非常活跃,经常登陆网站(一定的规则,认为缓存未到过期时间),且我这个slave节点自上次“重建缓存”(即重新从数据库中读取数据,建立缓存,后面会谈)后,没有发生过down机重启行为(又一定的规则),我也没有收到过master节点发送过来要求更新缓存(即从数据库中比较数据并更新)的Notification(通知),或是在一定条件下我这个slave节点对它掌握的缓存数据版本(版本管理系统原理,思考一下svn的工作原理)和数据库进行了一次比较(注意,比较数据版本可认为只是一个int值,且是原子操作,这和比较整条数据是否一致在性能上有天壤之别)发现是最新的数据版本,那么,我这个slave节点将直接返回缓存数据,而没有任何数据库读操
作
,也就是说,我这一次获取friend list的请求,得到的是缓存数据,当然,这个缓存数据肯定是最新的、正确的、和数据库中的持久化数据是一致的,后面会提到怎样来尽量保证这一点;
2、第1点中的“一定规则”不满足时,即我这个slave节点的缓存和数据库中的数据可能存在不一致的没有其它办法,我必须从数据库中读取数据,更新缓存,然后再返回。但同时注意,slave节点中的service服务进程,将认为此用户现在活跃,可能还会请求一些相关、类似的数据(如马上可能进行添加好友、删除好友等操作),所以去数据库读取数据的时候,将不会只读friend list,可能与用户有关的其它一部分数据,会被同时读取并更新缓存,如果负责这一部分数据的缓存服务并不是当前的service进程,或在其它slave节点,或同时还有几份service进程在工作,那么slave节点将提交“更新缓存”请求给master节点,通过master节点发出Notification给相关slave节点的相关service进程,从而,
尽可能使每一次读取数据库的作用最大化,而如果稍后用户果然进行了我们猜测的行为(可认为cache命中),结果将同第1点,直接通过缓存返回数据而且保证了数据的正确和一致性。
好了,刚刚提到的都是“读操作”,相比“写操作”, 其数据一致性更容易保证,之后我们将讲述“写操作”的工作原理。现在,让我们先跳过这一部分,继续看架构图。slave节点之后,就是实际的数据存储了,使用了MySQL、Redis,MySQL主从之间的协同是DBA的工作,不在此篇讨论,Redis主要存储K-V键值对数据,比如用户id和用户昵称,是最常用的K-V对之一,通过Redis进行存储,再结合上述的工作过程,可保证这个系统的高性能。而架构图最右下角的Hadoop与MongoDB,是可选的MySQL替代方案,其实,正是未来的主要发展方向。如果slave节点中的service服务进程与Hadoop良好结合,系统的性能将更上一层楼。顺便说一句,master、slave节点都是由C++开发的。Why C++?可参考酷壳上的一篇文章《C++ Performance per $》。
好了,上篇就讲到这里,余下的问题,我们在下篇进行讨论,谢谢大家。
(下篇)
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
回复
使用道具
举报
提升卡
置顶卡
沉默卡
喧嚣卡
变色卡
千斤顶
照妖镜
高级模式
B
Color
Image
Link
Quote
Code
Smilies
您需要登录后才可以回帖
登录
|
立即注册
回复
本版积分规则
回帖并转播
回帖后跳转到最后一页
签约作者
程序园优秀签约作者
发帖
孓访懔
2025-5-29 18:52:47
关注
0
粉丝关注
15
主题发布
板块介绍填写区域,请于后台编辑
财富榜{圆}
敖可
9984
黎瑞芝
9990
杭环
9988
4
猷咎
9988
5
凶契帽
9988
6
接快背
9988
7
氛疵
9988
8
恐肩
9986
9
虽裘侪
9986
10
里豳朝
9986
查看更多