用Map/Reduce来做好友推荐

SNS网站都有一个功能,就是好友推荐(或者Follower推荐)。例如,在人人网上出现的“你可能认识的人”。怎么来实现呢,有一个很简单的办法。如果小刚和小明不是好友,但是他们有很多的共同好友。那么可以认为,A和B很可能相识。

从图论的讲法上看,就是先列出一个人(记为小A)的所有朋友的朋友,在寻找小A和这些人之间有多少长度为2的通路。将这些通路数排序,寻找最高的那几个就可以了。

所以我们的Map/Reduce的任务就是:找出所有人的十个Top“推荐好友”。

社会化网络的图一般都很简单。我们假设输入是按name排序的。

  1. "ricky" => ["jay", "peter", "phyllis"]
  2. "peter" => ["dave", "jack", "ricky", "susan"]

我们使用两轮Map/Reduce任务来完成这个操作。

第一轮MR任务

这个任务的目的是计算每一对距离是2的人之间的通路数。

  • 在Map函数中,我们先将每对朋友做一个笛卡尔乘积,说的不大清楚,举个例子,比如
    1. "ricky" => ["jay", "john", "mitch"]

    那么结果就是

    1.  ["jay", "john"], ["jay", "mitch"], ["john", "mitch"]

    他们都是通过ricky牵线搭桥认识的。将已经是朋友的组合筛选掉,再排好序。传给Reducer。

  • 在Reduce函数中, 相同的组合必定会传给Reducer。所以Reducer只要数好有几个相同的组合传给他就行了.
Input record … person -> connection_list
  1. e.g. "ricky" => ["jay", "john", "mitch", "peter"]
  2. also the connection list is sorted by alphabetical order
  3.  
  4. def map(person, connection_list)
  5.   # Compute a cartesian product using nested loops
  6.   for each friend1 in connection_list
  7.      # Eliminate all 2-degree pairs if they already
  8.      # have a one-degree connection
  9.      emit([person, friend1, 0])
  10.      for each friend2 > friend1 in connection_list
  11.          emit([friend1, friend2, 1],  1)
  12.  
  13. def partition(key)
  14.   #use the first two elements of the key to choose a reducer
  15.   return super.partition([key[0], key[1]])
  16.  
  17. def reduce(person_pair, frequency_list)
  18.   # Check if this is a new pair
  19.   if @current_pair != [person_pair[0], person_pair[1]]
  20.       @current_pair = [person_pair[0], person_pair[1]]
  21.       # Skip all subsequent pairs if these two person
  22.       # already know each other
  23.       @skip = true if person_pair[2] == 0
  24.  
  25.   if !skip
  26.       path_count = 0
  27.       for each count in frequency_list
  28.           path_count += count
  29.       emit(person_pair, path_count)
  30.  
  31. Output record person_pair => path_count
  32. e.g. ["jay", "john"] => 5

第二轮MR任务

这一轮的MR任务是为了列出每个人距离为2的好友,查出他们直接究竟有几条路径。

  • 在Map函数中,我们将每一组数据重新排列,保证一个人信息落在一个reducer上
  • 在Reduce函数中,只要将每个人的可能好友之间的路径数排个序就可以了.
Input record = Output record of round 1
  1.  
  2. def map(person_pair, path_count)
  3.   emit([person_pair[0], path_count], person_pair[1])
  4.  
  5. def partition(key)
  6.   #use the first element of the key to choose a reducer
  7.   return super.partition(key[0])
  8.  
  9. def reduce(connection_count_pair, candidate_list)
  10.   # Check if this is a new person
  11.   if @current_person != connection_count_pair[0]
  12.       emit(@current_person, @top_ten)
  13.       @top_ten = []
  14.       @current_person = connection_count_pair[0]
  15.  
  16.   #Pick the top ten candidates to connect with
  17.   if @top_ten.size < 10
  18.       for each candidate in candidate_list
  19.           @top_ten.append([candidate, connection_count_pair[1]])
  20.           break if @pick_count > 10
  21.  
  22. Output record person -> candidate_count_list
  23.  
  24. e.g.  "ricky" => [["jay", 5],  ["peter", 3] ]

Follower推荐
如果我想要做Follower推荐而不是好友推荐怎么办呢?
很简单。只要将第一步的MR任务改为求“Follow关系”和“Followed”关系的笛卡尔乘积就可以了。这里就不列伪码了。

参考地址:http://horicky.blogspot.com/

Eclipse4.0的新特性(可下载)

千呼万唤始出来,Eclipse4.0提前版发布了。我等这个版本已经一年多了。新的版本的性能很好,真的很好。但是没有我所期待的Web运行模式。界面也不如原先优雅了。

感觉Eclipse4.0对于Eclipse3.6。在功能上相当于Eclipse3.6对于Eclipse3.5,在Eclipse个上变化并不大。毕竟Eclipse的功能主要靠插件提供,而Eclipse只是给这些功能提供一个展现的舞台。

对 于Eclipse平台本身,将Web技术引入到Eclipse平台内部。Eclipse开发者可以使用Css,Javascript等Web技术来开发插 件。新的RCP可以是一个富客户端开发工具,可以将应用程序编译成Flex,Dojo(js),以及本地版本运行。不过RCP在eclipse3.5已经出现了。

接下来介绍一些Eclipse4.0的新特性。

Eclipse4.0项目主页 http://www.eclipse.org/eclipse4/

新版工作台

新版的Eeclipse更新了用户界面。此更新的主要目标是采取一个更现代的视觉风格,减少混乱,并使用空白空间代替原先的分割线来区分不同的界面元素。重新设计了选项卡和工作台,让我们能更专注于工作区域。

全局搜索框

和Gmail相似,工具栏上有了全局搜索框。提供了一个“快速通道”。这个功能很亮。

更灵活的布局

您现在可以将功能面板和编辑器叠在一起了。例如,在一些情况下,您可以将功能面板和编辑器叠在一起,以提供更多的空间。

您不仅可以混合操作面板和编辑器,你还可以在编辑器区域分割一块给操作面板,然后最大化编辑器区域。整个工作空间都显示编辑器。

Eclipse开发者相关的功能

  • 通用事件总线
  • 用户界面模块化
  • 简洁的模型结构
  • 使用CSS来控制样式
  • 更多

虽然这些内容对于使用Eclipse的人用处不大,但是对于平台本身影响还是很大的。

Facebook背后的软件

Facebook

Facebook的数据规模使得很多传统的解决方案根本不适用,或者无法分解来处理。保持一个拥有5亿用户的系统一直稳定可靠的运行,并不是一件很容易的事情。这篇文章介绍了一下Facebook使用的软件。

Facebook的扩展性挑战

在我们讨论细节之前,这里有一些Facebook已经做的软件规模:

  • Facebook有570000000000每月页面浏览量 (据Google Ad Planner)。
  • Facebook的照片量比其他所有图片网站加起来还多(包括Flickr等网站)。
  • 每个月超过30亿张照片被上传。
  • Facebook的系统服务每秒处理120万张照片 。 这不包括CDN服务中处理的照片。
  • 每月超过25亿条的内容 (状态更新,评论等)被共享。
  • Facebook有超过30,000服务器 (这个数字是去年一年!)

Facebook扩展所依赖的软件

Facebook是在某些程度上说仍然是LAMP的站点,但它比普通的LAMP大得多,以纳入其他元素和很多服务,并修改现行的做法。

例如:

  • Facebook的仍使用PHP,但它已经为它建立一个编译器,以便它可以分为本地代码打开了Web服务器,从而提高性能。
  • Facebook的使用Linux,但他特别为网络吞吐量做了优化。
  • Facebook的使用MySQL,但主要是作为一个Key-value的持久性存储,Jions和服务器逻辑操作在Web服务器上操作。因为在那里更容易执行。

还有是自编写的系统,如Haystack,一个高度可扩展的对象存储,用来存储Facebook的照片。还有Scribe,一个日志系统,可以运行在Facebook的巨大规模上的日志系统。

OK。现在 我们介绍一下全球最大的社会网络网站的所使用的软件吧。

Memcached


Memcached

memcached的是现在互联网最有名的软件之一了。 这是一个分布式内存缓存系统,用来作为Web服务器和MySQL服务器之间的缓存层(因为数据库访问比较慢)。 多年以来,Facebook已经提出了一些优化Memcached和一些周边软件的办法。如压缩network stack。

Facebook的每时每刻都有数10TB的数据缓存在Memcached的数千台服务器上。 它可能是世界上最大的Memcached的集群了。

HipHop for PHP

HipHop for PHP

PHP作为一种脚本语言,和本地程序相比是运行缓慢的。 HipHop可以将PHP转换成C + +代码,然后再进行编译,可以获得更好的性能。 因为Facebook严重依赖PHP,这使得其可以让Web服务器运行的更有效率。

一个工程师小团队在Facebook(一开始只有三人)花了18个月时间开发HipHop,现在已经是可用状态。

Haystack

Haystack是Facebook的高性能照片存储/检索系统(严格来说,是一个对象存储,因此它并不一定要存储照片)。 它有许多工作要做;有超过200亿张上传的照片,并且每一个被保存在四个不同的分辨率,因此有超过800亿张照片。

它不仅是对能够处理的上亿的照片,运行表现也是至关重要的。 正如我们前面提到的,Facebook的服务约120万张照片每秒 ,这个数字不包括CDN上的。 这是一个惊人的数字。

BigPipe

BigPipe是Facebook开发的一个动态的网页服务系统。 Facebook使用它来按section(称为“pagelets”)处理每个网页,以获取最佳性能。

例如,在聊天窗口是分开的,新闻Feed也是分开的,等等。 这些pagelets可以在一个页面表现的时候同时使用,这是该页面表现的时候获取进来的。即使某些工程的一部分关闭或中端,用户也可以获得一部分网页。

Cassandra

Cassandra

Cassandra是一个不会单点失败的分布式存储系统。 这是为NoSQL运动的一个重要组成部分,并已公开的源代码(它甚至成为一个Apache项目)。Facebook在搜索功能中使用它。

除了Facebook,还有一些人也用它,例如Digg的。 不过最近Twitter放弃了cassandra

Scribe

Scribe是一个灵活的日志系统,Facebook在他的内部大量使用。 它的能够处理在Facebook的大规模日志记录,并自动处理新的日志记录类别,Facebook有数百个日志类别(categories)。

Hadoop and Hive

Hadoop

Hadoop的是一个开源的map-reduce实现,使得它可以在进行大数据上进行运算。 Facebook的使用这个进行数据分析(而我们都知道,Facebook已经大量的数据)。 Hive就是发源于Facebook,使得对于Hadoop使用的SQL查询成为可能,从而是其更容易对非程序员使用。

Hadoop和Hive是开源的(Apache项目),有为数众多的追随者,例如雅虎和Twitter。

Thrift

Facebook使用的几种不同的语言和不同的services。 PHP是最终用于前端,Erlang是用于聊天,Java和C ++也使用于多种场所,也许还有其他语言。Thrift是一个内部开发的跨语言的框架,联系语言,使他们可以在一起合作,从而使他们之间可以交互。 这使得Facebook可以更容易为继续保持其跨语言的发展。

Facebook已经让Thrift开源。更多的语言支持已被添加到Thrift。

Varnish

Varnish

Varnish是一个HTTP加速器,可以作为一个负载平衡器,并缓存的内容,然后可以以闪电般的速度送达。

Facebook使用的arnish来处理照片和个人资料图片,处理每天数十亿的要求。 和其他的东西一样,Varnish是开源的。

保持Facebook 顺畅运行的其他东西。

我们已经提到的软件,组成了Facebook的系统,并帮助运行在大规模上。 但是,处理这么大的系统是一个复杂的任务,因此我们将列出一些其他的东西,他们保持了Facebook的平稳运行。

渐进发布和暗启动

Facebook有一个他们所谓的守门人制度(Gatekeeper),允许他们可以给不同的用户运行两套不同的系统。 这让Facebook渐进的发布新的功能,A / B测试,只为Facebook雇员发布等的某些特性。

Gatekeeper也可以让Facebook实现“暗启动”,这是在用户使用一些功能之前,就激活某些功能(因为用户没有察觉,所以称之为暗启动)。 这将作为一个现实世界的压力测试,在正式启动前,帮助揭露一些功能障碍和其他问题。 暗启动通常是在正式启动前两个星期。

Profiling的直播系统

Facebook的仔细监控其系统,有趣的是它也负责监察每一个PHP函数在生产环境的性能。 检测各个PHP的环境的配置运行情况。使用开源工具,XHProf

渐进的利用关闭功能来提升性能

如果Facebook运行时出现性能问题,有一个办法,就是逐步禁用不太重要的功能,以增强Facebook的大量核心功能表现。

我们没有提及的事情

我们没有提到硬件相关的事情,但这也是提高可伸缩性的重要一环。例如,就像其他大型站点,Facebook利用CDN来处理静态内容。Facebook还有一个the huge data center,可以帮助他扩展更多的服务。

Facebook的开源情结

不仅是Facebook使用(和帮助),如Linux,Memcached的,MySQL和Hadoop的开源软件,以及许多其他情况下,也贡献许多了其内部开发的软件。

Facebook亦开源了Tornado,一个高性能的网络服务器框架,由FriendFeed团队开发。

关于开放源码软件清单,可以在Facebook’s Open Source page.找到。

Data sources:

http://royal.pingdom.com/2010/06/18/the-software-behind-facebook/

Various presentations by Facebook engineers, as well as the always informativeFacebook engineering blog.

来到上海了

来到上海了。

挤上了人山人海的地铁,兴致勃勃的向浦东进发。大海的地铁确实很拥挤,要想跳钢管是不可能了。作为地铁的克星,果然不负众望,地铁行至一半,死机不动了,许久方徐行。

找了个地方安顿了下来。准备Galaxydb那个项目。去看看单位。采购生活资料,事情还是蛮多的。值得一提的是,我们下定决心,决定斥巨资购买一把菜刀的时候发现找不到能买到菜刀的地方了。于是我打听到因为世博会,上海已经停止出售和运输刀具。于是我们只有吃冷冻食物了。

其实我们还可以吃刀削面。


刀削面的传说

据传当蒙古鞑靼侵占中原后,为防止汉人起义造反,将家家户户的金属器具全部没收,并规定每十户人家只能用一把厨刀,切菜做饭时轮流使用。

一天中午,有位老汉想取刀做面,结果没能接到,气馁地回家,在回家的路上看到一块薄皮,就顺手捡起来揣在怀里。 回家后,老伴责怪老汉,老汉取出铁皮,老伴说:“你就会胡侃”,老汉灵机一动,就用这个切吧!他把揉好的面团放在一块木板上用左手端好,右手操起铁片就削了起来,薄薄的面片飞入锅中后不住地翻滚,很快就煮熟了。 老汉把捞入碗中浇上卤汁,边吃边说:“好得很,好得很,以后再也不用排队取厨刀了,就用这铁片片削吧。” 一传十,十传百,成了刀削面。

住的地方

床铺

同居对象的博客:http://www.qqlemon.com/

注:我们都是男性,性取向主流。

工作兼游戏台

又一个Grails BBS

最近浩然姐姐要我们交JavaEE的大作业,于是我敏捷了一把,用一个晚上的时间生产了一个Grails BBS。

以前有ROR和Java的基础,Grails学的很快,一两个钟头就略通皮毛了。推荐一本读物,多亏他的帮助。

BBS下载

域名转出中,访问不到莫见怪

Jsa4j快速入门

安装开发环境

安装Java JDK

安装Eclipse

下载jsa4j-derby

使用 Jsa4j开发

  • 新建一个Java工程,
  • 在classpath中导入dependence文件夹中的Jar包,还要有jsa4j-db-kv-derby- 1.0-alpha-1.jar.依赖情况详见:http://jsa4j.sourceforge.net/jsa4j-db-kv-derby/dependencies.html
  • 新建一个Xml文件,文件路径为 META-INF/jsa4j-db-kv.xml
    1. <jsa4j-db-kv xmlns="http://jerrymouse.org/ns/jsa4j-db-kv"
    2.         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    3.         xsi:schemaLocation="http://jerrymouse.org/ns/jsa4j_db_kv_1_0.xsd"
    4.         version="1.0">
    5.         <jsa4j-db-kv-unit name="derby-db">
    6.                 <provider>org.jerrymouse.jsa4j.db.kv.local.derby.DerbyDBManager
    7.                 </provider>
    8.         </jsa4j-db-kv-unit>
    9. </jsa4j-db-kv>
  • 新 建一个Java类:
    1.       package org.jerrymouse.jsa4j.db.kv.example;
    2.  
    3.       import org.jerrymouse.jsa4j.db.kv.DB;
    4.       import org.jerrymouse.jsa4j.db.kv.DBManagerFactory;
    5.       import org.jerrymouse.jsa4j.db.kv.Repository;
    6.  
    7.       public class Tutorial {
    8.  
    9.               private static DB db;
    10.  
    11.               private static String EXAMPLE = "example";
    12.  
    13.               private static DB getDB() {
    14.                       if (db == null)
    15.                               db = new DBManagerFactory().getDBManager("derby-db").getDB();
    16.                       return db;
    17.               }
    18.  
    19.               public static Repository getRepository(String prefix) {
    20.                       Repository repository = new Repository(prefix, getDB());
    21.                       return repository;
    22.               }
    23.  
    24.               public static void main(String[] args) {
    25.                       //存放一个字符串"hello jsa4j"
    26.                       getRepository(EXAMPLE).put("1", "hello jsa4j");
    27.                       //取出这个字符串
    28.                       String message = getRepository(EXAMPLE).get("1");
    29.                       System.out.println(message);
    30.               }
    31.       }
  • 如 是运行即可

详细参考API文档

示例代码下载示例代码

Jsa4j通用数据底层

jsa4j是Jerrymouse Storage API for Java的简称。是JerryMouse小组开发的通用数据 底层,可以架设在单机或者Gae环境之下。脱胎于CommonCloud项目,由于CommonCloud过 于复杂,缺乏可用性。所以开发了他的简化版Jsa4J。Jsa4J的目标是可用和简洁。项目地址



Jsa4j子项目列表

Jsa4j-db-kv 提供 KeyValue 数据库接口。有一个Derby和一个Gae实现。还有用于缓存的支持

接口本身非常简洁:只有两个方法:

 String get(String key)
 String put(String key, String value)

详 见API文档

Jsa4j-db-table 表结构的数据库支持

Jsa4j-search 提供全文搜索支持。

Jsa4j-bus 建立在分布式缓存上的通讯总线


Jsa4j- db-kv。随着NoSql?运动,新奇的数据库层出不穷,提供 了各种丰富的接口。这些接口丰富在两个方面:

  • 事务处理
  • 数据结构

Jsa4j- db-kv没有“事务处理”和“数据结构”的概念,极大的方便了数据库开发。

关于事务。不管是ACID还是 BASE,都是事务处理方式。Jsa4j-db-kv没有事务的概念,默认大于配置, 认为存操作需要事务,取操作不需要。认为数据库写入永远是成功的。具体是不是真的能成功,应该由另一套系统来管理。

对于比较可靠的列存数据库,和不怎么可靠的类似Cache的数据库都有支持。

关于数据结构。数据结构方面有关系性 数据库,列存(BigTable? like),文档数据库,图数据库和Key Value之分。其中Key Value是最简单的,可以由其他类型的数据库实现。同时提供一个索引工具和搜索工具,满足在数据索引上的需要。


项目地址

快速入门

Facebook Graph API使用介绍

Facebook Graph API可以理解为一个可以访问Facebook数据的Web服务。该API提供了对人员,相册,事件等等Facebook对象以及这些对象之间诸如朋友,标签,分享内容等等连接之间的访问。

当您输入一个URL后,会返回一个Json对象

对象的格式参考http://developers.facebook.com/docs/reference/api/

你可以用同样的方式访问Facebook对象

你也可以用https://graph.facebook.com/ID/CONNECTION_TYPE访问这些对象的其他信息

参考:http://developers.facebook.com/docs/api

演示文档模板 Made by Html5

Marcin Wichary , Ernest DelgadoDirect Guo 开发了一个HTML5 Slider。HTML5 Slider的目的,是为了展示即将到来的桌面和移动浏览器的最新功能。

这个Slider十分精美,于是我就把它精化成了一个Slide模板。

感觉用网页做Slide有一些优势:

  • 便于传播,包括搜索引擎友好,浏览器友好,跨平台等,易于放置于网站
  • 简单,html是一门大众语言,至少比Latex beamer简单多了
  • 精彩,借用JavaScript的丰富特性,可以达到的非常丰富的效果
  • 置于浏览器,便于链接其他资源
  • 互动,Slide可以做到和使用者互动和反馈

W3c已经有了专门写Slide的工具Slidey,不过我还是觉的这个模板更实用一点。

Demo

下载