Archive for the ‘Web Related’ Category

QClub - 豆瓣存储经验分享

Thursday, April 15th, 2010

上周六QClub上听了豆瓣的存储经验分享,豆瓣对问题分而治之的策略应用的很到位,有收获。

目前豆瓣的数据量是:

  • 200G 结构化数据(关系、广播等,特点:记录小、结构固定、经常关系查询)
  • 800G 文本数据(9点的博文)
  • 10T 图片
  • 6T 音乐

对数据库的关注主要是:可靠性(持久化、一致性),可用性,伸缩性,性能,成本 …
而通常一个数据库只能解决两方面的问题。关系型数据库的优势是一致性和可用性,Key-Value数据库的特点是可用性和伸缩性,所以针对不同类型的数据,要采用不同的存储方式

豆瓣使用关系数据库的经验:

  • 使用 InnoDB,并发性能好
  • 使用基本查询,避免 join,在应用层做连接处理
  • 分离大的文本字段
  • 使用 master(rw) - master - slave 结构,读写都使用一个 master,另外一个做 fail-over 的备份,slave 做备份用,双master手动切换,多实例混合部署,没有用 replication,因为存在复制延时。硬盘使用双 SCSI 做 raid0

豆瓣对 MySQL 使用垂直分表,设计时控制好表的宽度,无关数据分开存储(如书、影、音的收藏),单表1亿条数据性能没问题。
使用双master结构便于运维,比如修改表结构时,可以修改备用的 master,然后同步

小文件(图片、博文、音乐)的特点:

  • 主要是 get, set, delete请求,一般不会 update
  • 高可用性,要有 fail-over 机制
  • 占用空间大,10K-5M,增长非常快
  • 因为修改少,对一致性要求低
  • 访问带有高随机性

对小文件的单机文件系统存储系统可以用 reiserfs 3.x (4.x 不能用),远程文件系统可以用 WebDAV,比NFS靠谱,要设计要目录结构,备份可以用 rsync。
多机文件系统存储可以用 MogileFS,瓶颈在 Tracker 上,因为文件的索引信息都记录在一个中心节点的 MySQL 上,适合几十万到一百万的量级,机器故障时数据迁移很慢,因为要拷贝大量小文件。

BeansDB 是豆瓣为解决自己的业务场景开发的一款 key-value 数据库,现已贡献到开源社,此物具备以下特点:

  • hash 路由,无需中心节点,一个简单的路由表即可
  • 数据存储使用 tokyo cabinet
  • 读策略:依次读,直到读到数据为止
  • 利用 HashTree 同步
  • 保证最终一致性,短时间内不保证一致性
  • API接口遵循 memcached 协议

目前豆瓣一年多的时间,部署5台服务器,存储了4T,1.5亿个文件,冗余3份

日志文件存储:

  • 文件大,10M - 10G
  • 重要,不修改,可打包存储
  • 数量少,一天几个
  • 不能阻塞业务逻辑
  • 偶尔使用,可用性要求低

可以使用类GFS分布式存储,豆瓣用的是MooseFS,有FUSE client, Web 界面, 支持 hadoop cluster。日志分析导入数据仓库处理,使用 InfoBright(开源),商业的可以选择KDB+,更多规模可以自行使用 hadoop 的 map-reduce 构建。

另外豆瓣的全文检索用的是 Xapian

设计公益产品常犯的错误

Friday, February 26th, 2010

来自阿育王科技博客的一篇文章:公益产品设计的六个常犯错误

里面说的三个问题非常需要关注:

使用技术来解决文化问题。技术用来解决你在现实中切身体会到的问题,需要深入的参与、体会、理解,从而抽象,才好利用技术解决其中的问题,比如无味的重复、信息的不畅。用户的文化背景、生活习惯是非常重要的因素。

没有理解用户的使用环境。这里指的环境非常现实,文中举例说捐赠给发展中国家的医疗设备有98%在五年内会坏掉,罪魁祸首是电力不稳定。在设计这些医疗设备的发达国家里,这样的问题是不存在的,也自己不会在设计中考虑。再比如,一般的笔记本拿到撒哈拉用,八成会因为进沙子而坏掉,这就需要OLPC那样的一体塑料键盘了。

最后,也是我觉得目前阶段最重要的一点,不顺应的供应链。往往一个产品只能解决 big issue 中的一步,再下一步中没有相应的产品接招,这样第一步中的产品产生的效果就大打折扣了。所以说万事万物都需要一个够大的 ecosystem 才行。

A Web 2.0 Strategy: 10 Tactics for Success

Friday, February 26th, 2010

安猪分享了一个关于 web2.0 运营策略的 slide,总结得蛮切中要点的。

有两句话说中了一个 web 2.0 网站成功的重点

  • simple: can you explain your website on the phone?
  • value: a benefit to the person that make a real difference in their lives

其中有些内容是在今年的工作中要重点提升一下:

  • membership: profiles, friending, groups
  • greet every new member
  • build-in ways to share
  • natural network effects - more value with more “friends”
  • content: outside in, inside out

how to build activity-streaming

Friday, August 7th, 2009

好友动态在各大社交网站中基本上已经是标配了,而且一般都会显示在用户登录之后的默认首页上,这种做法的确方便用户了解网站和自己朋友的一些动态。设计上应该如何实现呢?Google 了一些资料,整理在下面,欢迎有实际经验的朋友指点!

用户看到的可能是三种情况:

  • 我的动态
  • 好友的动态
  • 全站的动态

朋友动态这种信息,根据网站的实际情况需要考虑几个问题:

1、是否只让用户看到最新n条?(海内的最新动态数量是固定的,采用先进先出原则,用户只能看到最新的n条;而UCH则可以每页150条允许用户翻页

2、用户增减好友后,朋友动态是否能够立刻体现出变化?(在海内,我如果在好友名单中删除一个人,好友动态还会有他的信息,只是不新增他的信息而已;而UCH里面,他的信息立刻消失。加一个人为朋友,也是一样的效果。

3、用户能否删除自己产生的动态?

4、阅读者是否可以删除其朋友动态中某一条动态?(在校内用户可以删除某一条朋友动态,在UCH用户可以屏蔽某人或者所有人的某类动态,在海内你只能看不能屏蔽

5、动态是否有阅读权限?

6、动态所指向的信息被修改、删除,动态是否要同步变化?(如果你修改了日志的标题,校内网的动态是不变的,而海内是变化的

最简单的实现方式是将所有事件记录到一张表里:
Event
- id
- user_id
- type
- data
- created_at
这样做比较适合用于显示全站更新,针对用户推送时,缺点明显:用户加好友后会显示出成为好友前的所有动态,删好友后之前的所有动态也看不到了。另外用户不能对活动进行删除,因为每个活动消息只有一份拷贝。
data 中可以用 json 来记录用户的动作,比如:
{photoId:2089, photoName:A trip to the beach}
PS: QQ新版的消息中心,对于同一好友下不同类型的操作都能合并。这时候如果动态表包括有type的字段,就不太好对付了,可以改成:

data中保存用户的操作日志,也就是本贴讨论的重点。我采用的方法是前面有同学提到json方式。如:

{
“blog”:[  {"id":1,"title":"安利台湾25周年庆"} ],
“photo”:[  {"id":1,"title":"51韶关游"} ]
}

其中blog、photo代表某种应用的标识,可以无限添加。只要显示的时候能分析就行。里面的id和title就是内容的属性,结构自定。至于新旧操作怎么合并,我是采取对event表的插入操作进行拦截实现的——我定义会员所有的操作均调用event的插入方法。在拦截函数中,先select该会员的记录。如返回为空,则直接插入新记录。如返回记录,则将待插入数据与原数据进行合并。如待插入数据为:

{
“blog”:[  {"id":2,"title":"我是谁"} ],

“share”:[  {"url":"http://www.tudou.com","title":"土豆网 - 视频 - 播客 - 每个人都是生活的导演"} ]
}

则合并后的content为:

{
“blog”:[  {"id":2,"title":"我是谁"}  {"id":1,"title":"安利台湾25周年庆"}, ],

“photo”:[  {"id":1,"title":"51韶关游"} ],

“share”:[  {"url":"http://www.tudou.com","title":"土豆网 - 视频 - 播客 - 每个人都是生活的导演"} ]
}

然后使用update方法即可。

为解决上面的问题,可以添加一个 EventUser 表,当用户发生动作后,用户的动作写在 Event 表中,给该用户的所有好友发一个消息,记录在 EventUser 表中
EventUser
- id
- event_id
- friend_user_id
- created_at
需要注意的是一定时间内完成的某些动作,对 Event 表应该更新,而不是插入。比如同时加N个好友可以合并到一个 event 中。另外当用户的动作被撤销后,也要考虑对应的 event 如何撤销。比如用户传了一张照片,然后又删掉了,这时如果传照片可以 event 没删掉,用户在动态列表中还会看到,XXX上传了一张照片,但点进去,照片已经不存在了。
优化:
Event 表可以做 mem cache
EventUser 表可以水平切分,分到多张表中,可以定期清除
写 EventUser 表的操作可以抛个消息,异步操作。或者先写到 mem cache 里,到一定条件时再持久化。
references:
http://i.laoer.com/sns-news-feed-design.html
http://www.javaeye.com/topic/176677
ruby on rails plugin:

web 3.0 come

Monday, August 3rd, 2009

微博客越来越火,围绕 twitter 已经成为了一个美丽的生态系统,感觉到 web 3.0 时代要来了。

看了一些相关资料,做了些对比:

Web 1.0 - as an information portal

- be the first to own the content
- divide www info useable directories
- everyone has their personal corner in the cyberspace
- lacks: context, interaction, scalability

Web 2.0 - as a platform

- focus on the power of community to create & validate (UGC, collaboration)
- tagging organization
- setting up “hooks” for future integration (RSS, API)
- lacks: personalization, true portability, interoperability

Web 3.0 - is semantic web

- HTML describes documents, while RDF describles things
- specs: RDF (FOAF, DOAP), GRDDL, W3C, microformats
- instances: Google, Twine, Swicki, Powerset, Wink, Twitter, FOAF, OpenSocial, Beacon, Joost, Netflix, Slingbox, iPhone, Andriod etc

个人总结是:
web1.0 是资源互联(text, video, music, pictures etc)
web2.0 是人互联(social graph, life streaming)
web3.0 是数据互联 (系统可以更智能的理解数据之间的关联和用户表达的含义,从而更准确的给出用户想要的东西)

2 keypoints of semantic web

Wednesday, July 29th, 2009
  1. add semantics to today’s web, rather than create a future web
  2. human first, machine second