FriendFeed 使用 MySQL 的经验

一直比较好奇 FriendFeed 网站背后的技术信息。Bret Taylor 的一篇 How FriendFeed uses MySQL to store schema-less data 给出了不少有价值的经验。

概览

FriendFeed 用 MySQL 存储绝大部分数据,超过 2.5 亿条记录。对待网站功能的态度: 让既有功能满足更多用户而不是添加更多的功能。

少添加新功能的好处是数据库 Schema 变化更小。在数据库Sharding 的情况下,如果修改 Schema 结构,必然会影响可用性。此外,几乎不进行复杂一点的关系型查询(比如 不做 JOIN 操作 — 这要用到传统意义上的索引机制 )。FriendFeed 也没有采用什么更新的数据库解决方案(比如 CouchDB ),原因无他,对 MySQL 更谙熟,知道其短长,扬长避短同样能发挥更大的作用。

Schema-Less

这是 FriendFeed 对付数据库的基本策略。只存储基本的对象属性,如果需要修改 Schema 层面的东西,只需要存储新的属性即可。其实就是更加”面向对象”,由基本的「元数据」一步一步衍生到所有的数据对象。

坚持「去索引化」,因为维护索引带来了复杂度,将索引数据存储到到表上。我认为这也是反范式的一个新的思路。在 Bret Taylor 文章的 「Details」 一节中给出了具体的例子。比如要在 user_id 上进行索引,那么创建 index_user_id 表(存储来自所有 Shard 的数据),以 user_id 和 entity_id 为主键即可。这样在修改基表的时候,不需要对其他「索引」表做变动。而删除「索引」也极为方便–删除创建的「索引表」即可。

一致性与原子性

关于一致性可能会有问题,但是可以确定基本原则:

  • 主条目表中存储的属性数据是规范的
  • 索引可能不对应实际的值(这和关系数据库本身的索引有些不同之处)

写入数据的时候按照如下顺序:

  • 写入条目表用 InnoDB 的 ACID 属性来保证
  • 把数据写入到其他 Shard 上的索引表中(猜测可能还是要延迟写)

在读取的时候可能会有短暂的数据不一致性的现象,但很快就能校正。考虑到 FriendFeed 业务的容忍性,这个问题并不严重。

笔记总结

总体感觉,FriendFeed 用了一种非常巧妙的方式进行数据库扩展(多耗费了一点存储空间)。不过这个方式总体上看来,极大减少了手工维护成本。相信 FriendFeed 分享的这个经验能给国内一些需要处理即时信息的站点一些启发。以上只是我的个人理解,如果去看一下 Bret 文章后面的留言,你肯定能得到更多信息(比如为何使用 UUID )。

最后提一下,FriendFeed 用 pickle 做 Python 的对象序列化。当然 Memcached 也是居家旅行必备佳品。

EOF

Linux 下分析性能 nmon 也挺好用

以前在 AIX 下,有的时候祭起 nmon ,比 topas 好用多了(去年 AIX 干脆集成了 nmon )。在 Linux 下,top 命令基本也是摆设。如果遇到某些机器没有安装 SYSSTAT 包, 直接把 nmon 抓回来还是挺方便的,省去了安装的麻烦。

NMON.png

最方便的就是能迅速抽取不同维度的性能概览数据。想想其实一个日常用的工具也有很多创新的,nmon 和 topas 读取的数据源是一样的(Perfstat API),但细节上做得更为到位(看来 Nigel 对用户体验也”略懂”阿)。nmon 抓取的数据很容易输出为 Round-Robin Database (RRD) 格式。便于进一步做数据展现。

AIX 提供的 Perfstat API 很赞,如果自己有兴趣,也可以自己写工具调用数据用以运维数据参考。我以前还写了两个山寨小工具,一个抽取网卡数据吞吐量,一个抽取磁盘 I/O 量。不会 C 也能照猫画虎弄出来。

EOF

GNU Bash, version 4.0

GNU Bash(Bourne-Again SHell) 发布了 4.0 版本。新增加了不少特性。最近大半年基本上很少在终端里了,不过还是要关注一下。

新特性不完全列表
列出几个日常使用有关的:

  • 新的环境变量 $BASHPID 用以返回当前进程 PID。
  • 新的 ‘checkjobs’ 命令检查报告 Job 运行的情况。
  • 如因为缺少资源而创建子进程失败,bash 再尝试几次之后再报错(这个怎么觉得有点傻?)
  • ‘ulimit’ 内建新选项 -b (socket buffer size) 与 -T (number of threads)。
  • 新的 &>> 重定向操作符,追加标准输出与标准错误到指定文件中。

其他新功能多和 Bash 下的 Shell 编程有关,感兴趣的可以仔细看一下说明文件

此外,Readline 有了比较大的功能增强。大家用的最多的命令行历史,现在有了新的 history-size 变量用来设定。

EOF

AntiAdsenseSpam — 协作投放干净一点的 Adsense 广告

很多写 Blog 的朋友还是喜欢投放 Google Adsense 广告的。不过有的时候广告内容可控制程度比较低,牛皮癣广告一下子都跑了出来。假如你的朋友在看你的 Blog ,页面旁边显示一些什么”某某女子医院” 或者是”某某男科” 之类的东西,人家还以为你这人趣味比较低,多少挺恶心人的。

我自己先收集了几个杭州地区的地址(现在人家都能精确定点投放牛皮癣了),附件这个 AntiAdsenseSpam.txt 是暂时的几个不想用的广告地址。在 Adsense 管理页面 Competitive Ad Filter -> AdSense for Content filters 或是 AdSense for Feeds filters 粘贴进去就行了。我总觉得 Competitive Ad Filter 这个名字起得不好,Google 可以考虑修改成 Porn info Filter 之类的,HOho

如果你也在投放 Adsense 广告,不妨把你看到的牛皮癣广告地址发过来(留言或者用 Twitter 给我消息 @Fenng ),我定期加入到AntiAdsenseSpam 文件中,大家统一设置,总体上节省不少人工成本。这也算我的社会化协作实验的一部分。

EOF