这篇文章主要描述的是Prismatic公司系统架构,作者是Todd Hoff,本文出自Todd对Prismatic的程序员Jason Wolfe的邮件专访。
关于Prismatic,首先有几个事情要说明下。他们的创业队伍很小,仅仅由4个计算机科学家构成,其中的三个都是年轻有为的斯坦福以及伯克利博士。他们是在用智慧解决信息超载这个问题,然而这些博士也同时担任着程序员的角色:开发网站、iOS程序、大数据以及机器学习需要的后台程序。Prismatic系统架构的亮点是如和使用机器学习实时地解决社交媒体流的处理问题。由于商业机密的原因,他没有透露他们的机器学习技术,但是我们可以通过架构看个大概。Prismatic创始人之一Bradford Cross把Prismatic的系统简洁地描述为:“它是一个提供大规模、实时以及动态的个性化信息排名、分类以及分组功能的综合系统。”接下来就把这个系统的架构展现给大家。
Prismatic主要功能是发现我们的兴趣,为我们推荐阅读
今天你应该读点什么呢?任何一个现代人每天都会陷入这个困境,大家通常使用一些很隐秘的途径去找到自己想要读的东西:Twitter、RSS、Facebook、Pinterest、G+、email以及Techmeme等这些信息源。Prismatic回答了“今天我应该读什么?”的问题,Jason Wolfe慷慨的同意并且详细地描述下他们正在使用的解决方案,言语中包含了许多时髦的技术名词,例如机器学习,社交图谱,大数据,过程化编程以及事实需求等等。然而结果是他们的方法更隐秘,但和其他一些相似应用不一样的地方在于他们会发掘你的兴趣,无论这些兴趣在你的信息中藏得有多深。
正如大家预料的,他们的做法有点特别。他们选了Clojure做为开发语言,它是一个编译成Java bytecode的现代Lisp语言。主要目的是充分利用过程化语言去构建具有丰富粒度,结构自由的程序,从而满足各种问题带来的特殊需求。列举两个他们用到的过程化语言的优点的例子:第一个是他们几乎每个地方都使用图库。对于每个用户来说,他们的图形计算可以被称为低延迟,流程化的map-reduce任务集;另外一个例子是他们使用子图实现了模块化的服务配置。
他们把系统设计的焦点放在过程化开发上来,避免了使用像Hadoop那样的巨型框架,转去使用小型的,这使得系统更可靠,更容易纠错,更容易扩展以及更容易理解。Prismatic的机器学习做法的难点在于要求一个非常长的训练周期。需要指出的是:首先,获得优质分析源内容并不需要多少时间;其次,使用基于机器学习的推荐系统需要对用户从幼儿到现在的一生的所有数据进行训练;这个可扩展的思维数字模拟系统扮演着信息的收集者以及生产者双重的角色。
图:越来越多的应用开始关注用户的阅读推荐
统计数据
- 现在每天有几千万篇文章、博客以及其他一些内容通过Twitter,Facebook,Google Reader以及互联网发布。
- 但是仅仅需要用户登录时的那几秒钟,Prismatic就能够使用他们之前的阅读历史进而去分析用户的兴趣,然后推荐阅读,使用用户在社交网络上的活动,从而将联系人发表的、符合用户胃口的文章推荐过来。同时,Prismatic也会记录用户在它本身上的动作,也将它做为分析的一个来源。
- Prismatic只需要数十秒钟去访问用户的个人主页,通过和用户兴趣模型对比,便可以分析出用户最感兴趣的东西。
- 现在每周有数百万的优秀文章通过Prismatic成功分享给用户。
平台
- Prismatic的主机托管在AWS的EC2上,使用Linux操作系统。
- Prismatic99.9%的后台通道和API服务都用Clojure开发。
- Prismatic所有的重量级框架部署在JVM中。
- Prismatic使用MongoDB存储服务器参数和用户分析数据。
- Prismatic使用了MySQL。
- Prismatic使用了S3。
- Prismatic使用了Dynamo。
- Prismatic将重点放在开发能解决特殊问题产生的需求的代码上。
数据存储和输入输出
- 和典型的结构不同,Prismatic的服务都围绕着数据而设计,可以提供实时读写数据的能力。
- 大部分数据都直接在后端管道之间传输,不会和磁盘发生I/O。
- Prismatic把数据保持在离CPU尽可能近的地方,这样就让API的请求几乎没有IO延迟,同时把API绑定到CPU上,巧妙的扩展了系统的规模。
- Prismatic使用了许多现成的解决方案:MongoDB,MySQL以及Amazon的S3和Dynamo。每个都是经过对实际需求仔细研究的,包括规模,接入模式和数据存储相关的其他特性。
服务
从外部来看,Prismatic的系统被分成了10个独立的服务模块,大致可以归总为5种类型:数据采集;新用户管理;API;其他客户机服务;批处理。每个服务都是为一个功能而设计,通过一种特殊的方式进行横向扩展,通常受1到2个特殊资源限制(IO,CPU,RAM)。
- 数据采集——后台
每天都会有大量内容(包括文章,博客和网页等)产生,Prismatic想要尽可能多的捕捉到他们。为了让用户可以评论每个内容,并和自己兴趣相投的朋友进行分享,Prismatic必须识别每个内容的作者,分享者以及一些比较有价值的评论。做这些的第一步就是收集和分析内容和关系数据。
首先在采集通道入口执行下面这些步骤:通过喜好在RSS上找到新文章;通过API将用户Twitter和Facebook上的最新评论和动态收集上来。执行这些功能的服务非常简单,而且没有状态信息,唯一的状态和有意思的地方是如何确定哪些信息是已经收集过的了和怎样智能的分析接下来该收集哪个信息。其中最难的就是前者,因为有些人他可能在多个地方发过同一个信息。
接着,把RSS、Twitter以及Facebook等信息源收集上来的资料送入到一个过滤器中,让它决定哪些需要进入通道进行分析。首先把垃圾邮件和其他垃圾信息丢掉,URL将被送到管道中去,此时会有很多有趣的事情发生,Prismatic会建立一个URL队列,将每个队列送入一个图运算中,使用它将URL进行详细描述,抓取它的HTML代码,使用机器学习的算法把文章的内容抓取出来,识别最好的图片,抓取出作者,标签以及话题等等。为了让这些过程尽可能快速进行,能够装入内存以及提高表现力,他们投入了很大一部分时间,当然,处理这些URL的方式是高度并发的。
最后是文档控制器,它的作用是接收上面处理好的详细的文章和社交内容,将他们进行匹配,把文章集整理成故事系列,决定把哪些设为当前要处理的文档,并且管理这些API相关的机器目录。
- 新用户管理——后台
新用户管理模块主要负责收集新注册的用户的信息。它主要由两个部分构成:通过用户的Twitter,Facebook以及GoogleReader找出他喜欢的主题以及喜欢的文章来源;分析他的社交图谱,找出他最喜欢哪些朋友分享的文章。
执行这些功能的服务也是高度并行的。社交图谱分析非常复杂,关键是这些服务如何能够实现如此低的延迟以及如此可靠的吞吐量:对于Twitter,Facebook和Google Reader的活跃用户来说,准确找出数百个用户喜欢的话题对于Prismatic来说只需要15秒,甚至更少。用户授权以后,Prismatic就可以非常快地分析出用户的兴趣,用户常常在注册的时候(填写密码和点击确认的过程中)这个工作就已经完成了。看看在这15秒内,发生了什么:Prismatic把用户最近在Twitter和Facebook上发表的内容以及Google Reader中标记为喜欢的东西都抓取进来,这一般是10秒钟左右;然后把用户和他的联系人等共享的1000个URL收集上来;再将这些数据送入上面提到的文档控制器,使用相同机器学习堆栈进行采集/分析的通道;这些分析结果经过聚合,后期处理,最终都存储到DynamoDB和S3里去。
这个过程对延迟的要求非常严格,所以这些进程不能串行,必须并发执行,所以他们不得不尽可能多地使用通道和并行处理的技术。这个过程对吞吐能力要求和很高,因为每个进程并不小,同时一旦有许多用户同时来注册,要想降低延迟你就必须做更多的事情。这里也是Prismatic的独到之处,他们的流处理和聚合类都将重量级降了下来,把性能做到了极致,达到了每个用户使用一个低延迟map-reduce任务的效果。对于多个用户的情况,他们系统使用的并发处理几乎发挥了机器的全部性能。
API——面向客户机
数据采集和新用户管理都部署在API机器上。系统主要的设计目标和挑战是:最近的文章必须被编入索引并且可以满足低延迟的需求,索引并不算小(常常是许多GB),而且必须实时更新,只有这样才能把最近更新的文章传递给用户,这些需要为用户设计跨机器的负载均衡,同时要求必须能快速简单地将任务划分到新机器(当然还有关闭合并);如果要想找到用户的真正需求,仅仅使用索引是不够的,同时还需要用户的“指纹”(他们的爱好,社交关系,最近读过的文章等),这些指纹数据非常大而且在不断发生变化。
对于前几个问题需要用到文档控制器(上面提到了)。文档控制器组织当前的文档集,对他们进行预处理,每隔几分钟就把刚刚做好的的索引集存储S3中去。当一个新的API机器启动时,文档控制器首先读取这些文件,将他们放入内存,再将最新的索引副本传递给它。文档控制器也负责将所有索引的改动(新增文档/新增评论/删除等)实时地传递给所有正在运行的API机器上去。其他一些API机器常用的功能也由文档控制器从S3中读入内存,周期性的更新到S3,如果数据超过了S3的存储大小限制,就将它存入DynamoDB。
剩下的问题就是如何在保证延迟需求前提下,提取和更新每个请求里的用户“指纹”。Prismatic这里使用的方法是使用粘性会话(Session),把用户绑定到一台API机器上。当用户第一次登录的时候,就把他的信息存入一个具有有效期的回写式缓存中。在用户会话的生命期周期内,把其中的数据放入内存进行兴趣分析。在这个过程中用户进行的所有操作都会通过同一个API机器进行处理,对于那很小的一部分不关键的用户指纹,每隔几分钟,会话到期或者关闭时再分批进行更新。更多的关键指纹直接进行同步或者至少使用一个直写式缓存进行更新。
其他的服务——面向客户机
- 公共兴趣功能,主要是为没有登录的用户服务,通过常规的API收集他们的需求,按照年龄分区,将不同的需求放在不同的页面上。
- 用户功能,管理创建账户,登录等功能。通常就部署在SQL数据库上,存储用户的主要数据,但这些常常需要周期性地拍下快照并且进行备份。
- URL简化服务
- 批处理以及其他服务
- 另外还有一些其他的服务,用于机器语言训练,数据归档和事件追踪和分析。
图库
这是一个声明性的描述图形计算的好方法,充分发挥了Clojure的优点。一个图就是一个Clojure示意图,在里面定义键值对,键里存储的是关键词,值里存的是使用示意图中其他方法对关键词计算后得到的功能,这样就达到了外部参数的效果。
这个方法几乎在所有的地方得到了应用。例如文档分析通道就是一个图,其中每个文件中的核心内容都依赖于它(举个例子,如果要定义某个文档的主题,前提是先要提取它的文字内容);订阅生成进程就是一个由查询和排名两个步骤组成的图;每个订阅生成服务本身就是一个图,其中的每个资源(如数据存储,内存,HTTP控制器等)就是这个图一个节点,他们互相依赖。这样就为下面这些工作提供了方便:
模块化对服务配置进行简洁描述(例如使用子图);使用进行和服务之间的相互依赖关系绘制出图表;测量每个节点在进行像文档分析,或者在每个复杂服务(例如API)的资源上进行的活动等复杂运算时,所需要的计算时间和发生的错误;智能为每个计算的不同线程规划节点(在理论层面甚至到机器层面);通过用模拟的方式替换掉图中的一些节点,从而可以对全部生产服务进行简单的测试。
Prismatic把机器学习的技术用于了文档和用户这两个领域。
机器学习用于文档
对于HTML文档的处理:提取出页面中的核心文本(而不是它的侧栏,页脚,评论等),标题,作者,有用的图片等;确定文档相关的一些特点(例如文章是关于什的,主题等)。这些任务的模式很典型。模型通过其他机器大型批任务进行训练,首先将数据从S3读入,然后再把学到的参数文件存储S3上,之后在内容提取通道中将S3中的模型读入(同时也要定期刷新)。所有从系统输出的数据也会反馈给通道,这样就对了解用户的兴趣更有帮助,做到了随时从错误中学习。
Prismatic研发的框架“flop”库是软件工程师最感兴趣的,它实现了最先进的机器学习训练和推理代码,它和普通的漂亮的Clojure代码非常相似,但确编译(使用神奇的宏)成低级的数组执行循环,这使得它和Java中的metal非常相似,不用借助于JNI便可以使用这个框架。
这个代码框架比一个重量级的Java更简洁,更容易读懂,同时和Java的执行速度基本持平。Prismatic将大部分的功夫都花在创建一个能快速运行的故事机器组件上了。
机器学习用于用户
使用社交网络数据推测用户都有哪些兴趣并且使用应用中的明显标志(用户增加一些或者删除一些文章)去优化这些推测。
使用这些明显标志的问题很有意思,因为用户的输入必须要非常快速的在他们的订阅中反馈。如果一个用户将一个推荐的出版物中5个文章都删除了,接着马上就不要再把这个出版物中的其他文章给用户继续展示了,第二天也不要。这意味着没有时间为所有的用户执行另一个批处理任务,解决的办法就是在线进行学习:当用户提交了那些明显的标志时,立刻对用户的模型进行更新。
用户和应用交互时产生的原始数据流要保存下来。这样就可以稍后重新运行对用户兴趣进行机器学习所需要的原始流数据,同时还能避免由于脆弱的缓存在上传这些数据的过程中出现错误,从而导致这些数据丢失。引入在线学习可以纠正并且更加准确地对模型进行计算。
学到的东西
- 找到你的定位。仔细考虑下整个通道和流过它的所有数据。在众多的挑战上多做些工作,针对每个问题提出特定的解决方案。每个服务都有它自己的规模,同时服务间使用一个非常容易扩展的方式进行的通信,这种方式还不能给其他的服务带来太大的压力。Prismatic没有使用Hadoop构建系统,所有的数据都以原始数据的形式存在分布式数据库和文件系统中。
- 发现并充分利用高度并行的机会。
- 当用户在等待时进行并行运算。新用户注册过程,例如新用户上传通道要在用户等待时并发工作,这样就可以实现在几秒内就完成注册。
- 使用过程化语言开发丰富粒度的,自由抽象的程序。这些抽象层次可以用于构成特殊问题的逻辑层。
- 避免重量级,大规模的框架,例如Hadoop。这样产生的是较小的代码库,相同条件下,更不容易出错,更容易理解并且更容易进行扩展。构建自己的代码库的理由很简单,因为大部分开源的功能都被锁入了重量级的框架中,很难进行代码复用,扩展和问题出现时很难进行调试。
- 找到合适的人开发对系统很重要。目前Prismatic后台服务开发团队是由3个计算机科学博士组成,他们负责所有的开发工作,包括从机器学习的算法研究到低层次的web和iPhone客户端系统工程的所有代码。
- 将所有的代码尽早投入生产,尽管投资早期经常在构建和调试工具,但这使创建和调试产品服务变得简单和有趣。
- 保持简单。不要花太多精力在复杂的代码库或者框架上,使用简单的东西,当有一个更简单的解决方案足够好时就不要再幻想了。例如使用简单的机遇HTTP的通信协议,而不要再去考虑什么流行的框架了。如果能够工作,要很乐意去买一些现成的管理解决方案,例如S3或者Dynamo。
- 多在构建强大的开发工具和类库上下些功夫。例如,Prismatic的“flop”库,它允许他们写出和Java处理速度一样快,代码量只有十分之一的数字运算机器学习算法;“Store”抽象了许多不重要的键值存储细节,允许在各种环境下高度的对缓存,批处理和传递流数据进行抽象;“graph”使的写数据,测试和管理分布式流进程服务变得简易可行。
- 对每一种数据类型要慎重考虑,不要期望能找到一个I/O和存储的通用解决方案。(@康文博编译)
最后分享下使用的感受:
我(译者)登录到Prismatic首页的时候,简单大方的风格在我使用之前就感受到了技术气息十足(这时系统会推荐大众兴趣)。当我点击注册的时候,界面提示可以用Facebook账号登录,输入了用户名和密码的时候(这时他已经把我Facebook,Twitter和Google Reader里的数据进行了分析),之后展现给我的是一篇一篇云计算和大数据的文章,当然也包含一些移动新闻等(果然实时的250ms不是吹嘘的)。
这让我想到了国内的应用,第一个是有道阅读,用过的朋友都应该知道,它其实只提供了Prismatic未注册用户效果,即推荐了很多的大众热点兴趣,然后要求用户在里面勾选。第二个我想到了的是网易邮箱,当你订阅的关键词比较准确时,他推荐的文章也大都比较符合用户的口味。然而可惜的是Prismatic目前只支持Facebook,Twitter和Google Reader等国外的社交工具,内容抓取的范围也仅是国外的知名出版物,所以我很期待国内能够出现与之媲美的应用,将微博,QQ,人人等国内社交工具集成进来,将阅读推荐做到每个人都不一样,每篇文章都符合用户的口味。
相关链接:Prismatic系统架构解析:机器学习在社交数据分析和用户分析上的实践
原文链接: Prismatic Architecture - Using Machine Learning On Social Networks To Figure Out What You Should Read On The Web