Archive for the ‘ running computers ’ Category

开源云计算技术初探

云计算的大潮向我们奔涌而来。而国内的云计算却是乌云一片,搞云计算的多数是骗子,政客,核心学者,偶尔几个技术人有点儿实际研究也敝帚自珍,奉之如圭臬,搞点神秘主义,喜欢被别人崇拜,但又不喜欢与人分享。我是实在看不惯的,而且那些藏着掖着的技术多半不怎么样。这让我想起一个故事,我的很多同学还在航天系统服务,有次聚会他感慨:“我终于知道我们国家为啥要保密了,因为怕被美国人知道我们有多落后。”作为强烈的对比我们看看美帝的云计算,尤其是开源的云计算都已经有了哪些成熟的成果,有什么东西我们是可以轻而易举地借鉴的。

首先我们来看看云计算的三个层次:IaaS,PaaS,SaaS。其中SaaS比较特殊,因为你总不能做出的应用也和别人一模一样吧,除非你是企鹅公司,否则多多少少还是会不太一样的,所以构建完全一样的SaaS是没有意义的,但是可以通过很多有意义的组件快速地搭建你的SaaS,也就是应用。至于各种各样的组件,我想这已经是老生常谈了,毫无新意,也就不说了。那么这里我们就详细说说PaaS和IaaS吧。

IaaS

先说IaaS吧,这个可能对初学者比较好理解,就是可以按照需求弹性地提供计算和存储资源(狭义地讲:内存资源),比如EC2。很长时间除了Amazon提供的服务,我们别无选择。自然很多厂商是不甘心的,其中就有Rackspace,于是乎经过苦心寻找终于锁定了openstack。这个项目最早由NASA发起的,现在已经有很多公司入伙了,包括Citrix Systems, Dell, AMD, Intel, Canonical, SUSE Linux, HP, and Cisco等。发展势头正旺。想看更多的openstack内容请移步这里

openstack的官方网站在这里

当然openstack也有一个严重的问题,就是目前还不是很成熟,主要表现在部署很麻烦。这样就有了devstack,一个专门用于部署的脚本。让部署的工作轻松不少。openstack也有竞争对手的,比较有名的就是Eucalyptus官方网站在这里。不过相比于openstack的火爆,Eucalyptus真是门可罗雀。另外还有两种NimbusOpenNebula也有自己的特色,大家可以在选型时酌情参考。

当所有人都把目光聚集在Linux时,一个被人遗忘的骑士发出了他的吼声。这个贵族就是solaris,没错你没看错就是那个被oracle收购去的的solaris。个人觉得sun在被收购前做得最有意义的事儿就是做了open solaris,最大的遗憾就是没有开放sun studio,也就是sun的编译工具。当大家都热捧linux的时候不要忘了solaris的很多特性正是云计算尤其是多租环境特别需要的。在oracle无耻地绞杀了open solaris后,很多衍生版本应运而生,其中最著名的要算Illumos了,而Node.js背后的公司Joyent更是在其基础上发扬光大,加入了KVM支持,推出了SmartOS。SmartOS集各种武器于一身,在硬件虚拟化,操作系统虚拟化,安全存储和全面调试等方面都有很强的优势。

PaaS

下面讲讲PaaS。额外说一句为啥node会火呢,我发现所有开源的PaaS都支持Node。

Cloud Foundry

从前大家都认为VPS提供服务就可以了,至于怎么做的大可以不必告诉用户。这种思路貌似也延伸到了做PaaS上,当然不得不承认很多用户并不想知道PaaS究竟是什么,也不想知道机理,只不过想用而已。这也说明了目前处在第一阶段,先要满足用户的功能需求。但是对以PaaS为生的企业来说,往往情形就不那么简单了,是将PaaS作为服务还是将其作为平台,在商业模式上可是很不一样的啊。很多人都对服务和平台之间的区别不是很清楚。国内目前的环境也更是如此,比如国内很多微博产品,还是停留在做服务的简单路线上,缺少纵向合作,不能形成有力的产业上下游,虽然口口声声说是开放平台,但开不开放不是自己标榜的,而是开发者说的。这里要说的是,做PaaS,更要做成平台才有未来,要能集成各种第三方服务,想尽一切办法让开发者降低成本,还能让第三方服务提供商获得利益。这里我就不特别细说平台模式的细节了,感兴趣的同学可以买一本《商业模式新生代》自己研究一下。

显然,一大批云计算业界的翘楚认识到这一点了。你看Salesforce旗下的heroku.com对如何做平台的思路非常清晰,路线明确。真是不看不知道,一看吓一跳。恍然间大悟,原来PaaS还可以这么玩。恍然大悟的不止我一个,VMware也在冥思苦想,作为业界虚拟化技术的霸主,怎能对PaaS不闻不问呢。平台构建好以后,后进者的门槛是非常高的,例如没有后进者可以撼动纽约证券交易所的地位,那么怎么开始呢?VMware想到了开源,以争取更多的开发者支持。当然借助VMware强大的资金支持,这个开源的PaaS一定会成为PaaS的一支重要的力量,尤其是构建私有云的环境中。

Cloud Foundry推出的时机非常好,对比较潮流的几个技术有内置的支持,比如Redis,MongoDB,RabbitMQ,MySQL,PostgeSQL。这些东东无异是现代互联网应用的必要组件,很难想象什么应用能够完全避开上述所有产品。同时CF对Java,Ruby,Node.js都有原生支持,对Python和PHP也有合作支持,这些都是它的优势。但从目前来看CF的缺点也是非常明显的。显然VMware对于如何做好社区产品是缺乏经验的,集市不是大教堂,很多做法是不一样的。开源和开放也不完全是同义词,缺少对应用开发者的真正理解是CF的头等硬伤。相比于Heroku的整体体验,CF太繁琐太重型了,那种复杂的企业级的思路用在做PaaS上,开发者买不买账还得时间来检验。不过什么东西都自己搞一套,最后吃亏的总是自己。想当年微软自己搞得版本控制系统,最后还不得放弃掉,集成了第三方的版本控制系统。CF目前有这种趋势,明显对于社区的一些PaaS理念置若罔闻,很多地方非常难用。

难用归难用,CF在设计上还是值得学习的,从VMware选用Ruby作为Cloud Foundry的主要开发语言,我觉得应该作为一个信号。Ruby的确是云时代的语言,这点下面会继续说。有个开源的PaaS可以学习,总归是件非常不错的事儿。Cloud Foundry也是业界的一个起点,其标志性的意义也非常重大。在此之后,很多PaaS项目都开放了源码。

Haibu

很多人看到这个名字都会感到非常陌生。不过它的东家nodejitsu在Node.js圈子里可是举足轻重的一家。Joyent虽然掌控着Node.js,但似乎并没有开源其Node PaaS的想法(或许真的没有PaaS也说不定),而nodejitsu则提供了很好的Node PaaS,不但能在Joyent的云上部署,也可以在EC2,Rackspace之类的地方部署。总的来说,Haibu的设计更加社区化,模块之间独立性更高。有很多组件被广泛用于其他项目。同时也使用了很多其他的开源组件,这点和Cloud Foundry完全不同,后者甚至连消息传递都是自己实现的一套。Haibu的代码不是很多,不用说基本上都是Node代码,所以有心的话,看一遍应该不是很困难。

当然haibu的缺点也是比较明显的。仅就只支持一种语言来说就不那么让人欢心鼓舞了。不过谁知道今后Node.js会不会成为诸如awk这样的经典之作呢?所以只做好一件事情也算符合KISS原则。至于对于其他相应的第三方组件,貌似不用担心,全交给Node.js本身去考虑了。但这些组件能不能有效的云化,能不能结合得好,只有使用者自己心里清楚了。所以说,haibu这种着眼点比较小的项目需要的是喜欢自己折腾的文艺青年,估计普通青年不会太喜欢。

Nodester

这是一个看上去不起眼的项目。但是我却越看越觉得十分有趣。个人感觉他们充分学习了heroku的精华,这点非常重要。可能有的朋友会说,为什么不学Google App Engine,我只能说,在玩PaaS这个领域,Google真的是有点烂泥扶不上墙的感觉。项目维护得非常活跃,也是学习PaaS的好材料。至少国内的几家觊觎PaaS的公司应该好好学学,说句真心话,你们目前做得PaaS或者严格讲叫做伪PaaS真心叫人反胃。个人觉得问人要钱的底线是提供一些比免费更好的产品或者服务,所以有了这些免费的产品应该大幅提高自身的质量,否则死的会很惨。历史上做编译器的故事大家可以自己找找,觉得和今天的一些事情非常类似。

彻底的RESTful设计,虽说只用到REST的第二层(关于哪一层,详见《REST实战》),但不得不说有这种想法的人设计的API就是令人赏心悦目。学习云时代的API设计的话,这个应该是一个不错的范本。PaaS的本质不就是把运维专业化,从而彻底分离,降低开发和运维的依赖性,从而使得运维专业化,甚至独立出来形成专门的公司。此处省略马克思关于分工合作的论述数千字。这种解耦的核心看点就在于接口的设计啊,所以各位看官,一定要好好留意这个REST。我知道这不是他们首创,也不是他们最先鼓吹的,但若是和我们自己的设计相比有优点就该学习嘛。

 

周边开源技术

puppet

这是一项现在很火的技术啦。管理大规模服务器的首选。国内很多同学管理server farm时都很挫的。有人用SecureCRT复制击键,有的人用bash写个循环。如果还这么个方式做云计算的话,恐怕会死得很惨的。云计算将一些原有的软件过程分工细化出来,其存在的意义无非是成本比原来要低。万事归一都在一个钱字上面,说什么功能,说什么服务,说什么扩展性,说白了都是因为成本。问问EC2的使用者为什么要用EC2,说来说去无非就是便宜。原来这种“非研发”成本不被人注意,主要是因为“研发”的浪费太多了,所以处在一个不引人注意的位置。现在到了第二个阶段,大家发现这部分还是挺混乱挺浪费钱的,于是就有了各种各样的方法。

其实在puppet之前还有一个类似的管理工具叫做cfengine,国内用的很少。因为这个东西配置起来比较麻烦,而且像我刚才说的,那时候很多人还没有意识到管理很多机器是个麻烦的事情。这些软件的目的就是让机器管理轻松一点儿,随着这些工具的出现,一些对运维层面深入的思考也不断涌现。其中有几条精华得以在各个工具中有所体现:

  • 故障是常态的,包括各个层面,硬盘的,内存的,整机的,网络的无所不包。
  • 迁移和部署应该是容易的
  • 机器的角色是动态调整的
  • 自动化的,完全自动化的
后来的一些思潮,比如Infrastructure as Code等等都是对这些理念的总结和提高。puppet是Ruby写的,相对于cfengine,性能不高。但这里的场景和Could Foundry一样,真正的问题是我们需要那么高的性能么。cfengine有着非常令人讨厌的语法,尽管其作者的文档能力十分彪悍,甚至还出版过专著,但cfengine依然很难用。puppet在概念上要好很多,据说算是cfengine的直接继承人,所以算是第二代。
统领一群机器不容易,想要高效统领就更困难了,如何用计算机解决一个貌似管理的问题十分有趣,看puppet代码一定要带着这一目的,要思考的是这么设计背后的原因。

chef

这个东西号称是第三代,也就是puppet的下一代,但是目前还不是很成熟。其借鉴了很多puppet成熟的思路,又有很多创新。比如配方(菜谱)的概念,比如配方托管的云化管理思路都是非常值得学习和借鉴的。但目前来看,还处于一个上升期,社区不如puppet那么强大,支持机器的种类也不如puppet那么多。而且puppet也学习很多他的理念,所以今后一段时间二者的相互争辉还是有的看的。

Lustre

哦,这是一个超级文件系统,全世界最牛的500强超级计算机有很多都是用的这个文件系统,开源的,对于学习文件系统还是挺有帮助的。这里我又要免不了八卦一下。这个技术本来是CMU的一个牛人做的,后来成立了公司,借着被sun收购。哎,后面的事儿你们都知道了。不过,当初sun的想法是将其精华融入ZFS,具体融合的怎样,还得进一步考证。不过在sun手里的这些年倒是挺发扬光大的。要知道美国无论是政府还是军方有好多超算中心,sun最愿意搞这些体现技术牛逼的工程了。但贵族以没落,被暴发户收购了。这项技术命运多舛,放在社区手里,我总觉得不放心。大家若是对存储有兴趣,多留意这个就好了,相对来讲资料非常全。

题外话

Ruby和JavaScript是云时代的主流编程语言,Python紧追,PHP应了那句话了“not even close”。heroku将matz叔挖过去的时候,明确放话Ruby是云时代的语言,heroku的整个工程实践也是按照Ruby的最佳工程实践来做的。另外一块那肯定是JVM平台了,云计算肯定会带来JVM平台的另一轮繁荣。至于.NET,本人毫无研究,就不妄加评论了。

网络虚拟化技术下一步会得到很大的发展。原有在多种操作系统下的独有技术将快速融合,比如DTrace,ZFS移植到Linux,KVM移植到Solaris。以DTrace为首的强大工具将会得到非常大发展,成为各种开源产品的标配,以增强在发杂环境下的调试能力。个人认为未来有经验的DTrace工程师会活得非常滋润,有点供不应求,请联想那么多云,尤其是国内的烂云,少不了要调试的人吧。

云计算红红火火,但繁荣的市场上也到处是骗子无赖,踏踏实实做点事情不容易。个人认为踏踏实实学好云计算的相关技术,比肤浅地开发几个手机应用有意思。国外很多大学也开设了相关的课程,大家可以多多关注。

还有些没有说完的话题今后会在补遗中写写。

 

 

包管理器杂谈

前言

今天我想思维跳跃一下,讲讲包管理器,这是一个相当有趣的话题。因为程序员年复一年的写程序,大多是为了娱乐他人,好吧,有的人管那叫创造价值,有的人叫养家糊口。其实没所谓了,本质上来说大部分程序员并不是自己程序的受害者,所以你知道为什么这个世界上有那么多烂程序了吧。让我们回来,聚焦在那些极少的程序员写给自己的程序,除了编译器,版本控制工具以外还有一种非常非常重要,那就是包管理器。

你知道的这个世界上真正了解编译器的人据说坐不满一间教室。我想了解包管理器得人也多不到哪去。首先我们要看看今天要出场讨论的一些候选人。

  • apt 具有超级牛力Debian系猛男
  • yum 为Redhat延寿20年的黄狗
  • homebrew Mac下的青年才俊
  • rubygems Ruby下的魔法大师
  • npm Node.js的超级保镖
  • elpa Emacs的小宝宝

我今天要忽略一些内容,很可能引起某些人的不满。比如像Perl,Python,PHP,Haskell,Lua,R都有一些类似的设施,所以就不一一讨论了。明眼人也许看出来了,六个男嘉宾可以分为两组。一组是系统级别的(system-level),一组是应用级别的(application-level)。维基百科基本上对系统级别的包管理器做了一些介绍,应用级别的仅仅是列举了几个,并没有详细的介绍。但我认为包管理器都是完成类似的工作所以放到一起来讨论。

验证

从单个包的角度来说,一定要确保其来源,否则会轻易受到中间人攻击。所以一般的包管理器都具备简单的验证环节。常见的手法是MD5校验,或者其他Hash校验,homebrew提供的大部分安装包都是用这样的方式校验的。较为严格的应做签名验证,apt和yum都有相应的机制来验证软件包是否来自可信的源。综合来讲Hash的方式加密强度较低,而且严格说来这种校验只应作为下载的完整性检查,并属于授信操作。

依赖性

可以说包管理器解决最为重要的问题就是依赖性关系的问题。我相信在没有yum的RedHat中世纪,大家需要参考n多资料才能正确编译内核。那个时候他们是真心羡慕Debian的。在elpa出现之前,配置一个贴心的emacs环境简直就被视为高手的验证标准。依赖性关系其实并不像看上去的那样容易解决。很多年来make为了解决编译依赖性关系遭受不少的冷嘲热讽。尤其是这种依赖性关系比较松散的时候,看上去就不那么好解决。A依赖于B的3.2.1以上但不超过3.3的版本,这种有时候行有时候不行的条件判断构成了一个非常复杂的逻辑关系。但包管理器必须处理好这个关系,知道哪些依赖条件没有得到满足。依赖性关系的管理是一个生态系统的核心价值。Perl有了CPAN所以带来了一个非常美好的世界,甚至有人说CPAN比Perl的语法更吸引他。依赖性可以让程序员不那么纠结去手工寻找所需要的包,而这个过程可能是相当费时,步骤非常繁琐,而且极容易出错的。对,就好比不使用make工具来编译内核,不是不可能,但阿汤哥会做一些更有利于世界和平的事情。依赖性带来的好处就是开包即用,开袋即食,完全不必担心由于依赖性造成的破损。我猜测由于包管理器提供了一个可信的,可重复的,健壮的依赖性管理,每年程序员节省下来更多时间用于创造新的垃圾代码。

多版本

传统上的包管理器的互斥关系管理有点粗放,apt和yum在处理升级之类的问题时基本就是粗暴地将老的版本替换掉。当然这样设计是比较简单的,可是我们的系统并不美好,经常会有一些遗留软件需要老版本的库。而且从实践的角度来讲这也是一个不太难解决的问题,很多人的机器上都有各种版本的软件,所以后来设计的包管理器就注意了这方面的改进,比如homebrew和rubygems都可以支持同一个软件的多个版本,相互不影响,用户可以随意指定使用软件的版本。多版本是松散型依赖关系必然会出现的特性,也是简单粗暴转向优雅设计的拐点。一个随之而来的问题就是清理不用的版本。这是原来简单粗暴方式比较好解决的一个问题。将原来的是非判断变成了一个寻求最优解的优化问题了。

相对独立的环境

有的时候我们希望严格限制程序的运行环境,但由于包管理器为了便于升级和追新设定了比较宽松的限定条件,使得构建相同的运行环境在相当长的一段时间都是一个非常困难的任务。随着云计算的兴起,基础设施代码化这种思潮逐渐深入实践,诸如bundler这样精巧的工具诞生了。环境配置再也没有手工操作了,而且可以确保所有系统完全一样,简直帅呆了。如果你不觉得帅,那你定没有半夜被狗血电话叫起来去修复线上bug,结果发现这是某个库包与开发者的环境不一样导致的。相对独立的环境在开发者之间也非常重要,任何差异都可能导致惨痛的教训,真金白银的教训啊。相信越来越多的开发者会在云端部署自己的应用,构建相同的环境今后会成为开发者的基本要求的。

发布

有的包管理工具还提供非常便利的构建工具,可以快速构建自己的软件包,并将其发布。开发者可以随时贡献自己的智慧。rubygems就是这样的典型。homebrew可以本地构建一个配方,然后发起pull request,一旦获准别人就能使用了。这个对于未来的开发模式非常重要。Node.js社区的蓬勃发展就是很好的例证。实践证明降低参与者的参与成本特别有利于大家为社区做贡献。

源码还是二进制

我倾向于homebrew的源码编译方式,虽然有点慢,遭到一些诟病,不过我觉得看着代码打补丁,编译是我的个人乐趣。

传输问题

考虑到中国网络的多样性问题,在此我讨论四个方面:网速测试,断点续传,多点传输,下载调度。无疑elpa在这几方面做得奇差无比,简直就是各个方面的反面教材。yum提供插件可以检测最快的镜像源,apt做得也还可以。但都不能同时从多个源下载同一个包,有时候我们还是很需要迅雷或者BT的功能的。断点续传不用多说了,算是一个基本功能。同时开启多少个并发就不能智能点么,非得一个或者n个,就不能自动调节么。

甚至我觉得包管理器应该构建于BT或者电驴之上。

关于源

私自搭建一个源应得到鼓励,应该几乎没有成本地加入到整个全球分布式的系统中,源之间的同步应该也是开箱即用的。这方面做得最好的我认为是全球的公钥分发系统,BT和eDonkey次之。

结语

生态系统无论对一门语言还是对一个系统来说都是非常重要的,人们不会凭着一门语言良好的语法就蜂拥而至的。良好的生态系统为他们提供可靠而丰富的工具链,库包,最佳实践。而位于生态系统核心的正式管理依赖性关系的包管理器。本人杂乱地讲述了对各种包管理器一些思考,希望能“抛砖引砖拍”!

今天学到的几个shell工具

大部分来自 25个ssh技巧,不过我就纳闷了copy-id算是技巧么。
pv 用来查看pipe的速度。
yes 不停地返回某个字符串,其实我觉得这个应该是写Unix程序模仿的第一个对象。
当然了yes和pv搭配起来就能看看某种管道的速度是多少。尤其是远程的情况,比如搭配了ssh。

cstream 可以限制流量的好东西

echo w00t, i’m 733+ | cstream -b1 -t2

另外,tcpdump有个替代品啊tshark,也是很不错的。不知道现在的libpcap,有没有用到mmap这样的技术,有个牛人弄了libcap-mmap在08年的时候就能在10G网络工作,真是牛的一塌糊涂啊。哪天听听ifconfig讲一下这个。

ack 是一种更好的 grep, 完整perl风格的正则支持。

索引,做还是不做,这是个问题

先说个题外话很多人都搞错了mongodb的名字,错误地拼成了mangodb,或者mango。我劝大家不要吃芒果了。从我的网站搜索结果来看拼成mangodb的真的不在少数,这里还要请大家特别注意,尤其是母语不是英语的人。否则要是到英语讨论组提问的话,会引起不必要的误解。
首先要说明的是mongodb的索引和传统的关系型数据库的索引几乎完全一样,所以很多原来的优化手段这里也是适用的,反之也对。那么索引是什么呢?有些人觉得我故弄玄虚,玩数据库的谁人不知索引啊。好吧,那我换一个问法,索引用来干什么?索引是为了在查询的时候更加快速。bingo!这句话是有好多隐含的意思的。查询更加快速,那么是和什么相比呢?肯定是和笨方法相比了。所谓的笨方法就是复杂度为O(n)的线性查找了。这种查找的好处就是不用做任何预处理,而且不需要额外的空间,可以容易地并发。据我所知有两种方法可以降低时间复杂度,一种利用排序的方法,可以将查找有序表的时间复杂度降到O(log(n)),一种使用Hash的方法,用空间换时间,使得时间复杂度讲到O(1)。今天要讨论的主要集中在变无序为有序的做法,也就是大部分索引的机理。
既然涉及到排序,那么就涉及到顺序。所以按照{a:1, b:1}建立的索引,和{b:1, a:1}建立的索引是完全不同的。这种不同的表象是建立索引的速度会用不同,深层次的原因就是排序的准则不同所以顺序就不同,导致的排序复杂程度就不一样。要知道排一几乎有序的数列,和排一个几乎无序的数列可能是完全不同的工作量。还记得所有的算法书上都将到了最好情况和最坏情况吧。所以以一定要考虑你自己的数据究竟是什么样子的,本身有什么性质,建立索引的时候要尽量的符合现有顺序。少折腾,会有很大的获益。至于查询的时候,查询优化器不会计较{a:20, b:30}还是{b:30, a:20}会自动优化的。还要考虑的一个问题就是索引的复用,因为如果建立所以是{a:1,b:1,c:1,d:1},下面这几种都将能复用这个索引{a:10}, {a:10,b:20}, {a:10,b:20,c:90},查询关键字的顺序并不重要,但必须是建立索引的前几个关键字的组合,前一个,前两个,以此类推。
上面讲了第一顺序,还有另外一个顺序。那就是关键字的排序顺序。当然要是你的索引只有一个关键字,就没所谓了。要是有多个关键字,首先要考虑关键字摆放的顺序(上面讲到的),然后就是关键字本身怎么排的问题。是{a:1, b:-1}还是{a:1, b:1}。还是那句话,少折腾就多获益。
不要对不怎么变化的值进行索引。比如性别,有无驾照这种布尔类型的量,对这个索引是没有任何意义的。排不出顺序,也就失去了索引的意义。
有些时候需要返回大量结果,比如返回的结果占到集的一般,这时候,最好就别用索引, 老老实实的用笨方法更快。因为当你要把一本书的前半本都读出来时,索引帮不上什么忙的,反而显得很这腾。所以不见得索引就一定快,要适合自己才是关键。

巧用oplog

by 10gen’s Mathias Stearn
翻译:程显峰

你已经使用了热备(还没有?),也已经知道设置起来非常容易。但可能你还不知道:所有的操作都会存储在一个常规的固定集中,在主控上是local.oplog.$main,在备份上是local.oplog.rs。通过查询这个集,可以深入探究系统的各个方面,甚至可以实现异步触发器。

?View Code JAVASCRIPT
> use local
switched to db local
> db.oplog.$main.find().sort({$natural:-1})
{ "ts" : { "t" : 1288884355000, "i" : 1 }, "op" : "u", "ns" :
"test.foo", "o2" : { "_id" : 1 }, "o" : { "$set" : { "i" : 2 } } }
{ "ts" : { "t" : 1288884349000, "i" : 1 }, "op" : "u", "ns" :
"test.foo", "o2" : { "_id" : 1 }, "o" : { "$set" : { "i" : 1 } } }
{ "ts" : { "t" : 1288884227000, "i" : 1 }, "op" : "i", "ns" :
"test.foo", "o" : { "_id" : 1, "some" : "thing" } }
{ "ts" : { "t" : 1288884225000, "i" : 1 }, "op" : "n", "ns" : "", "o" : { } }

可以看到有两次更新,一次插入,一次空操作(就是最下面的那个)。op可以是下列值:
i – insert
d – delete
u – update
c – command
n – no-op

空操作定期执行确保时效性。如果想过滤掉这些信息,在查询条件加入{op:{$ne:’n’}}就可以了。

很重要的一点就是所有oplog条目都是等幂的。例如上面的两次更新都是由{$inc:{i:1}}调用的,但是最后会转换成$set操作,这样就可以在以后多次重放。

无线折腾折腾记续集

前些天,有人非常无耻地使用我家无线。本来我的无线就是没有密码的,倡导大家共享的精神,怎奈有些人不讲道德,疯狂下载。一气之下挂上了WPA2。噩梦就从此开始了。

老婆的机器一切正常。我的机器不能正常上网了。时断时续,很是怪异。从我多年的抢险经验来说,这种情况是最倒霉的,因为几乎无法判断问题的具体位置。于是就得挨个排除,反正我也乐此不疲,顺便借口和老婆说修东西来升级一下家里的硬件,于是买了150M的新无线路由和USB网卡。

东西拿回来后,开始大张旗鼓的折腾。先是在别处试了一下新的USB网卡,很稳定,但是插在我的linux机器上不能启动。很是郁闷,驱动都找到了,但是接口就是不能up,折腾了半天也不行。换了路由器,依然不行,也不是路由的问题。但是切回不加密的方式就好了,说明可能是wpa2+aes与驱动不兼容,查了些资料,发现这个是不太可能的,因为从2.6.25以后的内核默认支持我的网卡,模块是ath5k。既然内核支持了,那么就说明兼容性不太成问题。

不过各种迹象都表明貌似我的机器有问题。现在怀疑是在原来内核不支持我的网卡时配置的驱动和现在的驱动有部分冲突。并且没有卸载干净,理由就是新买的USB网卡不能工作,在别的Ubuntu上很正常。这个网卡用的Realtek的芯片,包括BT4之类的都可以使用,应该没有兼容性问题的。

考虑到当初切到awesome下,乱搞一气装了wicd,想反正这东西也不稳定(现在来看不稳定也是有原因的),倒不如切换回network manager算了。但是于事无补,问题依旧。至于底层的东西,我最近也没有时间研究太多,还是暂时缓缓吧。另外说几句,原来无知啊,还搞了半天madwifi,其实屁用没有,内核已经内置了。不过貌似国内知道的人不多啊。

目前解决的方案就是全面重装,升10.10,然后老老实实干活,少折腾。可是备份,资料转移又是个问题。怎么才能最平滑地度过呢?

MongoDB中的数据类型

JavaScript中的数只有一种类型64bit的浮点数。但是mongo中有三种分别是32bit的整数,64bit的整数,64bit的浮点数。

在mongo的shell中修改数字的话,很可能会改变数字的类型,这个大家要特别注意。不过估计很少有人会在shell直接修改数据吧。

还有一个问题是64bit整数保存成64bit浮点数,可能会有误差,这个请童鞋们仔细思考,慎重使用。想看看究竟的同学可以自己构造一个大数存进mongo中(当然一定不是在JavaScript中执行的,要不我不就白说了),然后看看结果。

mongo本身还提供其他有趣的类型,注意这些类型并不是所有编程语言都支持的。比如有些语言没有正则表达式类型,有些没有符号类型,有些语言没有日期类型。mongo还支持大部分语言都没有的最大最小类型。另外,你真的可以把JavaScript代码存在mongo里面,而且有一个对应的code类型。不过这么用的时候要慎重,当年blade爷就破口大骂将代码存在数据库里的愚蠢行为,不知道将来有一天他会不会这么做呢?

JavaScript支持的类型实在有限,所以在这里要警告大家,一定不要轻易在shell中修改数据回存。

做事的动力

做事的动力
2010-10-22 23:03:28

几个月前,拿到工作用机的时候,尝试在Win下安装QQ未果。
点击安装文件后,反复收到一个未能在某路径下找到QQ点什么什么点msi的文件的错误。
因为经常挂的IM都能用Pidgin登录,平时也不上Windows,更不常上QQ,就把这个问题放下了 ,不用就是了。

前些天某个午休,妹子偶然要求陪她下棋。
切到Win下面才想起来其实还没装上QQ……

……那就把它装上。
错误再次重现,这次看清楚了,那条提示是“未能在Administrator的Local Setttings/Temp下找到某msi文件”……
原来如此。

因为俺的习惯,拿到一台Win机器后首先禁掉了Administrator……所以我用来登录的帐号不是Administrator,所以那个安装文件也就根本木有向那个目录写东西的权限,所以也自然不会在那个目录下发现所需的文件。

找到了问题的根源,解决起来也就轻而易举了。

装上QQ,又发现QQ游戏被屏蔽了,换了几个端口依旧失败……
不过我有VPN……

行吧,问题都解决了~

不过此时妹子已然午睡去鸟
T. T

好吧,这件事给我的启示是:

某件事没作成,很可能是因为没有真正的动力。

关于Git的一点点忠告

周六的时候做了一个关于Git的讲座,其实我觉得每次讲座过后我自己都有很多进步,会暴露一些自己弄不懂的问题。这些问题可能原来自己并不在意,或者压根就没有研究过,在于别人的交流中这些问题都一股脑的蹦跳出来,让人无所适从。好在我脸皮比较厚,不太在意,这也体现了最近书中所学的“暴露缺点”的武林秘籍。

一个核心问题就是Git做分支太容易了,容易到了足可以影响到开发方式和开发习惯。这里罗嗦两句,说说量变到质变(以下省略一千字)。不过有个具体的例子还是和这个非常像的,那就是科学家用计算机证明了“四色猜想”,以及群的分类理论。啊哈~ 科学家把某种形式的证明变幻做了另外一种形式的计算,只要结果是什么就能证明什么。好吧,可能你有点晕了,简单来说只要你吹气超过20就证明你酒后驾车。

其实SVN做分支也是相对比较容易的,只不过checkout的时候很痛苦。Git的分支功能还是目前为止最高效的,因为git的分支,压根就不copy代码。总是觉得SVN在这点上非常让人难以接受,为什么Tag,分支都是目录呢?!更加可气的是居然还要复制。复制也就算了,居然还不记得从哪里来的。反观Git的分支实现,无非就是新建一个标记,几乎没有什么代价,所以大的项目也可以轻松的分支。Git会记录每个版本的来源,若是一个合并的节点,Git会保留合并的双方。这就是很多用SVN的同学要我演示若是已经合并了某个分支,对其再次合并会怎么样,哈,Git的给出的答案和正常人的想法一样:什么也不做,以为已经处理合并了,相关的冲突也解决了。这也是我为什么喜欢Git的一个原因,没有什么惊奇(最小意外原则),换句话说要是我设计Git,我也会这么做,自少在用户接口方面会这样做的。再次重申,我十分厌恶把Tag,分支和目录混为一谈。

很多人使用版本管理工具的功夫都是欠火候,不是因为他们记不住命令该如何使用,Git的最常用命令有21个,很不好意思,如果有人要我列举的话,我是答不上来的,我得看手册。这个问题有点怪怪的,哈哈,就好比我曾经问过好多天天写C程序的资深开发者:“C语言有多少关键字,请列举一下”,能答上来一半的就算多了。但这并不影响他们对每个关键字的理解。纵使你记住了全部32个关键字,大部分人还是写不出来什么像样儿的C程序。Git的情况也很类似。很多人知道如何分支,但不知道什么时候该分支,都会merge,但是不知道谁合并谁,由哪个角色来做,可能还有人会rebase,但是经常在不该用的时候用,结果就是一团糟。版本控制不是游戏,也不是随性的玩具想怎来就怎么来。我在讲Git的时候一再强调尽可能的分支,主干上尽可能就是合并的结果,尽可能不用rebase。当然这些都是些经验之谈,也没有觉得的准则,具体情况不同还是要具体来看。我只是希望大家不要把Git只是简单的看作一个工具,其实它是改造我们开发模式的一个实践。

我小学的时候老师给我们讲了一个故事(多半估计是杜撰的):一台非常精密的仪器坏掉了,现场的工程师怎么也找不到问题出在哪里了,挣扎了许久之后向一位这个领域的专家求助,专家到现场之后看了看机器,又要了图纸,沉思许久之后,在图纸上画了一条线。现场的工程师果然按照这个指引排除了故障,问专家的报酬是什么,专家回答说1000美元。很多人都觉得特别贵,觉得就画一条线根本不值,专家解释说:画一条线值1美元,知道画在什么地方值999美元。当年我十分单纯,记住这个故事纯粹是因为里面有好多钱,在我儿时那绝对是天文数字。现在想来我们的老师即便是杜撰了这个《读者》风格的故事来激励我们好好学习出人头地,我也十分佩服我的老师,他清楚的预见到了现在的社会故事中的价值观已经成为普世的了。我是想借着这个故事告诉那些整天琢磨奇技淫巧的程序员,知道怎么用Git并不重要,知道如何让Git提升你的项目管理水平才是最有价值的。

openduckbill对应新版pyinotify补丁。

openduckbill是Google开源的一个小文件同步工具。

其依赖于pyinotify提供文件变化监测。

在Ubuntu10.04下面使用easy_install安装的pyinotify的版本是0.8.9
openduckbill 最后一次更新是在2008年对应的是pyinotify0.7,不过这之后pyinotify代码有了变化,需要在openduckbill中进行相应修改。

欲与pyinotify新版本使用openduckbill-1.0.0.tar.gz 需打入以下patch:

diff -ruN openduckbill-1.0.0/src/daemon.py pdir/src/daemon.py
--- openduckbill-1.0.0/src/daemon.py    2008-02-20 19:41:41.000000000 +0800
+++ pdir/src/daemon.py  2010-10-12 11:49:07.863957042 +0800
@@ -1,4 +1,4 @@
-#!/usr/bin/python2.4
+#!/usr/bin/python
 
 # Copyright 2008 Google Inc.
 # Author : Anoop Chandran 
@@ -334,10 +334,10 @@
 
     avail_events = pyinotify.EventsCodes
     # Events to be monitored.
-    eventsmonitored = (avail_events.IN_CLOSE_WRITE | avail_events.IN_CREATE |
-                       avail_events.IN_DELETE | avail_events.IN_MODIFY |
-                       avail_events.IN_MOVED_FROM | avail_events.IN_MOVED_TO |
-                       avail_events.IN_ATTRIB | avail_events.IN_MOVE_SELF)
+    eventsmonitored = (avail_events.OP_FLAGS['IN_CLOSE_WRITE'] | avail_events.OP_FLAGS['IN_CREATE'] |
+                       avail_events.OP_FLAGS['IN_DELETE'] | avail_events.OP_FLAGS['IN_MODIFY'] |
+                       avail_events.OP_FLAGS['IN_MOVED_FROM'] | avail_events.OP_FLAGS['IN_MOVED_TO'] |
+                       avail_events.OP_FLAGS['IN_ATTRIB'] | avail_events.OP_FLAGS['IN_MOVE_SELF'])
     # Start a event watcher
     event_watcher = pyinotify.WatchManager()
     # Create a event processor
diff -ruN openduckbill-1.0.0/src/openduckbilld.py pdir/src/openduckbilld.py
--- openduckbill-1.0.0/src/openduckbilld.py 2008-02-20 19:41:41.000000000 +0800
+++ pdir/src/openduckbilld.py   2010-10-12 11:49:41.927943049 +0800
@@ -1,4 +1,4 @@
-#!/usr/bin/python2.4
+#!/usr/bin/python
 
 # Copyright 2008 Google Inc.
 # Author : Anoop Chandran