memcached完全剖析--1. memcached的基础

翻译一篇技术评论社的文章,是讲memcached的连载。fcicq同学说这个东西很有用,希望大家喜欢。

我是mixi株式会社开发部系统运营组的长野。 日常负责程序的运营。从今天开始,将分几次针对最近在Web应用的可扩展性领域 的热门话题memcached,与我公司开发部研究开发组的前坂一起, 说明其内部结构和使用。

(Read More)

Vi中的正则表达式

毋庸多言,在vim中正则表达式得到了十分广泛的应用。 最常用的 / 和 :s 命令中,正则表达式都是不可或缺的。 下面对vim中的正则表达式的一些难点进行说明。

关于magic

vim中有个magic的设定。设定方法为:

:set magic             " 设置magic
:set nomagic           " 取消magic
:h magic               " 查看帮助

vim毕竟是个编辑器,正则表达式中包含的大量元字符如果原封不动地引用(像perl那样), 势必会给不懂正则表达式的人造成麻烦,比如 /foo(1) 命令, 大多数人都用它来查找foo(1)这个字符串, 但如果按照正则表达式来解释,被查找的对象就成了 foo1 了。

于是,vim就规定,正则表达式的元字符必须用反斜杠进行转义才行, 如上面的例子,如果确实要用正则表达式,就应当写成 /foo(1) 。 但是,像 . * 这种极其常用的元字符,都加上反斜杠就太麻烦了。 而且,众口难调,有些人喜欢用正则表达式,有些人不喜欢用……

为了解决这个问题,vim设置了 magic 这个东西。简单地说, magic就是设置哪些元字符要加反斜杠哪些不用加的。 简单来说:

  • magic(\m):除了 $ . * ^ 之外其他元字符都要加反斜杠。
  • nomagic(\M):除了 $ ^ 之外其他元字符都要加反斜杠。

这个设置也可以在正则表达式中通过 \m \M 开关临时切换。 \m 后面的正则表达式会按照 magic 处理,\M 后面的正则表达式按照 nomagic 处理, 而忽略实际的magic设置。

例如:

/\m.*          # 查找任意字符串
/\M.*          # 查找字符串 .* (点号后面跟个星号)

另外还有更强大的 \v 和 \V。 * \v(即 very magic 之意):任何元字符都不用加反斜杠 * \V(即 very nomagic 之意):任何元字符都必须加反斜杠

例如:

/\v(a.c){3}$   # 查找行尾的abcaccadc
/\m(a.c){3}$   # 查找行尾的(abc){3}
/\M(a.c){3}$   # 查找行尾的(a.c){3}
/\V(a.c){3}$   # 查找任意位置的(a.c){3}$

默认设置是 magic,vim也推荐大家都使用magic的设置,在有特殊需要时,直接通过 \v\m\M\V 即可。

本文下面使用的元字符都是 magic 模式下的。

量词

vim的量词与perl相比一点也不逊色。

vim Perl 意义
* * 0个或多个(匹配优先)
\+ + 1个或多个(匹配优先)
\? 或 \= ? 0个或1个(匹配优先),\?不能在 ? 命令(逆向查找)中使用
\{n,m} {n,m} n个到m个(匹配优先)
\{n,} {n,} 最少n个(匹配优先)
\{,m} {,m} 最多m个(匹配优先)
\{n} {n} 恰好n个
\{-n,m} {n,m}? n个到m个(忽略优先)
\{-} *? 0个或多个(忽略优先)
\{-1,} +? 1个或多个(忽略优先)
\{-,1} ?? 0个或1个(忽略优先)

从上表中可见,vim的忽略优先量词不像perl的 *? +? ?? 那样,而是统一使用 {- 实现的。 这大概跟忽略优先量词不常用有关吧。

环视和固化分组

vim居然还支持环视和固化分组的功能,强大,赞一个 :D 关于环视的解释请参考Yurii的《精通正则表达式》一书吧。

vim Perl 意义
\@= (?= 顺序环视
\@! (?! 顺序否定环视
\@<= (?<= 逆序环视
\@<! (?<! 逆序否定环视
\@> (?> 固化分组
\%(atom\) (?: 非捕获型括号

和perl稍有不同的是,vim中的环视和固化分组的模式的位置与perl不同。 例如,查找紧跟在 foo 之后的 bar,perl将模式写在环视的括号内, 而vim将模式写在环视的元字符之前。

# Perl的写法
/(?<=foo)bar/

# vim的写法
/\(foo\)\@<=bar

参考

vim的帮助文件非常有用,关于正则表达式可以参考以下的内容。

:h pattern
:h magic
:h perl-patterns

(Read More)

delicious新版插件有问题

最近Firefox的行为很奇怪,出现了许多以前一直没见过的现象。回想一下似乎是升级了delicious bookmarks 2.0.58版导致的。

目前发现的问题如下:

  • 历史菜单内的前进、后退按钮失效,工具栏的前进、后退、刷新按钮失效,右键菜单中相应菜单也失效,但用快捷键和鼠标手势可以正常浏览;
  • 不论访问什么网页,地址栏总是显示第一次手工输入的地址,而不会随着当前页面的变化而更新;
  • Ctrl-Tab切换Tab时,松手后屏幕中间显示的切换菜单不会自动消失;
  • 按一下Ctrl-Tab无法在所有Tab中依次切换,只能在当前Tab和上一个Tab之间切换;
  • Ctrl-PageUp和Ctrl-PageDown的功能会反过来,即Ctrl-PageUp变成“下一个Tab”,而Ctrl-PageDown变成“上一个Tab”。

这些现象在禁用delicious bookmarks后消失。但delicious bookmarks又不能不用,于是卸载之后从官方插件站点上重新安装了一次,目前还未发生上述问题。

2008-6-20更新:

今天delicious bookmarks 2.0.64版发布了,更新内容包括:

This release fixes several issues with FF2 and FF3 GA.

  • Fixes for “Organize Bookmarks” performance on FF3
  • Fixes for strange tab behavior in FF2
  • Fixes for sync issues on startup and login
  • Removing status bar icons now frees up space on the status bar
  • Classic mode has been simplified to remove the Delicious menu and work via bookmarklet interface
  • Cleaned up Delicious Bookmarks Options UI

其中第二条就是解决标签切换行为异常的。

(Read More)

项目经理和技术主管的分工

本文是日经BP上的一篇关于项目管理方法的实践的文章。对于短期的Web小型项目, 无论是开发周期、成本,还是技术上都有很大的风险。然而许多人对此认识不足, 导致项目失败,或是产品发布日期一拖再拖、成本大幅上升,或是匆忙发布后漏洞百出。 本文从项目管理的角度说明,即使在小型项目中,项目经理也不能将项目全权委托给技术主管, 而应当建立合适的体制,从几个方面对项目进行控制,这样才能保证项目的顺利进行。

原文在这里

(Read More)

SocialHistory:检查访问者是否访问过某站点

今天delicious上这个名为 SocialHistory 的脚本十分引人注目。 源代码可以在这里下载。 这段js代码的功能就是判断你的用户有没有访问过某个网站。使用方法很简单,例如:

window.onload = function() {
    var sl = new SocialHistory();
    alert(sl.doesVisit("Del.icio.us"));
}

如果用户曾经使用过del.icio.us,那么该函数就会返回真,否则返回假。

其实原理并不复杂,它利用了链接的 a:visited 伪类的属性。首先在页面上生成一个iframe, 并在这个iframe中设置 a 和 a:visited 为不同的样式。然后将网站的链接插入到 iframe 中。 浏览器就会根据用户的访问历史,为访问过的链接设置 a:visited 的样式。 最后再获得链接的最终样式,如果是 a:visited,就可以认为用户访问过该网站了。 具体的实现方式可以参考源代码。

这个脚本主要用于显示社会性书签的图标,可以恰到好处地显示用户所使用的网站。 但我担心,这样的做法是不是有盗取用户隐私之嫌? 虽然这个方法只能判断用户有无访问特定的网站,并不能无限制地得到所有访问历史。

(Read More)

[Perl]One-Liner

哦……Perl真的是太博大精深了。尤其是它的One-Liner程序,每一行都是优美的杰作啊。

下面搜集了一些很有用的One-Liner。大部分资料来自于 这里这里这里

(Read More)

制作安全网站的checklist

fcicq最近在IPA上看到一篇安全相关的文章, 它的最末尾有个checklist,于是催我把它翻译了。前几天比较忙,周末没什么事儿了,就翻译一下吧。

原文的标题是如何让网站更安全。 这里仅翻译文章最后的一个checklist。

2008/4/20更新:fcicq倒是神速啊,马上就把具体的应用策略扔出来了 :D 参考:PHP 实践 Security Checklist

(Read More)

[PBP]代码布局(4)

今天继续翻译代码布局的这一部分。有些很明显的条目,就不翻译了,看看代码就应该明白是什么意思。

(Read More)

[CSS]如何使用margin和padding?

margin和padding的意义相信大家都很清楚,可是在具体应用中, 到底应该使用哪一个,就比较难于判断了。 这篇文章 说得挺清楚的,在这里翻译一下,供参考。

何时应当使用margin

  • 需要在border外侧添加空白时。
  • 空白处不需要背景(色)时。
  • 上下相连的两个盒子之间的空白,需要相互抵消时。如15px + 20px的margin,将得到20px的空白。

何时应当时用padding

  • 需要在border内测添加空白时。
  • 空白处需要背景(色)时。
  • 上下相连的两个盒子之间的空白,希望等于两者之和时。如15px + 20px的padding,将得到35px的空白。

浏览器兼容性问题

在IE 5.x、IE6中,为float的盒子指定margin时,左侧margin可能会变成两倍的宽度。 通过改用padding或指定盒子为display:inline可以解决。

(Read More)

[Perl]认清上下文环境

今天在写代码时遇到一个很奇怪的问题。我写的这样一个函数:

sub parse {
  my $self = shift;
  my $header = shift;
  my $charset = shift;
  
  # 其它处理
  # ...
}

至于如何调用,则是先通过 MIME::Parser 模块解析邮件, 然后调用解析结果中的 MIME::Head::get 函数来获得邮件头的值, 再将其结果传递给 parse 函数:

print $self->parse($head->get("Cc"), "GB2312");

通常都没有问题,在parse函数中,$header取到 Cc 邮件头,而 $charset 取到 “GB2312”; 但当一封邮件中不存在Cc时,就会出现一件怪事: $header 变量竟然取到了第二个参数 “GB2312” 的值!

在 parse 中将 @_ 打出来,发现当Cc邮件头取不到时,第一个参数就“消失”了, 参数列表就变成了 (“GB2312”)。按照常理,参数列表应该是 (undef, “GB2312”)才对啊。

百思不得其解中,偶然看到 MIME::Head::get 的文档中这样说:

  • If a numeric INDEX is given, returns the occurence at that index, or undef if not present:
  • If no INDEX is given, but invoked in a scalar context, then INDEX simply defaults to 0:
  • If no INDEX is given, and invoked in an array context, then all occurences of the field are returned:

上面的调用属于没有 INDEX 的情况,莫非parse函数的参数列表提供了一个列表环境, 导致MIME::Head::get返回了一个数组?

于是强制为它提供一个标量环境,结果就正常地得到了 (undef, “GB2312”)。

print $self->parse(scalar $head->get("Cc"), "GB2312");

看来果然是上下文环境造成的问题。parse函数的第一个参数期待一个常量, 而函数的参数列表却是一个列表环境,再加上MIME::Head::get在列表环境中返回数组, 这样就会导致两种错误:

  • 如果不存在Cc,则参数列表为(“GB2312”),$header = “GB2312”;
  • 如果存在多个Cc,则参数列表为(“Cc-val1”, “Cc-val2”, “Cc-val3”, “GB2312”), $charset=”Cc-val2”。

两种情况都十分荒谬。

对Perl的上下文不熟悉的人,这里可要特别注意啊。

(Read More)