博文

目前显示的是 二月, 2011的博文

Two Ideas for Wanmei’s Databases

一、利用filesystem snapshot备份数据假设我们需要一小时备份一次数据库,假设我们的硬盘顺序写入速度平均大约是20MB/s,那么每小时最多也就能写入20*3600=72G的数据。假设我们的备份工具就是cp,那么算上读所需的时间,实际上当数据库的大小大于40G的时候,要想达成一小时一次的备份频率就很吃力了。此时还很重要的一点是,我忽略了这是一个正在使用的数据库,我假设这个数据库使用过程中因业务需要也是会产生IO的。而备份所产生的大量IO会导致数据库处理效率大大降低。看mysql是如何处理这个问题的? flush logs to disk, then backup the binlogs (except the newest one)。我提过,被否了。我今年有空了我一定会自己写个简单的数据库练手完,我一定会实现这个功能的。然后我当时想过用zfs的snapshot解决这个问题,但是基于运营部门人手缺乏,让他们去熟悉freebsd、solaris然后把咱们的一部分系统迁上去那是完全不可能的。前一段时间因为meego的缘故我知道了btrfs,如果它能稳定下来,这是极好的选择,其次就是lvm的snapshot。总之无论用哪一种,都能大大降低硬盘负荷(减少硬盘损坏的概率且降低对服务的影响),并且减少硬盘占用。另外,做版本回退也容易多了。如果服务器更新之后发现有BUG,可以在1分钟内回退到上个版本的代码和数据。二、更改数据序列化规则,做成前后兼容的。假如使用google protocol-buffer这样的东西去序列化数据,就可去掉因为数据库升级而更新表结构所花的时间,从而降低服务中断时间。完美不必去用google的东西,只需要稍微更改下现在的序列化/反序列化规则就可以了。

最近我的live writer不好使了

上次我给我的blog修正了一个bug,是atom publish完之后,http头没有location header。原因很简单,我代码写错了,导致传了一个null pointer给response.addHeader。然后tomcat就silent ignore it了。但是我却查了很久,为啥呢?为啥我明明addHeader了,结果就是没输出呢。修正这个BUG后,轮到wlw报告空指针了:System.NullReferenceException: Object reference not set to an instance of an object.
at WindowsLive.Writer.BlogClient.Clients.AtomClient.NewPost(String blogId, BlogPost post, INewCategoryContext newCategoryContext, Boolean publish, String& etag, XmlDocument& remotePost)
at WindowsLive.Writer.BlogClient.Blog.NewPost(BlogPost post, INewCategoryContext newCategoryContext, Boolean publish)
at WindowsLive.Writer.PostEditor.UpdateWeblogAsyncOperation.DoWork()
at WindowsLive.Writer.CoreServices.AsyncOperation.InternalStart()我一会儿抓包看看。貌似是它在发布成功之后给w3c.org提交完什么东西后报告的。

2011-02-24

最近读MySQL代码读的很爽。主要是vc下编译、调试、查找引用要比emacs啊eclipse之类的好多了。eclipse的CDT要是BUG少一点就好了。读代码主要是为了了解MySQL协议。很多东西非得去看代码,光凭Google搜是得不到答案的。比如刚连接的时候,Server发给Client的那个Hello packet中的thread id有什么用?我目前发现只有在kill的时候有用。按我现在的分析,SAE的mysql proxy发给client的这个值始终为0。还有很有意思的一件事情,有个同事跑过来问我,MySQL怎么处理网络连接的,用的是不是select? 我说“是”,然后他“哦”了一声,很满意的走了。还有人会继续想当然,用的是select啊,难怪不能支持高并发啊。而实际上,MySQL默认是thread-per-connection的模型。用select只是为了同时在多种协议上监听(TCP、Local socket、shared memory等)。 可是,看代码最多回答What,而不能回答Why。代码中偶尔也会有注释写为什么这么设计(比如server和client如何协商auth plugin那段),但是这样的注释太稀少了。所以我在想是不是同时得多去邮件列表里搜搜。

2010-02-21

我在想怎么着把mysql做成load on demand的service,但是我越想越觉得这个别扭。今天我下班很早,他们在加班写PPT。最近本公司的电梯里的液晶屏天天在播“PPT就是生产力”。表误会,那是一句调侃。我早早回来,去楼下拎碗盖饭上来吃。等饭等了很久,那家也卖火锅。我旁边的旁边的一个桌子,吃着吃着炸了。“嘭”的一声响,火苗就冒桌面上来了,然后桌子上的一个人,脸上被喷了一些黑糊糊的东西。那个倒霉的顾客到没说什么,换了个桌子坐下,你说都这样了吧,那老板还振振有词,说那两人故意找事,然后相互就吵起来了。我要了一份西红柿鸡蛋盖饭,后面的师傅给我装了两个饭盒。然后老板打开一看,只见菜不见饭,然后把一盒拿走了,另外给我盛了一盒米饭。然后我回家才发现,另外一盒只有上面一点点是菜。然后晚上继续看cmake,然后看了一会儿google protocol buffer。在上家公司的时候老兔给我们推荐过这个,他觉得这个很好。为啥我记得这么清楚呢,因为开源的东西中,能入众老大法眼的,实在寥寥。baidu搜了一下新闻和介绍,发现都是说它相比于json和xml而言效率如何如何高。我当时被恶心的,就跟以前有个小孩老问我,飞机和火车哪个厉害。好吧,冒出个做通信的,问这个和ASN.1有什么区别。还有更搞笑的,服务器用的是C++,拿着struct直接send,而客户端用的是protocol-buf,然后老报错,然后派人去抓包,然后上网问咋办啊?既然老兔推荐这个,那么我就拿它(G)和我们之前用的那个(W)做个比较吧。W的优势是,序列化和压缩是分开的。我挺反对在序列化的过程中对整数采用变长编码。把问题搞复杂了,其实没带来多么显著的收益(因为后面有压缩)。并且对length这样的字段做变长编码,将会多一次memcpy(除非用sendv避免这个)。而google的确是对字符串的length做了变长编码。google这套东西的劣势在于它是给优秀的程序员用的,光整数就给了这么多种。要不是因为变长编码,会这么麻烦吗?并且它所提供的数据类型太多且太底层。它没有封装vector/map/linked-list这样的东西。虽然线形表和链表以及Set在序列化后都可采用完全相同的表示,所以消息定义中不应该体现出它们之前是有区别的。但是实际用的过程中,我们还是喜欢看着一个复杂的对象不用做任何手动处理直接send出去…

原来secureCRT不支持4096位的RSA?

前几天我把fedora卸了,换成了win7,于是也就不用openssh登录服务器了,改用securecrt。后来发现key agent失效了,我每次登录服务器都需要输入key的password,并且A->B->C这样的Agent转发也失效了。然后我打开secure crt菜单上的"Tools”-> Manage Agent Keys,发现里面是空的,手动添加也加不进去。我以为是我的securecrt有BUG,于是换了新版本,结果还是如此。最后拿了一个2048位的key测试一下,OK了。囧啊!为了这个,我查了一早上!!!

重思No-SQL

NoSQL这个名词在最近两年真是火热。在我看来一个过时的、老掉牙的东西,居然被这么多互联网公司热捧。NoSQL可以有两个解释,Not-Only-SQL或者anti-SQL。如果按非SQL理解,通常指key-value数据库,而在这方面的技术,我想国内没有任何一家公司能超过完美时空。只是它太低调了,它懒得去XX大会上宣讲。而它对key-value数据库的开发使用经验、偏爱、忠心、排他心也是国内大型互联网公司中绝无仅有的。首先我认为,没有必要反对SQL。SQL只是一个语言,它本身没有什么错。在现代的运行环境下,数据库查询所花的时间中解析SQL所花的时间完全可忽略不计。其次,很多人喜欢key-value是因为它高效,但是传统的关系型数据库只要索引设置恰当,增删查改的速度不会慢于key-value数据库。而key-value数据库通过另外建一个表来搞secondary index的方式显然没有关系数据库原生就支持多索引那么高效、一致性那么好。很多人喜欢hibernate,我更不知道hibernate有什么好,干吗不用postgresql这样的原生就支持Object的数据库呢?非要自己在外面搞一层。还有JDBC、ODBC,将数据库访问接口统一化,这个想法挺好,但是如果我是在做一个最终产品而不是在做中间件,那么用什么数据库在一开始就是确定好的,我基本上不可能做到一半的时候去换另一种数据库。因为就算访问接口统一了,不同数据库的SQL语法依然是有很大差异的。无论是SQL还是non-SQL,都可以支持ACID,并且ACID在遇到分布式的时候,都得做退让,要么降低一些效率,要么放弃一些保证。在完美的时候,我一直想干掉那套古老的key-value数据库。主要的考虑是secondary index、编辑工具、备份工具、分布式事务。我当时的想法的是,假如bdb和mysql都能在效率上满足我的要求,而mysql的功能更多、工具更全面那么我肯定用它咯?(不过在完美,bdb和mysql都是非主流)。然后我在保留现有的API不变的情况下把底层的storage换成了postgresql,可惜还广泛的用,我就辞职了。我现在想,这么做最大的问题是,为我的项目凭空增添了很多不必要的复杂性。如果我自己写300行代码就能解决问题,那我肯定不用别人的3000行、30000行的实现了同样功能的开源库。在简洁至上的…

2011-02-19

现在住的这个房子,楼板非常薄,能清晰的听见楼上女人走路的声音,和她儿子哇哇的哭。我现在这个笔记本是3年前买的,我以为电池不行了,充满也只能用1个多小时,后来发现不是的,是因为我装了一个msyql,它一直在后台跑着,但是我往往忘记了它的存在。把它关了之后,使用时间能增长40多分钟。今天把我服务器上的mysql从5.1升级到5.5,把myisam的表尽可能的都改成了innodb,发现它增加了对libaio的依赖。然后最近就是一直在研究sina app engine的mysql服务。我觉得,它这样的结构适合做私有云,不适合做公有云。现在上面跑了10000多个应用,假如某个网站有一个SQL注入漏洞(这个太常见了),那么它要么能让这个mysqld crash掉,要么利用SELECT BENCHMARK(999999999,SHA1(RAND()))这样SQL一直把连接占着,把CPU占着。写了一篇分析放网上去了:http://wenku.baidu.com/view/4a14a028bd64783e09122bb2.html

双网卡,双网关

上次采购了一批2U的机器,每台机器有5个以太网卡,我插了3个。一个是IPMI,还有2个分别接在不同的网络内,一个接内网(192.168.109.2),一个接公网(218.2.18.194)。我之前以为很简单,没什么特别需要注意的,后来发现怎么设置默认网关是个麻烦事。本来我把默认网关设置成了192.168.109.1。路由表就是这样:Destination Gateway Genmask Flags Metric Ref Use Iface
218.2.18.192 0.0.0.0 255.255.255.192 U 0 0 0 eth1
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
0.0.0.0 192.168.1.1 0.0.0.0 UG 0 0 0 eth0后来发现有问题了。假设目的IP是218.2.18.194:从内网来的请求,直接从192.168.1.0的上一级路由转给了目的(218.2.18.194),没有问题。但是从公网来的请求,在218.2.18.194看都是处于SVN_RECV的状态。我猜是因为回去的包走默认网关192.168.1.1出去的,于是出不去。后来在网上搜了一下,改成这样,根据来源判断答复包的下一跳,就好了。ip route flush table 70
ip route add table 70 to 192.168.1.0/24 dev eth0
ip route add table 70 to default via 192.168.1.1 dev eth0ip route flush table 80
ip route add table 80 to 218.2.18.192/26 dev eth1
ip route add table 80 to default via 218.2.18.193 dev eth1ip rule add from 192.168.1.0/24 table 70 priority 70
ip rule add from 218.2.18.192/26 table 8…

原来少配了一个3层vlan接口

我的机器是这么连接的 交换机A(192.168.1.1)----交换机B(192.168.1.62)----服务器1(192.168.1.155)。其中192.168.1.1/26是一个vlan 100,而192.168.1.129/25是一个vlan 200。服务器1在vlan 200中。交换机A和交换机B之间是trun模式连起来,跑2个vlan(100和200)。从交换机A ping服务器1是可以通的。但是从B ping服务器1不通,从服务器1 ping B也不通。但是服务器1 能正常的顺着这条链路从A出去,然后和外面通信。后来我发现,ping不通仅仅是因为交换机B没有配置vlan 200的interface。#configure terminal#interface vlan 200#ip address 192.168.109.254 255.255.255.128#exit就好了。怪哉。其实要能ping通,是为了根据arp信息找到这个机器在哪个端口上。我现在是先ping然后show arp的方式来确定端口信息。看起来是,只有这个交换机的三层vlan接口所在的vlan才有arp信息。

2011-2-11

最近因为工作的原因,继续研究MySQL。从网上下载了最新的源代码后,发现竟然不会编译了,因为5.5已经去除了与autotools相关的部分,在所有平台下均采用cmake编译。哦,我傻了。我也就是前几天给openfetion打包的时候才刚刚开始用cmake。《Mastering CMake》这本书,我目前还没找到电子版下载,而CMake的官方文档(Documentation for CMake 2.8)仅可做参考手册用,不是像《MySQL Reference》那样是一本书,有逻辑,有层次的。对于如何在windows下用cmake编译mysql,国外有人写了一篇图文并茂的博文,http://sleto.wordpress.com/2010/11/26/step-by-step-guide-on-how-to-compile-mysql-5-5-on-microsoft-windows/。但是我编译到sql_locale.cc就编译不过去了。原因在我很明白,之前的博文中解释过这个问题http://www.sunchangming.com/blog/post/3382.form。如果把系统的区域与语言设置里面“非Unicode程序的语言”改成英文然后重启,那么必然是可以编译过去的,这是最稳妥的办法。但是我比较懒。我就挑编译不过去的这个文件,用notepad++打开,加上BOM,然后就OK了。这种做法是有缺陷的,因为已经编译过去的文件未必就真的是正确的(见前面的3382文)。我目前对cmake的了解还不深,仅限于写一些简单的程序。但是毫无疑问,为了写一个hello world,cmake要比autotools简单太多太多了。我甚至建议以后大学生的C/C++ 教材中不要再用tc/vc了,里面的例子直接就是cmake/nmake加命令行版的cl,再配合以notepad++这样的编辑器。工具链越简单,学生越容易明白编译、链接的过程,并且这些都是开源的工具,省的让学生从学校就养成了必用盗版软件的习惯。MySQL社区在废弃autotools的时候,其内部也不是没有反对的声音。其中Alex Esterkin提到,“configure.ac and configure.in are NOT the same thing. If you do not
know the differenc…

试用jailkit

Jailkit大大简化了创建jail需要的操作。# wget 'http://olivier.sessink.nl/jailkit/jailkit-2.13.tar.bz2'# tar -jxf jailkit-2.13.tar.bz2# cd jailkit-2.13#./configure -prefix=/usr --sysconfdir=/etc# make install用起来是很简单的:jk_cp -j /usr/java/jdk1.6.0_23 /data/tomcatroot/jk_cp -j /data/tomcatroot/ /etc/localtimejk_cp -j /data/tomcatroot/ /bin/shjk_cp -j /data/tomcatroot/ /bin/unamejk_cp -j /data/tomcatroot/ /usr/bin/dirnamejk_cp -j /data/tomcatroot/ /usr/bin/ttyjk_cp -j /data/tomcatroot/ /usr/bin/touch然后编译tomcat native:./configure --with-apr=/usr/bin/apr-config --prefix=/tmp/nativemake installjk_cp -j /data/tomcatroot/ /tmp/native/cp -r /data/tomcatroot/tmp/native/* /data/tomcatroot/然后修正文件夹权限chown -R 33:33 conf logs webapps work temp然后挂载特殊的文件系统mount -o bind /dev /data/tomcatroot/devmount -o bind /proc /data/tomcatroot/proc (没有这个会报告找不到libjli.so)然后tomcat的bin目录下创建setenv.sh,设置JAVA_HOME到jre的根目录下。然后启动tomcat,jk_chrootlaunch -u 33 -g 33 -j /data/tomcatroot -x /data/tomcatroot/usr/local/apache-tomcat-7.x.x…