引子
最近换了工作,时间也充裕了一些,利用休假时间和自己的空余时间对所思所学,进行归纳总结。对于自己3年来一直努力的Buddy,进行了深入的思考,其实一直以来,具体来说从04年开始就一直习惯的用PHP,到现在,这么多年的时间,很多时候自己把自己限制在了PHP所能实现的范围内,不过这个也是由时代决定的,04到现在从Web1.0到2.0,从做站开始,就一直围绕“站”这个概念来做东西,所以PHP还是足够用了,之后到了百度,还是做了PHP,作为一个开发工程师,一直在完成各个逻辑功能,功能做多了,就想自己能不能做一个框架,来让自己做事情做的更快一些呢?为此,将积累的代码进行整理,命名为buddy,它的完善随着 的开源项目一并完善,一直到2011年都在做堆逻辑的事情,就想有所改变,是否应该在深入底层?后来换了部门之后发现,其实牛人真的很多,看了做PHP做到极致的 及组内的其他的RD,QA同学们的能力之后,意识到自己的水平,真的是......小吐槽下,其实意识到自己的差距,那么应该做些什么来提高自己?看着各个技术达人基本都是在一些方面做到极致之后,其他的方面也跟上了,达到了高手的境界,在此特别提下2个人,,,因为现在使用的技术都是他们开发的,一个是的项目,一个是的框架。之所以是牛人,因为他们在往牛人的路上,都留下了产出,这些东西,造福了其他的人或者说其他的人可以从这里学到很多。不管是项目上的应用,还是看到他们源码之后自己的提升。说了这么多总结一句,就是有一些人有不同于他人的想法而又把这些想法实现了,这些才是值得大家记住和尊重的。
简单高效智能的架构是什么样的?
先上张图,通过图中来来详细的解说为什么它简单、高效、智能
技术选型
Nginx(OpenResty) + PHP + Mysql + Redis + Memcachd + Sphinx + 外部的API
图中的部分,从上到下来看
第一层,Presentaion 表现层,和用户交互的部分,也可以说是请求的来源,系统的入口
第二层,API 接口层,提供对表现层的数据交互的支持,包含了主要的3部分,业务部分,公共部分和监控报警部分,右边的主要是用户的私有数据 和 公共的数据 以及一些静态的资源
第三层,LOGIC 逻辑实现层 + Sharding,可以支持海量的数据存储,逻辑层涉及到各种的模块,外部的API接口等等,以及后端的异步模块等,模块方面主要有MatchMaker(分类器,建立对象和对象之间的关系),Searchd搜索模块(提供搜索支持),Recommender推荐器(对外提供推荐服务)还有一些统计模块和用户找回模块等...
第四层,Store 存储层,主存储使用了 Mysql,Redis
如何简单?
简单,我理解的简单,从技术选型来讲,就是用自己熟悉的,经过生产环境检验的可靠的技术产品.
比如:
Redis,从最近的Twitter的Timeline以及Instagram中介绍,还有之前微博也使用,充分的让大家认识到Redis的强大。
Nginx,牛逼了很多年了,但是通过OpenResty项目,让人深刻的感受到,Nginx,它真的不只是Web服务器软件。
从开源的角度来讲,主要是开源产品的技术认可度以及作者(个人/团队)是否在积极的维护。从当前用的OpenResty和Yaf来看,作者都是很积极的,更不用说Nginx和Redis的作者的了。
Yaf:最近每个一周基本有一个版本,鸟哥很给力,我昨晚报告了一个Bug,今天就修复了,发布了2.1.14版本了
OpenResty:4.29号刚刚发布的新版本,章亦春老师也很给力。
Nginx:刚刚不久前发布了1.2.0版本
Redis:看作者的Blog最近2.6RC在一直进行中,估计也不久的了
Mysql:5.5系列的版本也在不断的开发中
由于这些作者的活跃和开发,只要项目中遇到问题或者是发现Bug都可以及时的联系到他们并能得到作者的反馈,这个是亲自体验过,备受感动.
大部分底层的事情,都让牛人做了,那我们能做什么呢?关注与自己的业务逻辑,是否就是简单了?也许,这个时候,你会说,这个怎么简单了?还是需要写很多的代码,还是要考虑Sharding的问题,还是要考虑到各个模块之间的数据互通,还是需要考虑到数据结构的设计等等,这个时候Buddy就可以登场了,Buddy就是将这些技术产品及我们需要的模块都能够完全的融合进来,并将项目中的共性的部分,通过接口抽象出来,实现大部分的功能,这样您只要开发自己项目中的特殊的部分,大大的减少开发时间,那么,用Buddy,在靠谱的软件集合下面做自己的项目,省事也省心。接下来的博文中,会对架构图中每个模块部分进行详细的阐述并附上具体的代码。这里只是笔者的一种实现方式,聪明的你也许做的比笔者更好,那就开始行动吧!
如何高效?
高效应该如何定义?由于很多的项目都存在sharding,所以单纯的从性能来说,一个请求发送和接收需要的时间还有数据量的不同,10ms? 200ms ? 300 ms? 如何才能算高效呢?
还是可以从单机的性能测试来算,看cpu的idle及内存占用等来算?其实笔者认为,在执行的过程中,尽量用高效的语言做尽可能少的事情,这样才是高效。这里主要来show下OpenResty的评测的结果。以及章老师PPT中的一些结论。
具体的可以点击图片看章老师的微博中的具体的评论以及中的文章。
看了评测之后,看了由 Lua 粘合的Nginx生态环境 中章老师对生成环境下的介绍的,确实是感觉一个提升,可以节省很多的服务器及带宽的成本
这些是章老师的评测及相关的介绍,本次笔者所在的公司的项目中也会实践这个架构,接下来也会出一些性能的评测出来,别人说的高效,要在自己的项目中能实现,才是真的高效。
高效是对自己而言的,高效是意味着更小的投入有更高的负载能力和更好的用户体验。
如何智能?
智能,最近出现在很多的地方都提及,印象较深的是豆瓣的豆瓣猜首页,其中主要的是看了豆瓣的阿稳写的《智能WEB算法》里面对于智能WEB的表述,其实笔者认为智能的范围相对而言比较广,而且在于用户的体验,用户如何体会到智能? 看到一些的站点的页面上渐渐的出现了,你可能喜欢,你可能认识,你可能想买,你关注的人也关注了某某。随着智能的普及,我们是否在初期设计的时候就从架构的角度来解决这些问题呢?从架构图中可以看到,笔者标了3个模块MatchMaker,Recommender,Searchd,Count这4个模块,主要是为了从常见的部分尝试实现智能。一下具体阐述如何通过这些模块来实现智能。
MatchMaker模块,输入2个对象,判断2个对象之间是否存在关系,并确定是否要建立关系或者解除关系。并将最终的数据放到Private/Public 存储中,具体设计是放到Redis的数据类型为List/Set的存储中,实现前端可之间读取的关系集合。也许你会说,这个之前我们是如何做的?比如说淘宝上的发布商品,你会经过4层,还有输入过程中输入勾选各种的属性,最终发布了宝贝,然后建立了宝贝和各种属性,品牌,分类等之间的关联,那我们需要做到这样细化的粒度的关联么?我们可以通过使用聚类或者分类等各种智能WEB算法来实现自动的分类么?其实笔者也在尝试中。接下来完善模块后会详细的细化模块,现在只有一些最简单的通过对象的title来进行分词并通过分词后的结果建立tag之间的关联关系的实现。其他的具体的场景根据项目中具体用到的在逐渐完善。
Recommender模块,推荐器模块,通过使用协同过滤及复合的算法来实现对具体场景的推荐,这块网上的资料也很多,还是得根据自己项目的场景来具体的选用不同的算法来实现,笔者的项目中用到的一些,主要有判断2个是否相似,用到了距离计算的一些算法,编辑距离/dice距离等。还有在开发中的,参考了项目中的,基于物品和基于用户的推荐等。用户的访问日志及行为日志分析也作为反馈到推荐器中,建立推荐器所有的数据。
Searchd模块,搜索模块,搜索当前项目中使用了Sphinx,之前在Solr和Sphinx中选择了Sphinx,主要的原因有:
一,Sphinx的配置和资料比较多些,国内有Coreseek项目在中文方面支持的比较多。
二,配置相对比较简单,相比于Solr而言,对于配置有张宴大侠写的文章,都比较详细。
三,当前来说够用,对于数据量在千万到上亿级别还够用。郁闷的是看源码比较吃力。主文件24k行,实在头大。
四,自动提示及统计搜索热词,以及词库的配置等,还用了一些分词模块,主要有scws,xplite
搜索结果的体验很重要,对于结果现在都是使用评分模式,现在笔者的项目中用到的还是只有一些属性的加权平均算出来的。
Count模块,统计模块,对于之前的提及基本都是通过在数据库中进行SQL,还有LOG统计得来,Buddy中的提及主要是设计了触发点,根据事件来驱动,将数据存储在redis中,之后进行计算,实现了大部分的及时的数据提及功能,主要使用了OpenResty中之间通过HTTP写redis及Log的读取后抽取并提交到接口接口进行输入的方式来统计。统计模块详细的设计在后续的文章中将有详细的描述。
结语
很多时候,都在使用大家认为稳妥的技术方案,好多的时候,一个Team里面其实还是有想吃螃蟹的人的,可惜最后都被和谐了,在和谐的社会里面,技术也和谐,还有什么激情?
听过很多的抱怨,也有过多个项目亲身经历,很多时候对于技术方案最终的选型都无法最终决定,为此当你有能力决定技术选型和架构的时候,是不是可以尝试下?
是否可以从全局及未来来考虑,让我们使用简单高效智能的技术解决方案,来更快,更好的将项目推进,并能够通过技术节约公司的成本。
也许这样,就多能撑过一个冬天,也许这样,你会自豪的说,其实我也是个爱吃螃蟹的人!