Rsync备份镜像详解

| | 评论(0) | 引用通告(0)

(转载自:http://www.kingstor.com/FAQ/Help-Detail-612.htm,这个文章介绍的比较详实,是系统管理员必备的资料了)

介绍

  Rsync(remote sync)是类unix系统下的数据镜像备份工具,支持大多数的类unix系统,无论是Linux、Solaris还是BSD,都经过了的测试,现在也有支持windows下的rsync(cwRsync)也已经测试通过,rsync 是一个节约带宽的备份方案,不像传统的 ftp 会下载所有的文件,不管是否有更新,而 rsync 只下载那些做了更新的数据。它的特性如下:

           ●.可以镜像保存整个目录树和文件系统。
           ●. 可以很容易做到保持原来文件的权限、时间、软硬链接等等。
           ●. 无须特殊权限即可安装。
           ●. 优化的流程,文件传输效率高。
           ●. 支持匿名传输

何时选择rsync

  通过ssh用tar 为文件系统的某部分建立远程副本是非常理想的,而rsync则更适合用来使两台机器之间保持文件系统的同步。一般说来,tar 用于最初的副本,而rsync 则用于获取自最后一份副本以来所发生的更改。这是因为不存在任何目标文件时,tar 可能比rsync 速度更快,但是当两个文件系统之间的差异很小时,rsync 会比tar 快得多

  rsync 下载地址:http://rsync.samba.org
  安装过程:
   tar xvzf rsync-2.6.9.tar.gz
   cd rsync-2.6.7
   ./configure --prefix=/home/rsync
   make
   make install

  参数说明:--prefix 指定rsync要安装的目录.
  至此,安装过程就结束了

rsync配置

/etc/rsyncd.conf   (默认是没有的,可以手工创建)
#全局选项
strict modes =yes                         #是否检查口令文件的权限
port = 873                                #默认端口873,用ssh传输的话,则不需要监听这个端口
log file = /home/rsync/rsyncd.log            #日志记录文件
pid file = /home/rsync/rsyncd.pid    #运行进程的ID写到哪里

#模块选项 (个人认为,不需要这个)
[test]                                    # 这里是认证的模块名,在client端需要指定
max connections = 5                       #客户端最大连接数,默认0(没限制)
uid = livedoorcn                          #指定该模块传输文件时守护进程应该具有的uid
           gid = livedoorcn                #指定该模块传输文件时守护进程应该具有的gid
           path = /home/rsync_test         # 需要做备份的目录
           ignore errors                   # 可以忽略一些无关的IO错误
           read nly = no                  #no客户端可上传文件,yes只读
           write nly = no                 #no客户端可下载文件,yes不能下载
           hosts allow = *                 #充许任何主机连接
           hosts deny = 10.5.3.77          #禁止指定的主机连接
           auth users = livedoorcn         # 认证的用户名,如果没有这行,则表明是匿名
           secrets file = /usr/local/rsync/rsyncd.scrt     # 指定认证口令文件位置

rsync 的启动

rsycn 的启动方式有多种,我们在这里介绍以下几种:
●. 守护进程方式:
/usr/local/rsync/bin/rsync --daemon
●.inetd方式:
在/etc/services中加入:
rsync            873/tcp
然后在/etc/inetd.conf中加入:
rsync    stream   tcp      nowait   root    /usr/local/bin/rsync rsyncd --daemon
●.加入rc.local    推荐用此方式
vi /etc/rc.d/rc.local,在最后添加:
/usr/local/bin/rsync --daemon

验证启动是否成功
ps -aux |grep rsync
root        59120   0.0   0.2   1460    972   ??   Ss     5:20PM    0:00.00   /usr/local/rsync/bin/rsync -daemon

rsync命令的用法

  在配置完rsync服务器后,就可以从客户端发出rsync命令来实现各种同步的操作。(当然,客户端也需要安装编译rsync,只是不需要添加守护进程而已)

  rsync有很多功能选项,下面就对介绍一下常用的选项,命令格式可以为:
  1. rsync [OPTION]... SRC [SRC]... [USER@]HOST:DEST
  2. rsync [OPTION]... [USER@]HOST:SRC DEST
  3. rsync [OPTION]... SRC [SRC]... DEST
  4. rsync [OPTION]... [USER@]HOST::SRC [DEST]
  5. rsync [OPTION]... SRC [SRC]... [USER@]HOST::DEST
  6. rsync [OPTION]... rsync://[USER@]HOST[:PORT]/SRC [DEST]

rsync有六种不同的工作模式:

  1. 拷贝本地文件;当SRC和DES路径信息都不包含有单个冒号":"分隔符时就启动这种工作模式。
  2.使用一个远程shell程序(如rsh、ssh)来实现将本地机器的内容拷贝到远程机器。当DST
路径地址包含单个冒号":"分隔符时启动该模式。
  3.使用一个远程shell程序(如rsh、ssh)来实现将远程机器的内容拷贝到本地机器。当SRC
地址路径包含单个冒号":"分隔符时启动该模式。
  4. 从远程rsync服务器中拷贝文件到本地机。当SRC路径信息包含"::"分隔符时启动该模式。
  5. 从本地机器拷贝文件到远程rsync服务器中。当DST路径信息包含"::"分隔符时启动该模式。
  6. 列远程机的文件列表。这类似于rsync传输,不过只要在命令中省略掉本地机信息即可。

下面实例来说明(ssh传输方式)

  假设服务器端的IP为192.168.2.11,从客户端发出指令

  /home/rsync/bin/rsync -azu --progress /home/test/.root@192.168.2.11:/tmp/test/

  该指令是命令客户端将/home/test/下的所有目录和文件同步(上传)到服务端的/tmp/test/目录下。如果服务端的/tmp目录下没有test目录,则会自动新建。注意/home/test/后面的.,如果没有这个点,服务器端会在/tmp/test/下新建一个test目录,形成/home/test/test。该指令需要输入服务器端root帐号的密码。

  /home/rsync/bin/rsync -azu --progressroot@192.168.2.11:/tmp/test/. /home/test/

  该指令是命令客户端把服务器端/tmp/test/下的所有目录和文件同步(下载)到本地的/home/test/目录下。该指定同样需要输入服务器端root帐号的密码。

/home/rsync/bin/rsync -azu --exclude "logs/" --exclude "*.jpg" --progressroot@192.168.2.11:/tmp/test/. /home/test/

--exclude "logs/" 表示不将服务器端/tmp/test/目录下的/logs目录同步(下载)到本地;--exclude "*.jpg"表示不将服务器端/tmp/test/下的所有jpg文件(包括子目录下的)同步(下载)到本地。其余参数和产生的效果同上。

-a   表示以递归方式传输文件,并保持所有文件属性,等于-rlptgoD
-z    对备份的文件在传输时进行压缩处理
-u   仅仅进行更新,也就是跳过所有已经存在于DST,并且文件时间晚于要备份的文件。(不覆盖比较新的文件)
--progress 显示备份过程(作为服务在后台运行可去掉该参数)

rsync详细参数说明

-v, --verbose 详细模式输出
-q, --quiet 精简输出模式
-c, --checksum 打开校验开关,强制对文件传输进行校验
-a, --archive 归档模式,表示以递归方式传输文件,并保持所有文件属性,等于-rlptgoD
-r, --recursive 对子目录以递归模式处理
-R, --relative 使用相对路径信息

rsync foo/bar/foo.c remote:/tmp/
则在/tmp目录下创建foo.c文件,而如果使用-R参数:

rsync -R foo/bar/foo.c remote:/tmp/
则会创建文件/tmp/foo/bar/foo.c,也就是会保持完全路径信息。

-b, --backup 创建备份,也就是对于目的已经存在有同样的文件名时,将老的文件重新命名为~filename。可以使用--suffix选项来指定不同的备份文件前缀。
--backup-dir 将备份文件(如~filename)存放在在目录下。
-suffix=SUFFIX 定义备份文件前缀
-u, --update 仅仅进行更新,也就是跳过所有已经存在于DST,并且文件时间晚于要备份的文件。(不覆盖更新的文件)
-l, --links 保留软链结
-L, --copy-links 想对待常规文件一样处理软链结
--copy-unsafe-links 仅仅拷贝指向SRC路径目录树以外的链结
--safe-links 忽略指向SRC路径目录树以外的链结
-H, --hard-links 保留硬链结
-p, --perms 保持文件权限
-o, --owner 保持文件属主信息
-g, --group 保持文件属组信息
-D, --devices 保持设备文件信息
-t, --times 保持文件时间信息
-S, --sparse 对稀疏文件进行特殊处理以节省DST的空间
-n, --dry-run现实哪些文件将被传输
-W, --whole-file 拷贝文件,不进行增量检测
-x, --one-file-system 不要跨越文件系统边界
-B, --block-size=SIZE 检验算法使用的块尺寸,默认是700字节
-e, --rsh=COMMAND 指定替代rsh的shell程序
--rsync-path=PATH 指定远程服务器上的rsync命令所在路径信息
-C, --cvs-exclude 使用和CVS一样的方法自动忽略文件,用来排除那些不希望传输的文件
--existing 仅仅更新那些已经存在于DST的文件,而不备份那些新创建的文件
--delete 删除那些DST中SRC没有的文件
--delete-excluded 同样删除接收端那些被该选项指定排除的文件
--delete-after 传输结束以后再删除
--ignore-errors 及时出现IO错误也进行删除
--max-delete=NUM 最多删除NUM个文件
--partial 保留那些因故没有完全传输的文件,以是加快随后的再次传输
--force 强制删除目录,即使不为空
--numeric-ids 不将数字的用户和组ID匹配为用户名和组名
--timeout=TIME IP超时时间,单位为秒
-I, --ignore-times 不跳过那些有同样的时间和长度的文件
--size-only 当决定是否要备份文件时,仅仅察看文件大小而不考虑文件时间
--modify-window=NUM 决定文件是否时间相同时使用的时间戳窗口,默认为0
-T --temp-dir=DIR 在DIR中创建临时文件
--compare-dest=DIR 同样比较DIR中的文件来决定是否需要备份
-P 等同于 --partial
--progress 显示备份过程
-z, --compress 对备份的文件在传输时进行压缩处理
--exclude=PATTERN 指定排除不需要传输的文件模式
--include=PATTERN 指定不排除而需要传输的文件模式
--exclude-from=FILE 排除FILE中指定模式的文件
--include-from=FILE 不排除FILE指定模式匹配的文件
--version 打印版本信息
--address 绑定到特定的地址
--config=FILE 指定其他的配置文件,不使用默认的rsyncd.conf文件
--port=PORT 指定其他的rsync服务端口
--blocking-io 对远程shell使用阻塞IO
-stats 给出某些文件的传输状态
--progress 在传输时现实传输过程
--log-format=formAT 指定日志文件格式
--password-file=FILE 从FILE中得到密码
--bwlimit=KBPS 限制I/O带宽,KBytes per second
-h, --help 显示帮助信息

 

(转载于:http://www.54heimi.com/ 作者:张元英)

01.jpg
02.jpg

03.jpg
04.jpg
05.jpg
06.jpg
07.jpg08.jpg09.jpg10.jpg

转义字符表

| | 评论(0) | 引用通告(0)

特殊字符

字符

十进制

转义字符

"

"

"

&

&

&

<

&#60;

&lt;

>

&#62;

&gt;

不断开空格(non-breaking space)

&#160;

&nbsp;

 
 
 
 

其他字符

字符

十进制

转义字符

字符

十进制

转义字符

字符

十进制

转义字符

?

&#161;

&iexcl;

Á

&#193;

&Aacute;

á

&#225;

&aacute;

&#162;

&cent;

Â

&#194;

&circ;

â

&#226

&acirc;

&#163;

&pound;

Ã

&#195;

&Atilde;

ã

&#227;

&atilde;

¤

&#164;

&curren;

Ä

&#196;

&Auml

ä

&#228;

&auml;

&#165;

&yen;

Å

&#197;

&ring;

å

&#229;

&aring;

|

&#166;

&brvbar;

Æ

&#198;

&AElig;

æ

&#230;

&aelig;

§

&#167;

&sect;

Ç

&#199;

&Ccedil;

ç

&#231;

&ccedil;

¨

&#168;

&uml;

È

&#200;

&Egrave;

è

&#232;

&egrave;

©

&#169;

&copy;

É

&#201;

&Eacute;

é

&#233;

&eacute;

a

&#170;

&ordf;

Ê

&#202;

&Ecirc;

ê

&#234;

&ecirc;

?

&#171;

&laquo;

Ë

&#203;

&Euml;

ë

&#235;

&euml;

?

&#172;

&not;

Ì

&#204;

&Igrave;

ì

&#236;

&igrave;

\x7f

&#173;

&shy;

Í

&#205;

&Iacute;

í

&#237;

&iacute;

®

&#174;

&reg;

Î

&#206;

&Icirc;

î

&#238;

&icirc;

ˉ

&#175;

&macr;

Ï

&#207;

&Iuml;

ï

&#239;

&iuml;

°

&#176;

&deg;

Ð

&#208;

&ETH;

ð

&#240;

&ieth;

±

&#177;

&plusmn;

Ñ

&#209;

&Ntilde;

ñ

&#241;

&ntilde;

2

&#178;

&sup2;

Ò

&#210;

&Ograve;

ò

&#242;

&ograve;

3

&#179;

&sup3;

Ó

&#211;

&Oacute;

ó

&#243;

&oacute;

&#180;

&acute;

Ô

&#212;

&Ocirc;

ô

&#244;

&ocirc;

μ

&#181;

&micro;

Õ

&#213;

&Otilde;

õ

&#245;

&otilde;

?

&#182;

&para;

Ö

&#214;

&Ouml;

ö

&#246;

&ouml;

·

&#183;

&middot;

&times;

&#215;

&times;

÷

&#247;

&divide;

?

&#184;

&cedil;

Ø

&#216;

&Oslash;

ø

&#248;

&oslash;

1

&#185;

&sup1;

Ù

&#217;

&Ugrave;

ù

&#249;

&ugrave;

o

&#186;

&ordm;

Ú

&#218;

&Uacute;

ú

&#250;

&uacute;

?

&#187;

&raquo;

Û

&#219;

&Ucirc;

û

&#251;

&ucirc;

?

&#188;

&frac14;

Ü

&#220;

&Uuml;

ü

&#252;

&uuml;

?

&#189;

&frac12;

Ý

&#221;

&Yacute;

ý

&#253;

&yacute;

?

&#190;

&frac34;

Þ

&#222;

&THORN;

þ

&#254;

&thorn;

?

&#191;

&iquest;

ß

&#223;

&szlig;

ÿ

&#255;

&yuml;

À

&#192;

&Agrave;

à

&#224;

&agrave;

     

要落伍的八种人

| | 评论(1) | 引用通告(0)

(转载自 绝望的MATThttp://hi.baidu.com/mattfox/blog/item/c5c71b9594ffde0e7af48029.html

  不景气的社会,一定会淘汰不争气的人。如何不被淘汰,只要你不在这八种人之内。如果你在其中之内,那就赶紧提升来学习。

1》八小时之外不学习的人。

  胡适先生说:人与人的区别在于八小时之外如何运用。有时间的人不能成功,挤时间的人才能成功。八小时之内决定现在,八小时之外决定未来。什么样的想法什么样的生活。有学习才有选择权,没有知识,要有常识,没有常识,走进教室。不是社会发展太快,是我们思维反应太慢,为什么我们思维太慢,是我们没有跟上学习。人生有两大悲哀:结婚之后不再恋爱,毕业以后不在学习。

  拒绝学习,就是拒绝成长。家长不学习,会被孩子看不起并且和孩子有代沟。夫妻一方不学习,就会有隔阂,学习的人如同长高的树,自然会有高藤来缠。一个人不学习,就会与社会脱节,跟不上时代步伐,人活在21世纪,思想在20世纪,究竟学什么?不是学打工的技术,而是学创业的本领。

  思想观念40%+人际关系40%+专业能力20%=成功从这个公式里找自己的短板,缺啥学啥,社会需要啥你就学啥,而不是学感兴趣的,是学有利于社会有利于自己,有利于成功的。

人要有二亩田,白天是果腹的,晚上是耕种未来的。不学习是21世纪被淘汰的八种人首选第一的人。

2》对新生事物反应迟钝的人。

  任何一个新生事物的诞生都与巨大的商机挂钩。任何一个新生事物的诞生,又都在一片反对怀疑拒绝中悄然来临。21世纪的新生事物一定和趋势有关,而趋势不是用眼睛看的,是要用眼光来判断的。谁抓住趋势谁就抓住了未来。

  不学习就会把推论当结论,用已知判断未来,对新生事物视而不见充耳不闻,最终一定被社会淘汰。

3》靠个人能力单打独斗的人。

  21世纪是英雄退位团队进位的时代,抱团打天下已是趋势,谁拥有人群,谁拥有市场,1+1=2叫数学 1+1=11叫经济学 一根筷子能折断,十双筷子折不断。

4》玻璃心,心理脆弱容易受伤害的人。

  事情发生的大小不重要,而你的想法看法很重要。事情本身不伤害人,而你的想法会伤害你。就象第四章中小故事,老和尚和小和尚下山的故事一样,那个小和尚被自己的想法折磨的死去活来。百折不挠千锤百炼是中国人发明的词。

5》技能单一没有特长的人。

  就象第四章中猫与老鼠的故事一样,猫说:"什么年代了,一种技术能活吗?"据经济学家预测:到2015年中国将有50个行业要淘汰。没有危机是最大危机,满足现状是最大陷阱。人一定要在得意时给自己找退路,不要等失意时再找出路。

6》计较眼前目光短浅的人。

  计较眼前会失去未来,计较小钱会失去大钱。没有远见必寻短见。全世界最好的投资最没有风险的投资就是投资学习,学习可以让人有远见,学习才知道未来的趋势。

7》情商底下的人。

  很多人翻脸比翻书快。古人说:小不忍要乱大谋。脾气来了,福气走了。IQ是智商高可以找一个好工作,EQ是情商高可以有未来。AQ是逆境商可以变成登峰造极的人。

  世界上80%的人见了困难就躲避的人他一事无成。

  世界上15%的人见了困难能迎刃而解的人是成功人。

  世界上5%的人是打着灯笼找困难的人,这种高情商的人将成为登峰造极的人物。

  心理学家总结四种情商的结局:

  1有能力有脾气的人----怀才不与

  2有能力没脾气的人----春风得意

  3没能力有脾气的人----一事无成

  4没能力没脾气的人----贵人相助

8》观念落后知识陈旧的人。

  过期的食品不能吃,过期的观念也不能用。21世纪的成功学,不是你赢过多少人,而是你帮过多少人。学助人成功的本领。

  世界上最大的敌人,不是别人就是自己。

  人成功在短板上人失败在短板上。人成功在缺点上人失败在缺点上。成功是优点的发挥失败是缺点的累计。

  六大劣根断送一生:自以为是,不以为然,倚老卖老,老气横秋,格格不入,每况愈下。

  只要你把人做好,这个世界杯都属于你。

(转贴,原地址不详)

摘要
网络上的IP数据库以纯真版的最为流行,LumaQQ也采用了纯真版IP数据库做为IP查询功能的基础。不过关于其格式的文档却非常之少,后来终于在网上找到了一份文档,得以了解其内幕,不过那份文档寥寥数语,也是颇为耐心才读明白。在这里我重写一份,以此做为LumaQQ开发者文档的一部分,我想还是必要的。本文详细介绍了纯真IP数据库的格式,并且给出了一些Demo以供参考。

Luma, 清华大学
修改日期: 2005/01/14

Note: 在此感谢纯真IP数据库作者金狐和那唯一一份文档的作者。

修改历史:
2005-01-14 修改了原来一些表达不清和错误的地方

 


自从有了IP数据库这种东西,QQ外挂的显示IP功能也随之而生,本人见识颇窄,是否还有其他应用不得而知,不过,IP数据库确实是个不错的东西。如今网络上最流行的IP数据库我想应该是纯真版的(说错了也不要扁我),迄今为止其IP记录条数已经接近30000,对于有些IP甚至能精确到楼层,不亦快哉。2004年4、5月间,正逢LumaQQ破土动工,为了加上这个人人都喜欢,但是好像人人都不知道为什么喜欢的显IP功能,我也采用了纯真版IP数据库,它的优点是记录多,查询速度快,它只用一个文件QQWry.dat就包含了所有记录,方便嵌入到其他程序中,也方便升级。

基本结构

QQWry.dat文件在结构上分为3块:文件头,记录区,索引区。一般我们要查找IP时,先在索引区查找记录偏移,然后再到记录区读出信息。由于记录区的记录是不定长的,所以直接在记录区中搜索是不可能的。由于记录数比较多,如果我们遍历索引区也会是有点慢的,一般来说,我们可以用二分查找法搜索索引区,其速度比遍历索引区快若干数量级。图1是QQWry.dat的文件结构图。



200572310278433.gif图1. QQWry.dat文件结构

要注意的是,QQWry.dat里面全部采用了little-endian字节序

一. 了解文件头

QQWry.dat的文件头只有8个字节,其结构非常简单,首四个字节是第一条索引的绝对偏移,后四个字节是最后一条索引的绝对偏移。

二. 了解记录区

每条IP记录都由国家和地区名组成,国家地区在这里并不是太确切,因为可能会查出来"清华大学计算机系"之类的,这里清华大学就成了国家名了,所以这个国家地区名和IP数据库制作的时候有关系。所以记录的格式有点像QName,有一个全局部分和局部部分组成,我们这里还是沿用国家名和地区名的说法。

于是我们想象着一条记录的格式应该是: [IP地址][国家名][地区名],当然,这个没有什么问题,但是这只是最简单的情况。很显然,国家名和地区名可能会有很多的重复,如果每条记录都保存一个完整的名称拷贝是非常不理想的,所以我们就需要重定向以节省空间。所以为了得到一个国家名或者地区名,我们就有了两个可能:第一就是直接的字符串表示的国家名,第二就是一个4字节的结构,第一个字节表明了重定向的模式,后面3个字节是国家名或者地区名的实际偏移位置。对于国家名来说,情况还可能更复杂些,因为这样的重定向最多可能有两次。

那么什么是重定向模式?根据上面所说,一条记录的格式是[IP地址][国家记录][地区记录],如果国家记录是重定向的话,那么地区记录是有可能没有的,于是就有了两种情况,我管他叫做模式1和模式2。我们对这些格式的情况举图说明:



200572310278926.gif图2. IP记录的最简单形式

图2表示了最简单的IP记录格式,我想没有什么可以解释的



200572310278938.gif图3. 重定向模式1

图3演示了重定向模式1的情况。我们看到在模式1的情况下,地区记录也跟着国家记录走了,在IP地址之后只剩下了国家记录的4字节,后面3个字节构成了一个指针,指向了实际的国家名,然后又跟着地址名。模式1的标识字节是0x01。



4.gif图4. 重定向模式2

图4演示了重定向模式2的情况。我们看到了在模式2的情况下(其标识字节是0x02),地区记录没有跟着国家记录走,因此在国家记录之后4个字节之后还是有地区记录。我想你已经明白了模式1和模式2的区别,即:模式1的国家记录后面不会再有地区记录,模式2的国家记录后会有地区记录。下面我们来看一下更复杂的情况。



5.gif图5. 混和情况1

图5演示了当国家记录为模式1的时候可能出现的更复杂情况,在这种情况下,重定向指向的位置仍然是个重定向,不过第二次重定向为模式2。大家不用担心,没有模式3了,这个重定向也最多只有两次,并且如果发生了第二次重定向,则其一定为模式2,而且这种情况只会发生在国家记录上,对于地区记录,模式1 和模式2是一样的,地区记录也不会发生2次重定向。不过,这个图还可以更复杂,如图7:



6.gif图6. 混和情况2

图6是模式1下最复杂的混和情况,不过我想应该也很好理解,只不过地区记录也来重定向而已,有一点我要提醒你,如果重定向的地址是0,则表示未知的地区名。

所以我们总结如下:一条IP记录由[IP地址][国家记录][地区记录]组成,对于国家记录,可以有三种表示方式:字符串形式,重定向模式1和重定向模式2。对于地区记录,可以有两种表示方式:字符串形式和重定向,另外有一条规则:重定向模式1的国家记录后不能跟地区记录。按照这个总结,在这些方式中合理组合,就构成了IP记录的所有可能情况。

设计的理由

在我们继续去了解索引区的结构之前,我们先来了解一下为何记录区的结构要如此设计。我想你可能想到了答案:字符串重用。没错,在这种结构下,对于一个国家名和地区名,我只需要保存其一次就可以了。我们举例说明,为了表示方便,我们用小写字母代表IP记录,C表示国家名,A表示地区名:

  1. 有两条记录a(C1, A1), b(C2, A2),如果C1 = C2, A1 = A2,那么我们就可以使用图3显示的结构来实现重用
  2. 有三条记录a(C1, A1), b(C2, A2), c(C3, A3),如果C1 = C2, A2 = A3,现在我们想存储记录b,那么我们可以用图6的结构来实现重用
  3. 有两条记录a(C1, A1), b(C2, A2),如果C1 = C2,现在我们想存储记录b,那么我们可以采用模式2表示C2,用字符串表示A2

你可以举出更多的情况,你也会发现在这种结构下,不同的字符串只需要存储一次。

了解索引区

在"了解文件头"部分,我们说明了文件头实际上是两个指针,分别指向了第一条索引和最后一条索引的绝对偏移。如图8所示:



8.gif图8. 文件头指向索引区图示

实在是很简单,不是吗?从文件头你就可以定位到索引区,然后你就可以开始搜索IP了!每条索引长度为7个字节,前4个字节是起始IP地址,后三个字节就指向了IP记录。这里有些概念需要说明一下,什么是起始IP,那么有没有结束IP? 假设有这么一条记录:166.111.0.0 - 166.111.255.255,那么166.111.0.0就是起始IP,166.111.255.255就是结束IP,结束IP就是IP记录中的那头 4个字节,这下你应该就清楚了吧。于是乎,每条索引配合一条记录,构成了一个IP范围,如果你要查找166.111.138.138所在的位置,你就会发现166.111.138.138落在了166.111.0.0 - 166.111.255.255 这个范围内,那么你就可以顺着这条索引去读取国家和地区名了。那么我们给出一个最详细的图解吧:



9.gif图9. 文件详细结构

现在一切都清楚了是不是?也许还有一点你不清楚,QQWry.dat的版本信息存在哪里呢?答案是:最后一条IP记录实际上就是版本信息,最后一条记录显示出来就是这样:255.255.255.0 255.255.255.255 纯真网络 2004年6月25日IP数据。OK,到现在你应该全部清楚了。

Demo

下一步:我给出一个读取IP记录的程序片断,此片断摘录自LumaQQ源文件edu.tsinghua.lumaqq.IPSeeker.java,如果你有兴趣,可以下载源代码详细看看。

	/**
* 给定一个ip国家地区记录的偏移,返回一个IPLocation结构
* @param offset 国家记录的起始偏移
* @return IPLocation对象
*/
private IPLocation getIPLocation(long offset) {
try {
// 跳过4字节ip
ipFile.seek(offset + 4);
// 读取第一个字节判断是否标志字节
byte b = ipFile.readByte();
if(b == REDIRECT_MODE_1) {
// 读取国家偏移
long countryOffset = readLong3();
// 跳转至偏移处
ipFile.seek(countryOffset);
// 再检查一次标志字节,因为这个时候这个地方仍然可能是个重定向
b = ipFile.readByte();
if(b == REDIRECT_MODE_2) {
loc.country = readString(readLong3());
ipFile.seek(countryOffset + 4);
} else
loc.country = readString(countryOffset);
// 读取地区标志
loc.area = readArea(ipFile.getFilePointer());
} else if(b == REDIRECT_MODE_2) {
loc.country = readString(readLong3());
loc.area = readArea(offset + 8);
} else {
loc.country = readString(ipFile.getFilePointer() - 1);
loc.area = readArea(ipFile.getFilePointer());
}
return loc;
} catch (IOException e) {
return null;
}
}

/**
* 从offset偏移开始解析后面的字节,读出一个地区名
* @param offset 地区记录的起始偏移
* @return 地区名字符串
* @throws IOException 地区名字符串
*/
private String readArea(long offset) throws IOException {
ipFile.seek(offset);
byte b = ipFile.readByte();
if(b == REDIRECT_MODE_1 || b == REDIRECT_MODE_2) {
long areaOffset = readLong3(offset + 1);
if(areaOffset == 0)
return LumaQQ.getString("unknown.area");
else
return readString(areaOffset);
} else
return readString(offset);
}

/**
* 从offset位置读取3个字节为一个long,因为java为big-endian格式,所以没办法
* 用了这么一个函数来做转换
* @param offset 整数的起始偏移
* @return 读取的long值,返回-1表示读取文件失败
*/
private long readLong3(long offset) {
long ret = 0;
try {
ipFile.seek(offset);
ipFile.readFully(b3);
ret |= (b3[0] & 0xFF);
ret |= ((b3[1] << 8) & 0xFF00);
ret |= ((b3[2] << 16) & 0xFF0000);
return ret;
} catch (IOException e) {
return -1;
}
}

/**
* 从当前位置读取3个字节转换成long
* @return 读取的long值,返回-1表示读取文件失败
*/
private long readLong3() {
long ret = 0;
try {
ipFile.readFully(b3);
ret |= (b3[0] & 0xFF);
ret |= ((b3[1] << 8) & 0xFF00);
ret |= ((b3[2] << 16) & 0xFF0000);
return ret;
} catch (IOException e) {
return -1;
}
}

/**
* 从offset偏移处读取一个以0结束的字符串
* @param offset 字符串起始偏移
* @return 读取的字符串,出错返回空字符串
*/
private String readString(long offset) {
try {
ipFile.seek(offset);
int i;
for(i = 0, buf[i] = ipFile.readByte(); buf[i] != 0; buf[++i] = ipFile.readByte());
if(i != 0)
return Utils.getString(buf, 0, i, "GBK");
} catch (IOException e) {
log.error(e.getMessage());
}
return "";
}

代码并不复杂,getIPLocation是主要方法,它检查国家记录格式,并针对字符串形式,模式1,模式2采用不同的代码,readArea则相对简单,因为只有字符串和重定向两种情况需要处理。

总结

纯真IP数据库的结构使得查找IP简单迅速,不过你想要编辑它却是比较麻烦的,我想应该需要专门的工具来生成QQWry.dat文件,由于其文件格式的限制,你要直接添加IP记录就不容易了。不过,能查到IP已经很开心了,希望纯真记录越来越多~。

MYSQL的全文检索

| | 评论(0) | 引用通告(0)

(转摘自:http://www.php5.idv.tw/documents/mysql4tw/06-8.html ,虽然翻译的有点拗口,但仍不失重要的参考资料)

到 3.23.23 时,MySQL 开始支持全文索引和搜索。全文索引在 MySQL 中是一个 FULLTEXT 类型索引。FULLTEXT 索引用于 MyISAM 表,可以在 CREATE TABLE 时或之后使用 ALTER TABLECREATE INDEXCHARVARCHARTEXT 列上创建。对于大的数据库,将数据装载到一个没有 FULLTEXT 索引的表中,然后再使用 ALTER TABLE (或 CREATE INDEX) 创建索引,这将是非常快的。将数据装载到一个已经有 FULLTEXT 索引的表中,将是非常慢的。

全文搜索通过 MATCH() 函数完成。

mysql> CREATE TABLE articles (
-> id INT UNSIGNED AUTO_INCREMENT NOT NULL PRIMARY KEY,
-> title VARCHAR(200),
-> body TEXT,
-> FULLTEXT (title,body)
-> );
Query OK, 0 rows affected (0.00 sec)

mysql> INSERT INTO articles VALUES
-> (NULL,'MySQL Tutorial', 'DBMS stands for DataBase ...'),
-> (NULL,'How To Use MySQL Efficiently', 'After you went through a ...'),
-> (NULL,'Optimising MySQL','In this tutorial we will show ...'),
-> (NULL,'1001 MySQL Tricks','1. Never run mysqld as root. 2. ...'),
-> (NULL,'MySQL vs. YourSQL', 'In the following database comparison ...'),
-> (NULL,'MySQL Security', 'When configured properly, MySQL ...');
Query OK, 6 rows affected (0.00 sec)
Records: 6 Duplicates: 0 Warnings: 0

mysql> SELECT * FROM articles
-> WHERE MATCH (title,body) AGAINST ('database');
+----+-------------------+------------------------------------------+
| id | title | body |
+----+-------------------+------------------------------------------+
| 5 | MySQL vs. YourSQL | In the following database comparison ... |
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
+----+-------------------+------------------------------------------+
2 rows in set (0.00 sec)

函数 MATCH() 对照一个文本集(包含在一个 FULLTEXT 索引中的一个或多个列的列集)执行一个自然语言搜索一个字符串。搜索字符串做为 AGAINST() 的参数被给定。搜索以忽略字母大小写的方式执行。对于表中的每个记录行,MATCH() 返回一个相关性值。即,在搜索字符串与记录行在 MATCH() 列表中指定的列的文本之间的相似性尺度。

MATCH() 被使用在一个 WHERE 子句中时 (参看上面的例子),返回的记录行被自动地以相关性从高到底的次序排序。相关性值是非负的浮点数字。零相关性意味着不相似。相关性的计算是基于:词在记录行中的数目、在行中唯一词的数目、在集中词的全部数目和包含一个特殊词的文档(记录行)的数目。

它也可以执行一个逻辑模式的搜索。这在下面的章节中被描述。

前面的例子是函数 MATCH() 使用上的一些基本说明。记录行以相似性递减的顺序返回。

下一个示例显示如何检索一个明确的相似性值。如果即没有 WHERE 也没有 ORDER BY 子句,返回行是不排序的。

mysql> SELECT id,MATCH (title,body) AGAINST ('Tutorial') FROM articles;
+----+-----------------------------------------+
| id | MATCH (title,body) AGAINST ('Tutorial') |
+----+-----------------------------------------+
| 1 | 0.64840710366884 |
| 2 | 0 |
| 3 | 0.66266459031789 |
| 4 | 0 |
| 5 | 0 |
| 6 | 0 |
+----+-----------------------------------------+
6 rows in set (0.00 sec)

下面的示例更复杂一点。查询返回相似性并依然以相似度递减的次序返回记录行。为了完成这个结果,你应该指定 MATCH() 两次。这不会引起附加的开销,因为 MySQL 优化器会注意到两次同样的 MATCH() 调用,并只调用一次全文搜索代码。

mysql> SELECT id, body, MATCH (title,body) AGAINST
-> ('Security implications of running MySQL as root') AS score
-> FROM articles WHERE MATCH (title,body) AGAINST
-> ('Security implications of running MySQL as root');
+----+-------------------------------------+-----------------+
| id | body | score |
+----+-------------------------------------+-----------------+
| 4 | 1. Never run mysqld as root. 2. ... | 1.5055546709332 |
| 6 | When configured properly, MySQL ... | 1.31140957288 |
+----+-------------------------------------+-----------------+
2 rows in set (0.00 sec)

MySQL 使用一个非常简单的剖析器来将文本分隔成词。一个"词"是由文字、数据、"'""_" 组成的任何字符序列。任何在 stopword 列表上出现的,或太短的(3 个字符或更少的)的 "word" 将被忽略。

在集和查询中的每个合适的词根据其在集与查询中的重要性衡量。这样,一个出现在多个文档中的词将有较低的权重(可能甚至有一个零权重),因为在这个特定的集中,它有较低的语义值。否则,如果词是较少的,它将得到一个较高的权重。然后,词的权重将被结合用于计算记录行的相似性。

这样一个技术工作可很好地工作与大的集(实际上,它会小心地与之谐调)。 对于非常小的表,词分类不足以充份地反应它们的语义值,有时这个模式可能产生奇怪的结果。

mysql> SELECT * FROM articles WHERE MATCH (title,body) AGAINST ('MySQL');
Empty set (0.00 sec)

在上面的例子中,搜索词 MySQL 却没有得到任何结果,因为这个词在超过一半的记录行中出现。同样的,它被有效地处理为一个 stopword (即,一个零语义值的词)。这是最理想的行为 -- 一个自然语言的查询不应该从一个 1GB 的表中返回每个次行(second row)。

匹配表中一半记录行的词很少可能找到相关文档。实际上,它可能会发现许多不相关的文档。我们都知道,当我们在互联网上通过搜索引擎试图搜索某些东西时,这会经常发生。因为这个原因,在这个特殊的数据集中,这样的行被设置一个低的语义值。

到 4.0.1 时,MySQL 也可以使用 IN BOOLEAN MODE 修饰语来执行一个逻辑全文搜索。

mysql> SELECT * FROM articles WHERE MATCH (title,body)
-> AGAINST ('+MySQL -YourSQL' IN BOOLEAN MODE);
+----+------------------------------+-------------------------------------+
| id | title | body |
+----+------------------------------+-------------------------------------+
| 1 | MySQL Tutorial | DBMS stands for DataBase ... |
| 2 | How To Use MySQL Efficiently | After you went through a ... |
| 3 | Optimising MySQL | In this tutorial we will show ... |
| 4 | 1001 MySQL Tricks | 1. Never run mysqld as root. 2. ... |
| 6 | MySQL Security | When configured properly, MySQL ... |
+----+------------------------------+-------------------------------------+

这个查询返回所有包含词 MySQL 的记录行(注意: 50% 的阈值没有使用),但是它没有包含词 YourSQL。注意,一个逻辑模式的搜索不会自动地以相似值的降序排序记录行。你可以从上面的结果出看得出来,最高的相似值(包含 MySQL 两次的那个) 最列在最后,而不是第一位。一个逻辑全文搜索即使在没有一个 FULLTEXT 索引的情况下也可以工作,然而它 些。

逻辑全文搜索支持下面的操作符:

+
一个领头的加号表示,该词必须出现在每个返回的记录行中。
-
一个领头的减号表示,该词必须不出现在每个返回的记录行中。

缺省的 (当既没有加号也没有负号被指定时)词是随意的,但是包含它的记录行将被排列地更高一点。这个模仿没有 IN BOOLEAN MODE 修饰词的 MATCH() ... AGAINST() 的行为。
< >
这两个操作符用于改变一个词的相似性值的基值。< 操作符减少基值,> 操作符则增加它。参看下面的示例。
( )
圆括号用于对子表达式中的词分组。
~
一个领头的否定号的作用象一个否定操作符,引起行相似性的词的基值为负的。它对标记一个噪声词很有用。一个包含这样的词的记录将被排列得低一点,但是不会被完全的排除,因为这样可以使用 - 操作符。
*
一个星号是截断操作符。不想其它的操作符,它应该被追加到一个词后,不加在前面。
"
短语,被包围在双引号"中,只匹配包含这个短语(字面上的,就好像被键入的)的记录行。

这里是一些示例:

apple banana
找至少包含上面词中的一个的记录行
+apple +juice
... 两个词均在被包含
+apple macintosh
... 包含词 "apple",但是如果同时包含 "macintosh",它的排列将更高一些
+apple -macintosh
... 包含 "apple" 但不包含 "macintosh"
+apple +(>pie <strudel)
... 包含 "apple" 和 "pie",或者包含的是 "apple" 和 "strudel" (以任何次序),但是 "apple pie" 排列得比 "apple strudel" 要高一点
apple*
... 包含 "apple","apples","applesauce" 和 "applet"
"some words"
... 可以包含 "some words of wisdom",但不是 "some noise words"

6.8.1 全文的限制

  • MATCH() 函数的所有参数必须是从来自于同一张表的列,同时必须是同一个FULLTEXT 索引中的一部分,除非 MATCH()IN BOOLEAN MODE 的。
  • MATCH() 列列表必须确切地匹配表的某一 FULLTEXT 索引中定义的列列表,除非 MATCH()IN BOOLEAN MODE 的。
  • AGAINST() 的参数必须是一个常量字符串。

6.8.2 微调 MySQL 全文搜索

不幸地,全文搜索仍然只有很少的用户可调参数,虽然增加一些在 TODO 上排列很高。如果你有一个 MySQL 源码发行(查看章节 2.3 安装一个 MySQL 源码发行),你可以发挥对全文搜索的更多控制。

注意,全文搜索为最佳的搜索效果,被仔细地调整了。修改默认值的行为,在大多数情况下,只会使搜索结果更糟。不要修改 MySQL 的源代码,除非你知道你在做什么!

  • 被索引的词的最小长度由 MySQL 变量 ft_min_word_len 指定。查看章节 4.5.6.4 SHOW VARIABLES。将它改为你所希望的值,并重建你的 FULLTEXT 索引。 (这个变量只从 MySQL 4.0 开始被支持)
  • stopword 列表可以从 ft_stopword_file 变量指定的文件中读取。查看章节 4.5.6.4 SHOW VARIABLES。在修改了 stopword 列表后,重建你的 FULLTEXT 索引。(这个变量只从 MySQL 4.0.10 开始被支持)
  • 50% 阈值选择由所选择的特殊的衡量模式确定。为了禁止它,修改 `myisam/ftdefs.h' 文件中下面的一行:
    #define GWS_IN_USE GWS_PROB
    改为:
    #define GWS_IN_USE GWS_FREQ
    然后重新编译 MySQL。在这种情况下,不需要重建索引。 注意:使用了这个,将严重地减少 MySQL 为 MATCH() 提供足够的相似性值的能力。如果你确实需要搜索这样的公共词,最好使用 IN BOOLEAN MODE 的搜索代替,它不遵守 50% 的阈值。
  • 有时,搜索引擎维护员希望更改使用于逻辑全文搜索的操作符。这些由变量 ft_boolean_syntax 定义。查看章节 4.5.6.4 SHOW VARIABLES。然而,这个变量是只读的,它的值在 `myisam/ft_static.c' 中被设置。

对于这些更改,要求你重建你的 FULLTEXT 索引,对于一个 MyISAM 表,最容易的重建索引文件的方式如下面的语句:

mysql> REPAIR TABLE tbl_name QUICK;

6.8.3 全文搜索 TODO

  • 使所有对 FULLTEXT 索引的操作更快
  • 邻近(Proximity)操作符
  • 对 "always-index words" 的支持。他们可以是用户希望视为一个词处理的任意字符串,例如 "C++"、"AS/400"、"TCP/IP",等等
  • 支持在 MERGE 表中的全文搜索
  • 对多字节字符的支持
  • 依照数据的语言建立 stopword 列表
  • Stemming (当然,依赖于数据的语言)
  • Generic user-suppliable UDF preparser.
  • 使模式更加灵活 (通过为 CREATE/ALTER TABLE 中的 FULLTEXT 增加某些可调整参数)
(转载自 http://www.yuanma.org/data/2007/0909/article_2851.htm
  Expires、Cache-Control、Last-Modified、ETag是RFC 2616(HTTP/1.1)协议中和网页缓存相关的几个字段。前两个用来控制缓存的失效日期,后两个用来验证网页的有效性。要注意的是, HTTP/1.0有一个功能比较弱的缓存控制机制:Pragma,使用HTTP/1.0的缓存将忽略Expires和Cache-Control头。我们这里以Apache2.0服务器为例,只讨论HTTP/1.1协议。
Expires
  Expires字段声明了一个网页或URL地址不再被浏览器缓存的时间,一旦超过了这个时间,浏览器都应该联系原始服务器。RFC告诉我们:"由于推断的失效时间也许会降低语义透明度,应该被谨慎使用,同时我们鼓励原始服务器尽可能提供确切的失效时间。"

  对于一般的纯静态页面,如html、gif、jpg、css、js,默认安装的Apache服务器,不会在响应头添加这个字段。Firefox浏览器接受到相应后,如果发现没有Expires字段,浏览器根据文件的类型和"Last-Modified"字段来推断出一个合适的失效时间,并存储在客户端。推测出的时间一般是接受到响应时间后的三天左右。

  Apache的expires_module模块可以在Http响应头部自动加上Expires字段。在Apache的httpd.conf文件中进行如下配置:
  #启用expires_module模块
  LoadModule expires_module modules/mod_expires.so
  # 启用有效期控制
  ExpiresActive On
  # GIF有效期为1个月
  ExpiresByType image/gif A2592000
  # HTML文档的有效期是最后修改时刻后的一星期
  ExpiresByType text/html M604800
  #以下的含义类似
  ExpiresByType text/css "now plus 2 month"
  ExpiresByType text/js "now plus 2 day"
  ExpiresByType image/jpeg "access plus 2 month"
  ExpiresByType image/bmp "access plus 2 month"
  ExpiresByType image/x-icon "access plus 2 month"
  ExpiresByType image/png "access plus 2 month"
  
  对于动态页面,如果在页面内部没有通过函数强制加上Expires,例如header("Expires: " . gmdate("D, d M Y H:i:s") . " GMT"),Apache服务器会把Wed, 11 Jan 1984 05:00:00 GMT作为Expires字段内容,返回给浏览器。即认为动态页面总是失效的。而浏览器仍然会保存已经失效的动态页面。

  可以发现Firefox浏览器总是缓存所有页面,不管失效、不失效还是没有声明失效时间。即使缓存中声明了一个网页的实效日期是1970-01- 01 08:00:00,浏览器仍然会发送该文件在缓存中的Last-Modified和ETag字段。如果在服务器端验证通过,返回304状态,浏览器就还会使用此缓存。

Cache-Control
  Cache-Control字段中可以声明多些元素,例如no-cache, must-revalidate, max-age=0等。这些元素用来指明页面被缓存最大时限,如何被缓存的,如何被转换到另一个不同的媒介,以及如何被存放在持久媒介中的。但是任何一个 Cache-Control指令都不能保证隐私性或者数据的安全性。"private"和"no-store"指令可以为隐私性和安全性方面提供一些帮助,但是他们并不能用于替代身
份验证和加密。
  Apache的mod_cern_meta模块允许文件级Http响应头部的控制,同时它也可以配置Cache-Control头(或任何其他头)。响应头文件是放在原始目录的子目录中,根据原始文件名所命名的一个文件。具体用法请参阅Apache的官方网站。其中Cache-Control : max-age表示失效日期。如果没有启动mod_cern_meta模块,Apache服务器会把Expires字段中的日期换算成以秒为单位的一个 delta值,赋值给max-age。如果启动mod_cern_meta模块,并且配置了max-age值,Apache会将这个覆盖Expires字段。同时,max-age隐含了Canche-Control: public。这样浏览器接受到的Cache-Control : max-age和Expires值就是一致的。
     如果失效日期Cache-Control : max-ag=0或者是负值,浏览器会在对应的缓存中把Expires设置为1970-01-01 08:00:00。

Last-Modified
  Last-Modified和ETag是条件请求(Conditional Request)相关的两个字段。如果一个缓存收到了针对一个页面的请求,它发送一个验证请求询问服务器页面是否已经更改,在HTTP头里面带上" ETag"和"If Modify Since"头。服务器根据这些信息判断是否有更新信息,如果没有,就返回HTTP 304(NotModify);如果有更新,返回HTTP 200和更新的页面内容,并且携带新的"ETag"和"LastModified"。
   
  使用这个机制,能够避免重复发送文件给浏览器,不过仍然会产生一个HTTP请求。
一般纯静态页面本身都会有Last-Modified信息,Apache服务器会读取页面文件中的Last-Modified信息,并添加到http响应头部。

  对于动态页面,如果在页面内部没有通过函数强制加上Last-Modified,例如header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"),Apache服务器会把当前时间作为Last-Modified,返回给浏览器。
  
  无论是纯静态页面还是动态页面,Firefox浏览器巧妙地按照接受到服务器响应的时间设置缓存页面的Last-Modified,而不是按照http响应头部中的Last-Modified字段。

ETag
  既然有了Last-Modified,为什么还要用ETag字段呢?因为如果在一秒钟之内对一个文件进行两次更改,Last-Modified就会不正确。因此,HTTP/1.1利用Entity Tag头提供了更加严格的验证。

  Apache服务器默认情况下,会对所有的静态、动态文件的响应头添加ETag字段。在Apache的httpd.conf文件中可以通过FileETag指令配置该选项。

  FileETag指令配置了当文档是基于一个文件时用以创建 Etag(entity tag)响应头的文件的属性。在Apache 1.3.22及以前,ETag的值是对文件的索引节(INode),大小(Size)和最后修改时间(MTime)进行Hash后得到的。如果一个目录的配置包含了'FileETag INode MTime Size'而其一个子目录包含了'FileETag -INode'那么这个子目录的设置(并会被其下任何没有进行覆盖的子目录继承)将等价于'FileETag MTime Size'。

  在多台负载平衡的服务器环境下,同一个文件会有不同的etag或者文件修改日期,浏览器每次都会重新下载。设置'FileETag None'可以使响应头不再包含ETag字段。
 
三种典型web服务器Header设置内容过期方法
一、Internet 信息服务 (IIS)的内容过期设置
  如果IIS 网站中有时间敏感信息,可以配置设置来保证过期信息不被代理服务器或 Web 浏览器缓存。可以配置网站内容,使之在任何的时间自动过期。当启用内容过期时,Web 浏览器将比较当前日期和截止日期,以便决定是显示缓存页还是从服务器请求更新的页。Microsoft ASP.NET 这样的服务器端技术可用于动态更改提供的内容。通常,时间敏感信息只限于单个文件、目录或网站;不过,您也可以为某台计算机上的所有网站设置内容过期。

  必须是本地计算机上 Administrators 组的成员或者必须被委派了相应的权限,才能执行下列步骤。作为安全性的最佳操作,请使用不属于 Administrators 组的帐户登录计算机,然后使用运行方式命令以管理员身份运行 IIS管理器在命令提示符下,键入 runas /user:administrative_accountname "mmc %systemroot%\system32\inetsrv\iis.msc"。

设置网站内容的过期时间
1. 在 IIS 管理器中,展开本地计算机;右键单击要设置内容过期的网站、虚拟目录或文件,然后单击"属性"。
2. 单击"HTTP 头"选项卡。
3. 选中"启用内容过期"复选框。
4. 单击"立即过期"、"此时间段后过期"或"过期时间",然后在对应的框中输入所需的过期信息。
5. 单击"确定"。
 
二、APACHE服务的内容过期设置
  Apache配置摘录及解释
i. 过期相关设置
LoadModule headers_module modules/mod_headers.so
#Load 修改header的模块。
LoadModule expires_module modules/mod_expires.so
#Load 设定过期header的模块。
Header append Via: CCN-BJ-4-502
#增加一个Via header,值配置成设备的hostname。
KeepAliveTimeout 60
#设置连接的保持时间为60秒。
ExpiresActive On
#启用过期header功能。
ExpiresDefault A604800
#缺省过期时间为"访问后的604800秒"
 
<Directory /data/download>
Options FollowSymLinks
AllowOverride None
Order allow,deny
Allow from all
ExpiresByType text/html A300
#text/html类型文件的过期设置为"访问后的300秒"
ExpiresByType text/css A259200
#text/css类型文件的过期设置为"访问后的259200秒"
ExpiresByType application/x-javascript A300
# application/x-javascript类型文件的过期设置为"访问后的300秒"
ExpiresByType image/gif A2592000
#image/gif类型文件的过期设置为"访问后的2592000秒"
ExpiresByType application/x-shockwave-flash A2592000
# application/x-shockwave-flash类型文件的过期设置为"访问后的2592000秒"
</Directory>

  上述配置文件中load的两个模块:mod_headers.so  和mod_expires.so 可以让Apache具有对header的一些定制功能。

ExpiresByType:     表示按照文件类型-MIME-TYPE设定过期策略;
A300: 表示在Access后300秒后过期;
ExpiresByType text/css A2592000:    表示Mime type是text/css的文件,在Access后2592000秒过期。
ExpiresDefault A604800:  表示除了单独制定的文件类型等过期策略外的其他内容,按照这个缺省的策略设定:访问后604800秒过期。

  上面的方法可以实现根据web发布的不同文件类型,针对不同的发布目录进行过期策略设置。在按照如上方法设置后,Apache会自动的产生两个相关的http header,举例如下:
HTTP/1.1 200 OK
Date: Tue, 27 Mar 2007 17:44:21 GMT
Server: Apache/2.0.54 (Unix)
Last-Modified: Thu, 25 Jan 2007 07:45:45 GMT
ETag: "72df3a-93-99499c40"
Accept-Ranges: bytes
Content-Length: 147
Cache-Control: max-age=2592000
Expires: Thu, 26 Apr 2007 17:44:21 GMT
Via: CCN-BJ-4-575
Keep-Alive: timeout=60, max=100
Connection: Keep-Alive
Content-Type: image/gif
Length: 147 [image/gif]
  其中:Date + Max-age = Expires.  Max-age是个时间长度,对应web server上面设置的过期时间;Expires是根据max-age算出来的过期时间点,两者是一致的,不同cache在判断内容是否过期时会严格比较系统时间和上述过期时间,或者比较age(在cache中存住的时间长度)和max-age的值。
 
三、lighttpd
  lighttpd默认是没有开启expire模块的,需要我们在使用是手工开启这个模块支持。把mod_expire前面的"#"号去掉。
# vi  /usr/local/lighttpd/etc/lighttpd.conf
                                "mod_expire",

设定过期时间
    * 设定指定url的过期时间:
expire.url = (
       "/images/" => "access 3 hours",
       "/admin/" => "access 3 hours",
       "/area/" => "access 3 hours",
       "/calendar/" => "access 3 hours",
       "/common/" => "access 3 hours",
       "/front/" => "access 3 hours",
       "/inc/" => "access 3 hours",
       "/jeditor/" => "access 3 hours",
       "/js/" => "access 3 hours",
       "/script/" => "access 3 hours",
       "/theme/" => "access 3 hours",
       "/upload/" => "access 3 hours",
       "/view/" => "access 3 hours",
       "/help/" => "access 3 hours",
       "/htm/" => "access 5 minutes"
       )

设置Etag
在配置文件中增加,etag.use-inode="disable"(i节点不参与etag的运算),保证多台服务器生成的Etag值一致。

(转载自http://www.cnbeta.com/articles/56551.htm)

抽时间统计了一下几个网站的前端 WebServer 类型和所用的 Cache 类型,结果如下:
综合类,从结果上来看 Apache 还是主流:

 Site  WebServer  Cache
www.baidu.com BWS/1.0 N/A
www.qq.com Apache squid/2.6.STABLE5
www.sina.com.cn Apache/2.0.54 (Unix) N/A
www.sohu.com Apache/1.3.37 (Unix) mod_gzip/1.3.26.1a squid
www.163.com Apache/2.2.6 (Unix) N/A
www.taobao.com Apache N/A
www.google.cn gws N/A
www.tom.com Apache NetCache NetApp/6.1.1D4
www.soso.com Apache N/A
www.youku.com Apache N/A
www.xunlei.com Apache/2.2.8 (Unix) N/A
www.eastmoney.com Microsoft-IIS/6.0 N/A
www.56.com nginx/0.5.33 squid/2.6.STABLE12-20070426
www.6.cn nginx/0.6.14 squid/3.0.STABLE1.dev
www.51.com Apache N/A
www.yahoo.cn 4EWS N/A