msgbartop
坚持原创
msgbarbottom

10 Jun 09 解决IE在https协议下用php输出文件内容无法下载问题

解决办法:
Header("Content-type: application/octet-stream");
Header("Content-Disposition: inline; filename=aaa.xlsx");
Header("Pragma:public");
用httpwatch查看,内容实际已经输出了只是无法保存,由此断定和Https协议无关,
firefox也可以执行下载,所以断定是IE本身的机制所限制。 
加上第三个header搞定了(前两个是下载文件必须的),跟证书和浏览器都没关系。

04 May 09 FriendFeed结构无关性数据库架构分享

由于用户量激增,导致数据量猛增,此架构方案之前大概有2亿5000条数据。在此架构之前FriendFeed也采用普遍的做法,比如,读写分离的Mysql主从数据库,并对数据进行了sharding,读操作之外用memecache缓存。但是对于新特性的推出,还是有很多不方便。比如更改数据库的结构,或者增删索引,在如此大的数据量和访问量下,经常导致长时间锁表,虽然

他们也用过在一台从库上建立或删除索引,完成后,再交换成新主库。但这种做法,错误率很高,DBA维护成本也很高,并不是一个轻量级的解决方案,并且这些只能应对现有的功能,对于新需求,修改表结构或增删索引,也存在同样的问题,所以开发了这款基于关系数据库的结构无关性架构。下面详细介绍下具体实现:

两类数据,主数据primary data和主数据索引,类似MYISAM,把数据和索引分开存储,只不过不是数据库来维护索引,而是人工维护索引。主数据叫做Entity:由两部分组成,id+Body 。其中id是唯一需要的,一个16位的全局id(UUID),Body是用二进制压缩存储的对象属性集合,这些属性对于应用来说是不透明的,这有点类似文档数据库。这样的Entiy结构,是结构无关性的核心,它通过向entity内增加或删除属性来达到改变数据库结构的目的,从而应对需求变动或新功能。entity body,可以相同也可以不同,根据相应的需求或业务逻辑,用sql语句,通过实体索引表,查询得到entity,之后由业务逻辑去处理得到的这个或这些实体数据。

具体举例:假如要查询某个用户发布的所有内容。先要建立实体表,如下:

CREATE TABLE entities (
added_id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
id BINARY(16) NOT NULL,
updated TIMESTAMP NOT NULL,
body MEDIUMBLOB,
UNIQUE KEY (id),
KEY (updated)
) ENGINE=InnoDB;

由于InnoDB按照主键的顺序存储数据,所以用added_id做主键,这样可以保证新增的数据顺序的写入到硬盘上。id采用binary格式压缩(UUID是无序的)。

Entity示例,采用序列化的格式存储,比如JSON结构或Python dictionaries:

{
“id”: “71f0c4d2291844cca2df6f486e96e37c”,
“user_id”: “f48b0440ca0c4f66991c4d5f6a078eaf”,
“feed_id”: “f48b0440ca0c4f66991c4d5f6a078eaf”,
“title”: “We just launched a new backend system for FriendFeed!”,
“link”: “http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c”,
“published”: 1235697046,
“updated”: 1235697046,
}

需要建立用户实体索引表,如下:

CREATE TABLE index_user_id (
user_id BINARY(16) NOT NULL,
entity_id BINARY(16) NOT NULL UNIQUE,
PRIMARY KEY (user_id, entity_id)
) ENGINE=InnoDB;
代码实现(Python):
先插入一条测试数据:

user_id_index = friendfeed.datastore.Index(
table=”index_user_id”, properties=[”user_id”], shard_on=”user_id”)

datastore = friendfeed.datastore.DataStore(
mysql_shards=[”127.0.0.1:3306″, “127.0.0.1:3307″],
indexes=[user_id_index])

new_entity = {
“id”: binascii.a2b_hex(”71f0c4d2291844cca2df6f486e96e37c”),
“user_id”: binascii.a2b_hex(”f48b0440ca0c4f66991c4d5f6a078eaf”),
“feed_id”: binascii.a2b_hex(”f48b0440ca0c4f66991c4d5f6a078eaf”),
“title”: u”We just launched a new backend system for FriendFeed!”,
“link”: u”http://friendfeed.com/e/71f0c4d2-2918-44cc-a2df-6f486e96e37c”,
“published”: 1235697046,
“updated”: 1235697046,
}
datastore.put(new_entity)

(这里有两个对象Index对象和DataStore对象)
//根据实体id查询
entity = datastore.get(binascii.a2b_hex(”71f0c4d2291844cca2df6f486e96e37c”))
//通过索引查询
entities = user_id_index.get_all(datastore, user_id=binascii.a2b_hex(”f48b0440ca0c4f66991c4d5f6a078eaf”))
通过例子可以看出,对于新增数据,首先要转换成entity表所需的格式,存储一份实体记录,然后对于某类需求,为它新建一张索引表格,再插入索引。对于同一条数据,可能被多个业务逻辑使用的情况,应该相应的为每个需求建立索引表格,当业务变动或不再需要时,修改或删除相应索引表格就行。对于已知entity id的情况可以直接通过DataStore查询。
为了保证索引的正确性,friendfeed设计了一种cleaner机制,它按照时间顺序不间断的检查entities表,增加新索引,删除错误的索引。
此架构优点:基于关系数据库的结构无关性数据库持久化解决方案,可以很好的应对新需求和底层结构的改变,数据和索引分开存储,人工维护索引,增加删除索引不影响其他业务逻辑的访问。并且采用专门程序维护索引正确性(The Cleaner:重点优化用于索引维护的程序)

缺点:

表的数量比较大

对存储空间占用大

一张实体表,对于多业务频繁的写入操作,也许会成为性能瓶颈,应该按应用拆分成多entities表结构。

11 Mar 09 xml2-config not found. Please check your libxml2 installation

wget  ftp://xmlsoft.org/libxml2/libxml2-2.7.3.tar.gz
sudo tar -zxvf libxml2-2.6.28.tar.gz
cd libxml2-2.6.28/
./configure
make
sudo make install

10 Sep 08 硬盘安装FreeBSD

一直想在我的小黑(thinkpad x61)上,装个FreeBSD桌面环境。由于没有内置光驱,尝试了用USB外接光驱启动安装,无法正常读取光盘镜像。但没有放弃,想起了以前用VmWare尝试安装MacOSX的方法,遂,决定一试,后成功,步骤如下:

1.新建虚拟主机,硬盘选择整个磁盘。
2.光驱加载ISO镜像,bios,光驱启动
3.进入安装界面,Custom自定义安装
4.FDISK,分了两个slice,(印象中ibm pc最多支持4个主分区,一个主分区被Windows占用,一个扩展分区,freebsd好像只能装在主分区上,这样一来,4个主分区,算是全了)5.LABEL,当时有点傻,错误的以为只能建一个bsd partition,现在想想,我可以建多个bsd分区,把 /,/usr,/var, /tmp分开,现在都装在了一个bsd分区里,不知道当时咋想的
6.选择包,安装完,重启,再虚拟机里一切正常。重启电脑关键的是这一步,由于当前系统还装了Ubuntu,使用Grub引导。查看了一下手册,进入启动菜单时,按C键,命令行方式。  root (hd0,a) 回车(设备名用的是linux的命名方式,我想这是Ubuntu下的grub)  kernel /boot/loader  boot见到了久违的FreeBSD启动菜单,但稍后的启动中又遇到点小麻烦,就是在虚拟机下找到的设备是ad0,但这里内核找到的是ad4,奇怪,ad能有4吗?无法mount跟分区,只好在提示符下手动加载ufs:至此安装结束,在ports里安装上了xfce,启动进入图形界面一切正常。编译了个Firefox3,汗啊,下回直接找安装包,就我电脑这配置,还编译了3个小时。无线目前还不好使,改天再接着研究,把FreeBSD进行到底。

08 Aug 08 early principles of X Window System

  • Do not add new functionality unless an implementor cannot complete a real application without it.
  • It is as important to decide what a system is not as to decide what it is. Do not serve all the world’s needs; rather, make the system extensible so that additional needs can be met in an upwardly compatible fashion.
  • The only thing worse than generalizing from one example is generalizing from no examples at all.
  • If a problem is not completely understood, it is probably best to provide no solution at all.
  • If you can get 90 percent of the desired effect for 10 percent of the work, use the simpler solution. (See also Worse is better.)
  • Isolate complexity as much as possible.
  • Provide mechanism rather than policy. In particular, place user interface policy in the clients’ hands.
  • 06 Jul 08 FreeBSD 禁止烦人的系统扬声器(beep)

    shell 下,很讨厌speaker的滴滴声,终于找到了解决办法,命令如下:

    kbdcontrol -b off

    13 Jun 08 顿悟测试驱动开发[转载]

    很早就听闻过测试驱动开发,在加入ThoughtWorks之前,在参加ThoughtWorks University之前。但是一直都不得其法,没有登堂入室。这次从印度参加了“有史以来最好的一届”的TWU,顿悟了测试驱动开发(以下简称TDD),算是最大的收获。
    其实TDD很简单,只要你不把它当测试。没错,就这么简单。把TDD当测试来写,你想着的就是如何找出已有代码的错误。想象着的是一副从迷宫中拯救出受困公主的图景。这个时候你就会受困于该如何去测与测什么的问题。假若你不把TDD当测试来写,顿时就会豁然开朗,拨云见日。
    我认为TDD的本质在于,通过写测试来写代码。也就是在每一行产品代码落笔之前,先写一个测试来给这行代码找一个存在的理由。在参加TWU期间,一位名叫 Garret Smith的培训师(Coach)反复和我们强调任何一行代码都要有测试。而且给我们举了一个实际例子:公司的英国办公室的一位同事编写一个软件专门用来对付无测试的代码。方式就是一行行地删除产品代码,如果测试仍然能够通过,这行代码就被删除了。这个例子给我的印象很深刻,因为我觉得它一语道破了天机。TDD其实就这么简单,让你的产品代码不能随便被别人“删除”。
    当用这个视角去实践TDD的时候。测试的名字就会很细节化。具体到描述什么条件时以什么参数调用什么方法时会有什么返回值。回头一想,这些测试对应着是什么呢?其实就是javadoc文档!那么TDD又是什么一个过程呢?就是先写文档再写代码的过程。这么一说来,TDD就很自然了。你先想到一个很简单的功能要实现,有很多的代码要写。从一堆要写的代码中选择出最简单的部分(比如边界的情况)来写。把这部分代码的外部行为想好,写出对应的测试来,并给测试取一个能够当文档使的名字。
    知道了TDD的本质与单元测试的本质之后,再来看一下我认为唯一关键的一个实践,那就是Mock。没有Mock的单元测试就很可能不是单元测试,也许是集成测试,也许是功能测试,总之不是TDD中所需要的那种能够驱动你开发的测试。任何牵涉到两个有行为的类之间交互的测试,都要Mock一个测另外一个,不然就会对象之间的互相影响就会使得测试测不准,无法确知问题所在,也无法让你的测试能够清晰地表达意图。
    也许以前有一些书籍或者人讲过TDD只适合测算法,单元测试要做到黑盒,写Mock要适度之类的话。我目前的认识是这些见解容易让人把单元测试真当测试来看了。其实矫枉过正也无妨,就把TDD测试不当测试吧。总结一下就是TDD是确保你的代码不被别人意外“删掉”的开发方式,单元测试是你产品代码的文档, Mock是编写单元测试时最重要的技术,用于隔离测试对象行为。

    21 May 08 解决DELL Vostro 系列笔记本无法安装系统问题

    部分DELL  Vostro 1000;Inspiron 1501或者131L的笔记本,在安装系统时 有可能出现错误提示”Bad Command”,多半是因为使用盗版光盘导致

    解决办法:

    开机按F2进入BIOS,按方向键选择Advanced,将将USB BIOS Legacy Support选项禁用(改为Disabled)〉F10保存退出即可,安装后再改回来。

    06 May 08 php中使用单元测试的艺术

    关于测试的谬误:
    1.时间消耗大
    2.代码过于复杂,无法测试
    3.只要可以工作,我不需要测试
    4.测试很无聊

    让我们一一打破这些说法:
    1.说测试占用时间,这要看你怎么看待时间的价值,我的答案是,测试会节省你未来修改代码时的时间,如果你是一气呵成,从不修改和重构代码,那单元测试可能对你没用,或者你的整个应用简单之至,一两百行代码就搞定,那单元测试可能对你没用。单元测试,当我们写代码时,我们可以用单元测试来验证单独的类或方法,或对某个需求或一组操作进行单元测试,

    2.对于代码过于复杂,无法测试的答案,这并不是单元测试的错,而是你的错,是你编写了不实用的代码。如果在你写代码的同时,进行了单元测试,就不会发生这种情况,而且这也是一种降低代码间耦合的好方法。
    3.可以工作的代码,和可以工作的测试,是不同事物。测试保证当你添加新功能,重构或做新的修改时,不会影响到程序的完整性,一旦有失败产生,可以迅速定位到错误。对于团队中不熟悉程序代码的新成员,可以一下看到他们所范的错误,帮助他们更好的理解程序和定位错误

    进阶:TDD 测试驱动开发
    面对一个全新的项目,我们经常遇到,无所适从不知从何入手的情况,或者我们根据经验,把需求拆分成独立的小块

    (未完,持续改进中。。。。。)

    04 May 08 unix command daily use

    ifconfig lnc0 inet 192.168.1.99 up

    id –make a note of your user id and groups. Do this with:

    uname — display information about the system

    ps -aux | more

    sudo rsync -avz –delete -e “ssh -i /root/rsync/mirror-rsync-key” sync@61.243.110.80: