简明 Vim 练级攻略

vim的学习曲线相当的大(参看各种文本编辑器的学习曲线),所以,如果你一开始看到的是一大堆VIM的命令分类,你一定会对这个编辑器失去兴趣的。下面的文章翻译自《Learn Vim Progressively》,我觉得这是给新手最好的VIM的升级教程了,没有列举所有的命令,只是列举了那些最有用的命令。非常不错。

——————————正文开始——————————

你想以最快的速度学习人类史上最好的文本编辑器VIM吗?你先得懂得如何在VIM幸存下来,然后一点一点地学习各种戏法。

Vim the Six Billion Dollar editor

Better, Stronger, Faster.

学习 vim 并且其会成为你最后一个使用的文本编辑器。没有比这个更好的文本编辑器了,非常地难学,但是却不可思议地好用。

我建议下面这四个步骤:

  1. 存活
  2. 感觉良好
  3. 觉得更好,更强,更快
  4. 使用VIM的超能力

当你走完这篇文章,你会成为一个vim的 superstar。

在开始学习以前,我需要给你一些警告:

  • 学习vim在开始时是痛苦的。
  • 需要时间
  • 需要不断地练习,就像你学习一个乐器一样。
  • 不要期望你能在3天内把vim练得比别的编辑器更有效率。
  • 事实上,你需要2周时间的苦练,而不是3天。

第一级 – 存活

  1. 安装 vim
  2. 启动 vim
  3. 什么也别干!请先阅读

当你安装好一个编辑器后,你一定会想在其中输入点什么东西,然后看看这个编辑器是什么样子。但vim不是这样的,请按照下面的命令操作:

  • 启 动Vim后,vim在 Normal 模式下。
  • 让我们进入 Insert 模式,请按下键 i 。(陈皓注:你会看到vim左下角有一个–insert–字样,表示,你可以以插入的方式输入了)
  • 此时,你可以输入文本了,就像你用“记事本”一样。
  • 如果你想返回 Normal 模式,请按 ESC 键。

现在,你知道如何在 Insert 和 Normal 模式下切换了。下面是一些命令,可以让你在 Normal 模式下幸存下来:

  • i → Insert 模式,按 ESC 回到 Normal 模式.
  • x → 删当前光标所在的一个字符。
  • :wq → 存盘 + 退出 (:w 存盘, :q 退出)   (陈皓注::w 后可以跟文件名)
  • dd → 删除当前行,并把删除的行存到剪贴板里
  • p → 粘贴剪贴板

推荐:

  • hjkl (强例推荐使用其移动光标,但不必需) →你也可以使用光标键 (←↓↑→). 注: j 就像下箭头。
  • :help <command> → 显示相关命令的帮助。你也可以就输入 :help 而不跟命令。(陈皓注:退出帮助需要输入:q)

继续阅读

开源跨浏览器 js复制剪切板组件:Zero Clipboard js+swf

开发中经常会用到复制的功能,在 IE 下实现比较简单。但要想做到跨浏览器比较困难了。本文将介绍一个跨浏览器的库类 Zero Clipboard 。它利用 Flash 进行复制,所以只要浏览器装有 Flash 就可以运行,而且比 IE 的 document.execCommand(“Copy”) 更加灵活。

Zero Clipboard 的实现原理
Zero Clipboard 利用 Flash 进行复制,之前有 Clipboard Copy 解决方案,其利用的是一个隐藏的 Flash。但最新的 Flash Player 10 只允许在 Flash 上进行操作才能启动剪贴板。所以 Zero Clipboard 对此进行了改进,用了一个透明的 Flash ,让其漂浮在按钮之上,这样其实点击的不是按钮而是 Flash ,也就可以使用 Flash 的复制功能了。

如何使用 Zero Clipboard
首先下载 Zero Clipboard (http://code.google.com/p/zeroclipboard/),并解压缩。其中需要两个文件:ZeroClipboard.js 和 ZeroClipboard.swf ,将这两个文件放入到你的项目中。
在页面引用JS文件:

<script type="text/javascript"src="ZeroClipboard.js"></script>

然后:

var clip =newZeroClipboard.Client();     //创建对象
clip.setHandCursor(true);                          // 设置鼠标手势为手型
clip.setText(“要复制的文本”);                    // 设置要复制的文本。
clip.glue(“button”);                                     // 注册复制按钮,参数为 id

演示地址:
http://demo.jb51.net/js/ZeroClipboard/index.html


memcached的分布式算法

memcached虽然称为“分布式”缓存服务器,但服务器端并没有“分布式”功能,memcached的分布式,则是完全由客户端程序库实现的。这种分布式是memcached的最大特点。

下面假设memcached服务器有node1~node3三台,应用程序要保存键名为“tokyo”“kanagawa”“chiba”“saitama”“gunma” 的数据。

memcached-0004-01.png

图1 分布式简介:准备

首先向memcached中添加“tokyo”。将“tokyo”传给客户端程序库后,客户端实现的算法就会根据“键”来决定保存数据的memcached服务器。服务器选定后,即命令它保存“tokyo”及其值。

memcached-0004-02.png

图2 分布式简介:添加时

同样,“kanagawa”“chiba”“saitama”“gunma”都是先选择服务器再保存。

接下来获取保存的数据。获取时也要将要获取的键“tokyo”传递给函数库。函数库通过与数据保存时相同的算法,根据“键”选择服务器。使用的算法相同,就能选中与保存时相同的服务器,然后发送get命令。只要数据没有因为某些原因被删除,就能获得保存的值。

memcached-0004-03.png

图3 分布式简介:获取时

这样,将不同的键保存到不同的服务器上,就实现了memcached的分布式。 memcached服务器增多后,键就会分散,即使一台memcached服务器发生故障无法连接,也不会影响其他的缓存,系统依然能继续运行。

接下来介绍第1次 中提到的Perl客户端函数库Cache::Memcached实现的分布式方法。

Cache::Memcached的分布式方法

Perl的memcached客户端函数库Cache::Memcached是 memcached的作者Brad Fitzpatrick的作品,可以说是原装的函数库了。

  • Cache::Memcached – search.cpan.org

该函数库实现了分布式功能,是memcached标准的分布式方法。

根据余数计算分散

Cache::Memcached的分布式方法简单来说,就是“根据服务器台数的余数进行分散”。求得键的整数哈希值,再除以服务器台数,根据其余数来选择服务器。

下面将Cache::Memcached简化成以下的Perl脚本来进行说明。

use strict;
use warnings;
use String::CRC32;

my @nodes = ('node1','node2','node3');
my @keys = ('tokyo', 'kanagawa', 'chiba', 'saitama', 'gunma');

foreach my $key (@keys) {
    my $crc = crc32($key);             # CRC値
    my $mod = $crc % ( $#nodes + 1 );
    my $server = $nodes[ $mod ];       # 根据余数选择服务器
    printf "%s => %s\n", $key, $server;
}

Cache::Memcached在求哈希值时使用了CRC。

  • String::CRC32 – search.cpan.org

首先求得字符串的CRC值,根据该值除以服务器节点数目得到的余数决定服务器。上面的代码执行后输入以下结果:

tokyo       => node2
kanagawa => node3
chiba       => node2
saitama   => node1
gunma     => node1

根据该结果,“tokyo”分散到node2,“kanagawa”分散到node3等。多说一句,当选择的服务器无法连接时,Cache::Memcached会将连接次数添加到键之后,再次计算哈希值并尝试连接。这个动作称为rehash。不希望rehash时可以在生成Cache::Memcached对象时指定“rehash => 0”选项。

根据余数计算分散的缺点

余数计算的方法简单,数据的分散性也相当优秀,但也有其缺点。那就是当添加或移除服务器时,缓存重组的代价相当巨大。添加服务器后,余数就会产生巨变,这样就无法获取与保存时相同的服务器,从而影响缓存的命中率。用Perl写段代码来验证其代价。

use strict;
use warnings;
use String::CRC32;

my @nodes = @ARGV;
my @keys = ('a'..'z');
my %nodes;

foreach my $key ( @keys ) {
    my $hash = crc32($key);
    my $mod = $hash % ( $#nodes + 1 );
    my $server = $nodes[ $mod ];
    push @{ $nodes{ $server } }, $key;
}

foreach my $node ( sort keys %nodes ) {
    printf "%s: %s\n", $node,  join ",", @{ $nodes{$node} };
}

这段Perl脚本演示了将“a”到“z”的键保存到memcached并访问的情况。将其保存为mod.pl并执行。

首先,当服务器只有三台时:

$ mod.pl node1 node2 nod3
node1: a,c,d,e,h,j,n,u,w,x
node2: g,i,k,l,p,r,s,y
node3: b,f,m,o,q,t,v,z

结果如上,node1保存a、c、d、e……,node2保存g、i、k……,每台服务器都保存了8个到10个数据。

接下来增加一台memcached服务器。

$ mod.pl node1 node2 node3 node4
node1: d,f,m,o,t,v
node2: b,i,k,p,r,y
node3: e,g,l,n,u,w
node4: a,c,h,j,q,s,x,z

添加了node4。可见,只有d、i、k、p、r、y命中了。像这样,添加节点后键分散到的服务器会发生巨大变化。26个键中只有六个在访问原来的服务器,其他的全都移到了其他服务器。命中率降低到23%。在Web应用程序中使用memcached时,在添加memcached服务器的瞬间缓存效率会大幅度下降,负载会集中到数据库服务器上,有可能会发生无法提供正常服务的情况。

mixi的Web应用程序运用中也有这个问题,导致无法添加memcached服务器。但由于使用了新的分布式方法,现在可以轻而易举地添加memcached服务器了。这种分布式方法称为 Consistent Hashing。

Consistent Hashing

Consistent Hashing的简单说明

Consistent Hashing如下所示:首先求出memcached服务器(节点)的哈希值,并将其配置到0~232的圆(continuum)上。然后用同样的方法求出存储数据的键的哈希值,并映射到圆上。然后从数据映射到的位置开始顺时针查找,将数据保存到找到的第一个服务器上。如果超过232仍然找不到服务器,就会保存到第一台memcached服务器上。

memcached-0004-04.png

图4 Consistent Hashing:基本原理

从上图的状态中添加一台memcached服务器。余数分布式算法由于保存键的服务器会发生巨大变化而影响缓存的命中率,但Consistent Hashing中,只有在continuum上增加服务器的地点逆时针方向的第一台服务器上的键会受到影响。

memcached-0004-05.png

图5 Consistent Hashing:添加服务器

因此,Consistent Hashing最大限度地抑制了键的重新分布。而且,有的Consistent Hashing的实现方法还采用了虚拟节点的思想。使用一般的hash函数的话,服务器的映射地点的分布非常不均匀。因此,使用虚拟节点的思想,为每个物理节点(服务器)在continuum上分配100~200个点。这样就能抑制分布不均匀,最大限度地减小服务器增减时的缓存重新分布。

通过下文中介绍的使用Consistent Hashing算法的memcached客户端函数库进行测试的结果是,由服务器台数(n)和增加的服务器台数(m)计算增加服务器后的命中率计算公式如下:

(1 – n/(n+m)) * 100

支持Consistent Hashing的函数库

本连载中多次介绍的Cache::Memcached虽然不支持Consistent Hashing,但已有几个客户端函数库支持了这种新的分布式算法。第一个支持Consistent Hashing和虚拟节点的memcached客户端函数库是名为libketama的PHP库,由last.fm开发。

至于Perl客户端,连载的第1次 中介绍过的Cache::Memcached::Fast和Cache::Memcached::libmemcached支持 Consistent Hashing。

两者的接口都与Cache::Memcached几乎相同,如果正在使用Cache::Memcached,那么就可以方便地替换过来。Cache::Memcached::Fast重新实现了libketama,使用Consistent Hashing创建对象时可以指定ketama_points选项。

my $memcached = Cache::Memcached::Fast->new({
    servers => ["192.168.0.1:11211","192.168.0.2:11211"],
    ketama_points => 150
});

另外,Cache::Memcached::libmemcached 是一个使用了Brain Aker开发的C函数库libmemcached的Perl模块。 libmemcached本身支持几种分布式算法,也支持Consistent Hashing,其Perl绑定也支持Consistent Hashing。

总结

本次介绍了memcached的分布式算法,主要有memcached的分布式是由客户端函数库实现,以及高效率地分散数据的Consistent Hashing算法。下次将介绍mixi在memcached应用方面的一些经验,和相关的兼容应用程序。

 

Win7下用XPMode的IE6测试主机WEB程序

WEB开发最纠结的地方恐怕就是各浏览器的兼容性问题了,CSS的,JS的,从IE6到IE9,从Firefox、Chrome到360、遨游……最麻烦的当属IE6了,可偏偏这哥们还是浏览器队伍中的不死小强。

最近我就遇到了这个问题,自己在win7 IE8+Firefox下开发,测试组那边报过IE6兼容性的bug,用IETester,发现IE6崩溃,用VM、VirtualBox虚拟XP,鼓捣半天网络配置搞不定,于是想到Win7下的XPMode,经过一晚上的研究,终于成功,现分享如下:

第一步:安装软件
1、Windows Virtual PC RC简体中文版:
32位:http://download.microsoft.com/download/9/F/D/9FD8E857-EE64-48E2-89EC-EF120913FB2D/Windows6.1-KB958559-x86.msu
64位:http://download.microsoft.com/download/9/F/D/9FD8E857-EE64-48E2-89EC-EF120913FB2D/Windows6.1-KB958559-x64.msu
2、Windows XP Mode RC简体中文版:

http://download.microsoft.com/download/9/2/4/924A5598-3ECF-4E0C-8959-D606EE38BF7B/WindowsXPMode_zh-cn.exe

安装完成后,开始-所有程序中会出现Windows Virtual PC菜单,这样XP Mode就安装完成。

第二步:安装Microsoft Loopback Adapter
Virtual PC和VMWare在网络共享方式是不同的,VMWare是通过模拟网卡实现网络共享的,而Virtual PC是通过在现有网卡上绑定Virtual PC emulated switch服务实现网络共享的。
Microsoft Loopback Adapter (微软回环网卡)类似一个虚拟网卡,能够被安装在一个没有网卡或者要用于测试多个宿主环境的 Windows 上,安装步骤如下:
1.单击开始图标,在智能搜索中输入“hdwwiz”,在搜索结果中鼠标右键单击该程序,使用“以管理员身份运行”方式来启动。
2.根据操作系统向导,选择“安装我手动从列表选择的硬件(高级)”。
3.在硬件列表中,选择“网络适配器”。
4.选择“Microsoft”厂商,并在右边网络适配器列表中选中“Microsoft Loopback Adapter”,下一步按照向导完成安装。

第三步:网络配置
1.virtual pc setting里的networking,第一个选NAT,第二个选microsoft loopback adapter(这个需要先关闭虚拟机);
2.配置microsoft loopback adapter 和 虚拟机系统里的microsoft loopbak网络连接IP为同一网段。例如 microsoft loopback adapter10.1.10.1,虚拟机系统里的microsoft loopbak10.1.10.2,网关同为255.255.255.0;
3、关闭win7和XP中的防火墙及杀毒软件的防火墙;
4、大功告成,XP Mode中的IE6就可以访问Win7中的WEB程序了。

一年之际在于春

刚刚进入2011年的春天,气温还未稳定,各大IT大佬就按捺不住心中的冲动,争先恐后地频频发力,IE9、Firefox4、chrome 10、Myeclipse 9都相继发布了正式版,向业界展示了大战2011的决心。
得益的当然还是我们用户,这几款新软都做出了不小的改进,用起来都不错。
一年之际在于春,我们也要为2011而努力。
不要让生命的每一天留下遗憾!

MongoDB入门(四)–mongodb与java

首先要下载java驱动包,地址:https://github.com/mongodb/mongo-java-driver/downloads,并引入工程。

//引入相关jar包
import com.mongodb.Mongo;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.BasicDBObject;
import com.mongodb.DBObject;
import com.mongodb.DBCursor;

//建立连接
Mongo m = new Mongo( "localhost" , 27017 );
//获取所有数据库列表,貌似空数据库不显示
for (String s : m.getDatabaseNames()) {
     System.out.println(s);
}
//打开mydb库,如没有,则新建一个
DB db = m.getDB( "mydb" );
//获取mydb库所有集合
Set<String> colls = db.getCollectionNames();

//显示所有集合
for (String s : colls) {
    System.out.println(s);
}
//获取一个集合
DBCollection coll = db.getCollection("testCollection")
//内部文档组装数据
BasicDBObject doc = new BasicDBObject();
doc.put("name", "MongoDB");
doc.put("type", "database");
doc.put("count", 1);
BasicDBObject info = new BasicDBObject();
info.put("x", 203);
info.put("y", 102);
doc.put("info", info);
//用集合的insert方式插入
coll.insert(doc);

//查找集合的第一个文档,即第一条记录
DBObject myDoc = coll.findOne();
System.out.println(myDoc);
//查询a:1的记录,相当于字段--值的关系
DBObject dbObject = new BasicDBObject();
dbObject.put("a", "1");
//使用游标来获取记录
DBCursor curs = coll.find(dbObject);
while (curs.hasNext()) {
    System.out.println("query result-------" + curs.next().get("_id").toString());
}

好了,简单先介绍到这儿,相信通过上面几行代码,你已经初步知道JAVA怎么操纵MongoDB了,进阶用法请查看官方手册:

http://www.mongodb.org/display/DOCS/Java+Tutorial

MongoDB入门(三)–命令入门

打开C:/mongodb/bin/mongo.exe,mongodb的自带客户端,输入命令:

show   dbs       显示数据库列表
show  users    显示用户
use   <db name>  切换数据库
show collections   显示当前数据中的集合(相当于关系型数据库中的表)
db.help()        显示数据库操作命令
db.foo.help()          显示操作集合的命令
db.foo.save({a:1})  向当前数据中foo集合中插入一条记录,mongodb以BSON为存储形式,类似于JSON,key-value成对,key一般是String,value可以为任意结构
db.foo.find()           查询当前数据库中的foo集合
db.foo.find({a:1})  查询foo集合中属性是a值是1的记录,相当于select * from foo where a=1
db.foo.find().count()   查询foo集合中记录数,相当于select count(*) from foo

命令就不一一介绍了, 详细的查询语法官网有mongo与sql的对照表:

http://www.mongodb.org/display/DOCS/SQL+to+Mongo+Mapping+Chart

今天就简单介绍到这儿,下一讲说一下mongodb与java的结合,呵。

MongoDB入门(二)—安装

一、下载
官网下载地址:http://www.mongodb.org/downloads,现在最新版本是1.6.5。

二、安装
本文于windows版本为例,Windows下MongoDB无需安装,下载ZIP压缩包,解压到C盘下就OK了,并在建立C:/data/db目录,这是数据文件存放的默认位置,也可以启动mongodb时带参数建立。

三、启动
bin目录下是MongoDB 的一些主程序,服务启动程序是mongod.exe,在命令行下执行:mongod就启动了服务了,也可以mongod  –dbpath  c:/data/db 来启动服务并创建数据存放路径,默认端口是27017,如需指定,则执行mongod –port  1111。

四、安装为windows服务
创建c:/mongodb/logs目录,执行mongod –logpath c:\mongodb\logs\mongodb.log –logappend
–dbpath C:\data\db –directoryperdb –serviceName mongodb –install,这样启动Windows时就会自动启动服务了。

OK,这样就安装完成了。