Bo-Blog 2.1.1 的 Nginx Rewrite 规则[原创]
[
2015/05/28 08:23 | by admin ]
2015/05/28 08:23 | by admin ]
[文章作者:张宴 本文版本:v1.1 最后修改:2009.12.01 转载请注明原文链接:http://blog.zyan.cc/bo-blog_nginx_rewrite/]
Bo-Blog是一款采用PHP开发的单用户博客程序,本人的博客也采用的是Bo-Blog,个人觉得bo-blog的排版、易用性要比WordPress好得多,但扩展性不如WordPress。
很多朋友向我询问过,Bo-Blog的Nginx Rewrite规则如何写。由于Bo-Blog官网只提供了Apache的Rewrite规则,这里,我将自己从 Bo-Blog 的 Apache Rewrite 规则转换而来的 Bo-Blog 2.1.1 的 Nginx Rewrite 重写规则贴在此处,供需要的朋友使用:
PS:2009-12-01修正一处错误,之前文章中的if (!-x更换为if (!-e
Bo-Blog是一款采用PHP开发的单用户博客程序,本人的博客也采用的是Bo-Blog,个人觉得bo-blog的排版、易用性要比WordPress好得多,但扩展性不如WordPress。
很多朋友向我询问过,Bo-Blog的Nginx Rewrite规则如何写。由于Bo-Blog官网只提供了Apache的Rewrite规则,这里,我将自己从 Bo-Blog 的 Apache Rewrite 规则转换而来的 Bo-Blog 2.1.1 的 Nginx Rewrite 重写规则贴在此处,供需要的朋友使用:
引用
if (!-e $request_filename)
{
rewrite ^/post/([0-9]+)/?([0-9]+)?/?([0-9]+)?/?$ /read.php?entryid=$1&page=$2&part=$3 last;
rewrite ^/page/([0-9]+)/([0-9]+)/?$ /index.php?mode=$1&page=$2 last;
rewrite ^/starred/([0-9]+)/?([0-9]+)?/?$ /star.php?mode=$1&page=$2 last;
rewrite ^/category/([^/]+)/?([0-9]+)?/?([0-9]+)?/?$ /index.php?go=category_$1&mode=$2&page=$3 last;
rewrite ^/archiver/([0-9]+)/([0-9]+)/?([0-9]+)?/?([0-9]+)?/?$ /index.php?go=archive&cm=$1&cy=$2&mode=$3&page=$4 last;
rewrite ^/date/([0-9]+)/([0-9]+)/([0-9]+)/?([0-9]+)?/?([0-9]+)?/?$ /index.php?go=showday_$1-$2-$3&mode=$4&page=$5 last;
rewrite ^/user/([0-9]+)/?$ /view.php?go=user_$1 last;
rewrite ^/tags/([^/]+)/?([0-9]+)?/?([0-9]+)?/?$ /tag.php?tag=$1&mode=$2&page=$3 last;
rewrite ^/component/id/([0-9]+)/?$ /page.php?pageid=$1 last;
rewrite ^/component/([^/]+)/?$ /page.php?pagealias=$1 last;
#Force redirection for old rules
rewrite ^/read\.php/([0-9]+)\.htm$ http://$host/post/$1/ permanent;
rewrite ^/post/([0-9]+)\.htm$ http://$host/post/$1/ permanent;
rewrite ^/post/([0-9]+)\_([0-9]+)\.htm$ http://$host/post/$1/$2/ permanent;
rewrite ^/post/([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/post/$1/$2/$3/ permanent;
rewrite ^/index\_([0-9]+)\_([0-9]+)\.htm$ http://$host/page/$1/$2/ permanent;
rewrite ^/star\_([0-9]+)\_([0-9]+)\.htm$ http://$host/starred/$1/$2/ permanent;
rewrite ^/category\_([0-9]+)\.htm$ http://$host/category/$1/ permanent;
rewrite ^/category\_([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/category/$1/$2/$3/ permanent;
rewrite ^/archive\_([0-9]+)\_([0-9]+)\.htm$ http://$host/archiver/$1/$2/ permanent;
rewrite ^/archive\_([0-9]+)\_([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/archiver/$1/$2/$3/$4/ permanent;
rewrite ^/showday\_([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/date/$1/$2/$3/ permanent;
rewrite ^/showday\_([0-9]+)\_([0-9]+)\_([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/date/$1/$2/$3/$4/$5/ permanent;
#Filename alias
rewrite ^/([a-zA-Z0-9_-]+)/?([0-9]+)?/?([0-9]+)?/?$ /read.php?blogalias=$1&page=$2&part=$3 last;
}
{
rewrite ^/post/([0-9]+)/?([0-9]+)?/?([0-9]+)?/?$ /read.php?entryid=$1&page=$2&part=$3 last;
rewrite ^/page/([0-9]+)/([0-9]+)/?$ /index.php?mode=$1&page=$2 last;
rewrite ^/starred/([0-9]+)/?([0-9]+)?/?$ /star.php?mode=$1&page=$2 last;
rewrite ^/category/([^/]+)/?([0-9]+)?/?([0-9]+)?/?$ /index.php?go=category_$1&mode=$2&page=$3 last;
rewrite ^/archiver/([0-9]+)/([0-9]+)/?([0-9]+)?/?([0-9]+)?/?$ /index.php?go=archive&cm=$1&cy=$2&mode=$3&page=$4 last;
rewrite ^/date/([0-9]+)/([0-9]+)/([0-9]+)/?([0-9]+)?/?([0-9]+)?/?$ /index.php?go=showday_$1-$2-$3&mode=$4&page=$5 last;
rewrite ^/user/([0-9]+)/?$ /view.php?go=user_$1 last;
rewrite ^/tags/([^/]+)/?([0-9]+)?/?([0-9]+)?/?$ /tag.php?tag=$1&mode=$2&page=$3 last;
rewrite ^/component/id/([0-9]+)/?$ /page.php?pageid=$1 last;
rewrite ^/component/([^/]+)/?$ /page.php?pagealias=$1 last;
#Force redirection for old rules
rewrite ^/read\.php/([0-9]+)\.htm$ http://$host/post/$1/ permanent;
rewrite ^/post/([0-9]+)\.htm$ http://$host/post/$1/ permanent;
rewrite ^/post/([0-9]+)\_([0-9]+)\.htm$ http://$host/post/$1/$2/ permanent;
rewrite ^/post/([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/post/$1/$2/$3/ permanent;
rewrite ^/index\_([0-9]+)\_([0-9]+)\.htm$ http://$host/page/$1/$2/ permanent;
rewrite ^/star\_([0-9]+)\_([0-9]+)\.htm$ http://$host/starred/$1/$2/ permanent;
rewrite ^/category\_([0-9]+)\.htm$ http://$host/category/$1/ permanent;
rewrite ^/category\_([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/category/$1/$2/$3/ permanent;
rewrite ^/archive\_([0-9]+)\_([0-9]+)\.htm$ http://$host/archiver/$1/$2/ permanent;
rewrite ^/archive\_([0-9]+)\_([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/archiver/$1/$2/$3/$4/ permanent;
rewrite ^/showday\_([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/date/$1/$2/$3/ permanent;
rewrite ^/showday\_([0-9]+)\_([0-9]+)\_([0-9]+)\_([0-9]+)\_([0-9]+)\.htm$ http://$host/date/$1/$2/$3/$4/$5/ permanent;
#Filename alias
rewrite ^/([a-zA-Z0-9_-]+)/?([0-9]+)?/?([0-9]+)?/?$ /read.php?blogalias=$1&page=$2&part=$3 last;
}
PS:2009-12-01修正一处错误,之前文章中的if (!-x更换为if (!-e
快速配置 Samba 将 Linux 目录映射为 Windows 驱动器,用于跨平台编程
[
2015/05/26 08:26 | by admin ]
2015/05/26 08:26 | by admin ]
[文章作者:张宴 本文版本:v1.0 最后修改:2011.04.08 转载请注明原文链接:http://blog.zyan.cc/samba_linux_windows/]
一、局域网内的 Linux 服务器上操作步骤:
1、安装samba(CentOS Linux):
2、创建www账号
3、创建samba配置文件
输入以下内容:
4、为samba用户www、root设立一个密码:
5、启动samba:
二、局域网内的 Windows 服务器上操作步骤:
1、Windows 上访问 samba,在“我的电脑”中输入:
2、Windows 断开 samba 共享连接,在【开始】→【运行】→【cmd】回车中输入:
3、将 samba 共享的 Linux 目录,映射成 Windows 的一个驱动器盘符:



三、跨平台C/C++代码编译、调试:
用 Windows 下的编辑器编写、修改跨平台的C/C++代码,保存后,无需复制到其他地方,即可同时用 Windows 下的 Visual Studio,Linux 下的 g++、gcc、gdb,编译、调试程序了。


注意:在samba共享的驱动器上执行“.bat”批处理脚本,会导致 Windows 蓝屏,这一点需要注意。
一、局域网内的 Linux 服务器上操作步骤:
1、安装samba(CentOS Linux):
yum install samba system-config-samba samba-client samba-common
2、创建www账号
/usr/sbin/groupadd www
/usr/sbin/useradd -g www www
mkdir -p /data0/knose/
chmod 777 /data0/knose/
mkdir -p /data0/htdocs/
chown -R www:www /data0/htdocs/
chmod 777 /data0/htdocs/
cat /etc/passwd | mksmbpasswd.sh> /etc/samba/smbpasswd
/usr/sbin/useradd -g www www
mkdir -p /data0/knose/
chmod 777 /data0/knose/
mkdir -p /data0/htdocs/
chown -R www:www /data0/htdocs/
chmod 777 /data0/htdocs/
cat /etc/passwd | mksmbpasswd.sh> /etc/samba/smbpasswd
3、创建samba配置文件
mv -f /etc/samba/smb.conf /etc/samba/smb.conf.bak
vi /etc/samba/smb.conf
vi /etc/samba/smb.conf
输入以下内容:
引用
[global]
server string = Samba Server
security = user
encrypt passwords = yes
smb passwd file = /etc/samba/smbpasswd
[knose]
workgroup = root
netbios name = root
path = /data0/knose
browseable = yes
writeable = yes
[web]
workgroup = www
netbios name = www
path = /data0/htdocs
browseable = yes
writeable = yes
server string = Samba Server
security = user
encrypt passwords = yes
smb passwd file = /etc/samba/smbpasswd
[knose]
workgroup = root
netbios name = root
path = /data0/knose
browseable = yes
writeable = yes
[web]
workgroup = www
netbios name = www
path = /data0/htdocs
browseable = yes
writeable = yes
4、为samba用户www、root设立一个密码:
smbpasswd -a www
smbpasswd -a root
smbpasswd -a root
5、启动samba:
/sbin/service smb start
二、局域网内的 Windows 服务器上操作步骤:
1、Windows 上访问 samba,在“我的电脑”中输入:
\\xxx.xxx.xxx.xxx\
2、Windows 断开 samba 共享连接,在【开始】→【运行】→【cmd】回车中输入:
net use * /del
3、将 samba 共享的 Linux 目录,映射成 Windows 的一个驱动器盘符:



三、跨平台C/C++代码编译、调试:
用 Windows 下的编辑器编写、修改跨平台的C/C++代码,保存后,无需复制到其他地方,即可同时用 Windows 下的 Visual Studio,Linux 下的 g++、gcc、gdb,编译、调试程序了。


注意:在samba共享的驱动器上执行“.bat”批处理脚本,会导致 Windows 蓝屏,这一点需要注意。
iPhone大小的盒子服务器Cubieboard
[
2015/05/26 08:25 | by admin ]
2015/05/26 08:25 | by admin ]
张宴在淘宝上350多元,买了个基于ARM平台的超小电脑 cubieboard,配置如下:
1G ARM cortex-A8 processor, NEON, VFPv3, 256KB L2 cache
Mali400, OpenGL ES GPU
512M/1GB DDR3 @480MHz
HDMI 1080p Output
10/100M Ethernet
4GB Nand Flash
2 USB Host, 1 micro SD slot, 1 SATA, 1 ir
96 extend pin including I2C, SPI, RGB/LVDS, CSI/TS, FM-IN, ADC, CVBS, VGA, SPDIF-OUT, R-TP..
Running Android, Ubuntu and other Linux distributions


找了台支持HDMI的显示器,安装了Ubuntu Linaro,然后很方便的安装了SSH Server、VNC Server、Nginx、PHP 5.3、MySQL 5.5:
C/C++的开发环境安装:


我使用5V、2A的电源,仅仅10W的耗电量(24小时开着,一月只需3~4元的电费),挂在家里联通ADSL +磊科NR235W路由器的后面。设置一下路由器的DMZ主机到 Cubieboard 的内网 IP 192.168.1.252,通过 DNSPOD 的动态域名解析脚本,将北京联通的公网IP和域名绑定。
一个好消息,北京联通没有封80端口,挂个小站不用备案了;一个坏消息,我家里的联通ADSL只有2M带宽,上行速率被限制在为512Kbps。
附:2013年5月21日开始,这个博客也运行在 Cubieboard 上了。
1G ARM cortex-A8 processor, NEON, VFPv3, 256KB L2 cache
Mali400, OpenGL ES GPU
512M/1GB DDR3 @480MHz
HDMI 1080p Output
10/100M Ethernet
4GB Nand Flash
2 USB Host, 1 micro SD slot, 1 SATA, 1 ir
96 extend pin including I2C, SPI, RGB/LVDS, CSI/TS, FM-IN, ADC, CVBS, VGA, SPDIF-OUT, R-TP..
Running Android, Ubuntu and other Linux distributions


找了台支持HDMI的显示器,安装了Ubuntu Linaro,然后很方便的安装了SSH Server、VNC Server、Nginx、PHP 5.3、MySQL 5.5:
apt-get install openssh-server
apt-get install vnc-server
apt-get install mysql-server mysql-client
apt-get install nginx
apt-get install php5-fpm
apt-get install php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl
apt-get install vnc-server
apt-get install mysql-server mysql-client
apt-get install nginx
apt-get install php5-fpm
apt-get install php5-mysql php5-curl php5-gd php5-intl php-pear php5-imagick php5-imap php5-mcrypt php5-memcache php5-ming php5-ps php5-pspell php5-recode php5-snmp php5-sqlite php5-tidy php5-xmlrpc php5-xsl
C/C++的开发环境安装:
apt-get install gcc
apt-get install g++
apt-get install cmake
apt-get install make
apt-get install g++
apt-get install cmake
apt-get install make


我使用5V、2A的电源,仅仅10W的耗电量(24小时开着,一月只需3~4元的电费),挂在家里联通ADSL +磊科NR235W路由器的后面。设置一下路由器的DMZ主机到 Cubieboard 的内网 IP 192.168.1.252,通过 DNSPOD 的动态域名解析脚本,将北京联通的公网IP和域名绑定。
一个好消息,北京联通没有封80端口,挂个小站不用备案了;一个坏消息,我家里的联通ADSL只有2M带宽,上行速率被限制在为512Kbps。
附:2013年5月21日开始,这个博客也运行在 Cubieboard 上了。
纳斯达克之旅:我的美股投资实录-转自zyan.cc
[
2015/05/26 08:17 | by admin ]
2015/05/26 08:17 | by admin ]
5月开始炒美股,投入资金不多,2500美元(按当时汇率为17000元人民币)。几个月来,一直在摸索,其间有赚有赔,到9月下旬,只实现盈亏平衡。但也就是在9月下旬,我摸索出了一条“超短线美股投资”道路。
于是,在10月一个月,实现了净利润1708美元(11366元人民币)。11月,继续保持这种势头,11月1日至4日的短短四天,净利润466.57美元(3105元人民币)。相对于2500美元的成本,现在的投资回报率已经达到87%,相信在下周末之前即可超过100%。
一、关于美股
很多网站介绍美股时,都不详细,很多细节没有介绍到,我这里就做一个详细的介绍吧:
1、开户
⑴、开户年龄需满20岁;
⑵、开户免费,没有最低开户金额限制(但一些美国证券公司要求至少500美元);
⑶、非美国人(国际账户)买卖股票不征税;
⑷、只需要证券账户即可,不需要额外开立美国银行账户;
⑸、开通一个证券账户,可以交易美国纽约交易所、纳斯达克、美国证券交易所的股票;
⑹、开户需填写《开户申请表》、《W-8BEN 表格》:W-8BEN 表格是用作向美国国税局 Internal Revenue Service) 申报非美国人士身份的文件。此表格是需要每 3 年更新一次。否则,于 W-8BEN 表格过期后后所进行之美股交易将不会再按非美国人士之标准征税。
⑺、记得填写融资账户申请单,开通融资账户。默认的现金账户只能做T+3交易。
⑻、更多关于开户的信息可以参考:http://www.firstrade.com/content/zh-cn/international
2、账户类型
⑴、现金账户:
①、只能做T+3交易,也就是当天买的股票只能第3天才能卖掉,否者,你的账户将被限制90天内禁止买卖股票。
②、现金账户只能做“买进、卖出”交易,不能做“卖空、卖空补回”交易。
③、现金账户没有融资购买力,现金是多少,就只能买多少钱的股票。
⑵、融资账户:
①、最低开户金额为2000美元(汇款时会扣几美元的国际银行中转费,所有尽量比2000美元多一点),可以做T+0当日冲销。当日冲销,也就是说可以当天“买进、卖出”同一支股票。
②、对于非美国公民,融资账户具有2倍的融资购买力(美国公民为4倍),也就是说,假如你投入2500美元,就可以买价值5000美元的股票。假设你卖出股票后赚了1000美元,现在账户总值为3500美元,就可以买价值7000美元的股票。融资买进股票每股必须高于4美元,有些股票无法融资交易系统将自动驳回订单。看板市场或店头小型股不可用融资买卖。
③、融资账户可以做“卖空、卖空补回”交易。“卖空”就相当于买跌,对应“卖空补回”是一对交易。假设现在新浪的股价为59.14美元,你觉得新浪股价会下跌,而此时你手中又没有新浪股票,你就可以“卖空”,从证券公司借来新浪的股票卖掉,在新浪股价下跌后,再“卖空补回”,买进新浪股票还给证券公司,赚钱差价。卖空的股价必须高过4美元,同时您帐户资产总值必须到达卖空总价值的50%[纳斯达克为100%]。
④、融资的那部分钱,是需要付利息的。只有动用融资账户的钱买了股票,才计算利息,买了股票第二天卖掉,就按买股票时的价值,计算一天的利息。如果做当日冲销,当天买、当天卖,就不扣利息。其实,融资的利息没多少,这是我9月、10月的融资利息,10月当日冲销比较多,利息不到4美元。

3、美股交易
⑴、美股的最小交易单位为1股。
⑵、美股为单一手续费,无论你买卖多少股,买进一次佣金为6.95美元,卖出一次佣金也为6.95美元(以Firstrade.com证券公司的佣金为例),无其他费用。“卖空、卖空补回”的佣金也是一样。
⑶、美国股市的交易时间是在中国北京时间的夜里(非工作时间),换算成北京时间,美股夏令是晚上9:30开盘,清晨4:00收市;冬令则晚上10:30开盘,清晨5:00结束。美国股市的一天交易时间是不间断的,也就是说“中午不休息”。
⑷、盘前盘后交易就是在非正常开盘时段(开盘前1个半小时及收盘后1个半小时)也可以进行交易。盘前和盘后交易的交易量不高,流动性不强,买卖价差(Bid Ask Spread)也较高。如果遇到发布财报等重要经济交易事件,则可以在盘前或盘后预先交易。
4、需要注意的事项
如果你的账户市值在25000美元(注意:是2万5千美元)以下,请不要在最近五个交易日内执行四次或四次以上当日冲销交易(当天买进并卖出一支股票算一次当日冲销),否者将会被美国金融业监管局(FINRA)标记为“惯性当日冲销交易者”。
一旦你成为“惯性当日冲销交易者”,并且你的账户市值小于25000美元,你的账户将会被限制在90天内禁止进行股票买卖交易,请一定要注意。当然,如果你的账户市值大于25000美元,将不会受影响。
⑴、“惯性当日冲销交易者”的定义为:任何客户在最近5个交易日内执行4次或4次以上当日冲销交易,且该当日冲销交易的次数占这5天总交易数的6%以上。
⑵、卖出前一交易日的持股,并在当天重新购入该股不会被视当日冲销交易。
举例:我11月1日“卖空、卖空补回”一次SINA,算一次当日冲销;11月2日“买进、卖出”一次BIDU,算一次当日冲销;11月3日买进新浪,4日卖出新浪,不算当日冲销;11月4日“卖空、卖空补回”一次BIDU,算一次当日冲销。这样,到11月5日的时候,我已经有3次当日冲销,这时候,如果买进一支股票,就不能在当天卖出,否者就变成了在最近5个交易日内执行4次当日冲销,将会被标记为“惯性当日冲销交易者”。所以,11月5日,你要么不进行股票买卖,要么买进不卖出,或卖空不补回。
5、我国的外汇管制
中华人民共和国外汇管理局颁布的《个人外汇管理办法实施细则》第二条规定,对个人结汇和境内个人购汇实行年度总额管理。年度总额分别为每人每年等值5万美元。
二、我的美股投资实录
美股的“买进、卖出”、“卖空、卖空补回”交易,决定了股价涨跌都能赚钱,只要判断对方向。通过数据挖掘算出大概的涨跌区间,再加上百度(NASDAQ:BIDU)、新浪(NASDAQ:SINA)等股票交易活跃,波幅大,在一个波峰或波谷做卖空或买入,不贪多,波动1美元就卖空补回或卖出,每晚平均赚100美元,一个月就算亏几次,盈利也超1000美元。
1、以我11月1日至3日的交易为例,来介绍如何操作:
⑴、11月1日,57.63美元卖空120股新浪(NASDAQ:SINA),56.60美元卖空补回120股新浪(NASDAQ:SINA);

⑵、11月2日,108.40美元买进79股百度(NASDAQ:BIDU),109.45美元卖出79股百度(NASDAQ:BIDU);

⑶、11月3日,56.20美元买进155股新浪(NASDAQ:SINA),4日58美元卖出155股新浪(NASDAQ:SINA);

2、最近一段时间的交易收益表,只因为买了一支非中国概念股,赔过一次,其他都是赚的。正如攻势足球,只要进球数远高于失球数,就是大比分获胜。


三、开户证券公司
1、我是在美国第一理财(https://www.firstrade.com/)证券公司开的户,通过中国邮政储蓄(电汇手续费比银行便宜),拿17000元人民币购汇2500美元,电汇到我的开户证券公司的(由于我国尚未正式开放个人境外证券投资,汇款用途请填:教育培训,以免银行不予汇款)。这是家有25年历史、华人开办的美国证券公司,有中文交易界面和中文客服人员,服务还不错。当然,你也可以选择其他证券公司,但最好是具有中文客服的公司,便于将来沟通。
2、如何取回资金

提款用的《汇款授权书》:https://invest.firstrade.com/forms/zh-cn/wire_fund_authorization.pdf
PS:最近看到一篇报道,说明我国正在逐步放宽对跨境证券购买与对外直接投资的限制,美股,将成为一项新的投资选择。
中国央行行长:将循序渐进实现人民币资本帐户(http://finance.ifeng.com/forex/whyw/20101104/2823557.shtml):
《中国证券报》周四报导称,中国央行行长周小川表示,未来几年中国将继续改革汇率机制,以循序渐进的方式实现人民币资本帐户下的可兑换。周小川在一次金融论坛上的讲话称,在2011年-2015年的下一个五年计划期间,中国将逐步允许人民币用于贸易结算与跨境投资领域。该报援引分析人士的话称,预计未来五年中国将放宽对跨境证券购买与对外直接投资的限制。自2009年7月推出人民币贸易结算试点以来,中国目前允许20多个省市用人民币进行跨境贸易结算。
基于Sphinx构建准实时更新的分布式通用搜索引擎平台[原创]
[
2015/05/26 08:14 | by admin ]
2015/05/26 08:14 | by admin ]
[文章作者:张宴 本文版本:v1.0 最后修改:2010.02.05 转载请注明原文链接:http://blog.zyan.cc/sphinx_search/]
前言:
2008年7月,我写过一篇文章《基于Sphinx+MySQL的千万级数据全文检索(搜索引擎)架构设计》。有不少网友希望阅读全文,我将该文档整理了一下,分享出来。文档解压后大小为7.33M,共19页。
本站下载地址: http://blog.zyan.cc/book/sphinx/sphinx_mysql.zip
新浪下载分流: http://ishare.iask.sina.com.cn/f/6728201.html
上述文档架构存在的局限,我在2008年12月的文章《亿级数据的高并发通用搜索引擎架构设计》中已经指出:一是MySQL本身的并发能力有限,在200~300个并发连接下,查询和更新就比较慢了;二是由于MySQL表的主键与Sphinx索引的ID一一对应,从而无法跨多表建立整站查询,而且新增加类别还得修改配置文件,比较麻烦;三是因为和MySQL集成,无法发挥出Sphinx的优势。虽然如此,但对于一些写入量不大的搜索应用,已经足够了,或许对很多人会有帮助。
正文:
在这之后,本人基于《亿级数据的高并发通用搜索引擎架构设计》开发的Sphinx分布式通用站内搜索引擎平台,已经在生产环境运行9个月以上,经过运营中的不断完善与改进,目前已形成了一套可扩展的分布式通用站内搜索引擎框架。CMS、视频、论坛等产品发生的增、删、改操作,文本内容实时写入自行开发的 HTTPSQS 高性能简单消息队列服务,通过队列控制器更新索引和存储。提供支持XML、JSON的API查询接口,支持亿级数据的索引、分布式、中文分词、高亮显示、自动摘要、准实时(1分钟内)增量索引更新。

下面是Sphinx新的搜索架构中技术关键点实现方式的一些介绍,与大家分享、交流一下:
1、一元分词和中文分词的结合:
①、一元分词位于索引更新模块。Sphinx索引引擎对于CJK(中日韩)语言(必须是UTF-8编码)支持一元切分,假设【反恐行动是国产主视角射击网络游戏】这段文字,Sphinx会将其切成【反 恐 行 动 是 国 产 主 视 角 射 击 网 络 游 戏】,然后对每个字建立反向索引。如果用这句话中包含的字组成一个不存在的词语,例如【恐动】,也会被搜索到,所以搜索时,需要加引号,例如搜索【"反恐行动"】,就能完全匹配连在一起的四个字,不连续的【"恐动"】就不会被搜索到。但是,这样还有一个问题,搜索【"反恐行动游戏"】或【"国产网络游戏"】就会搜索不到。对于这个问题,采用位于搜索查询模块的中文分词来处理。
sphinx.conf配置文件中关于UTF-8中文一元分词的配置如下:
②、中文分词位于搜索查询模块。搜索“反恐行动游戏”、“国产网络游戏”,先调用独立的中文分词系统,分别切分为“反恐行动 游戏”、“国产 网络游戏”,这时候,再给以空格分隔的词语加上引号,去Sphinx搜索【"反恐行动" "游戏"】或【"国产" "网络游戏"】,就能搜索到这条记录了。中文分词词库发生增、删、改,无需重建整个Sphinx搜索索引。
2、使用自行开发的HTTPSQS(http://code.google.com/p/httpsqs)开源简单队列服务程序,来缓冲高并发数据写入
新闻、论坛帖子、客服公告、SNS社区等发生的增、删、改操作,文本内容通过更新接口实时写入HTTPSQS队列,再通过队列控制器更新到Sphinx搜索引擎索引中。
3、Sphinx不能严格按照字段排序的小问题
如果不想使用权重,只希望严格按照时间、主键等排序,而匹配模式(Matching modes)又为非SPH_MATCH_BOOLEAN时(比较常用的是SPH_MATCH_ALL、SPH_MATCH_EXTENDED),Sphinx搜索结果在某一页中的排序会不太准确。例如:按照UNIX时间戳倒序排序,0,20为第一页,20,40为第二页,第一页的最小时间戳一定会大于第二页的最大时间戳,但是,第一页中的0,20条记录却不会严格按照时间戳排序,第二页亦是如此。因此,如果需要精确排序,用户翻到搜索结果的某一页,就需要对Sphinx在某一搜索结果页中的记录另行再排序,在我的这套搜索架构中,这一再排序操作由search.php查询接口使用array_multisort()函数处理。一般情况下,一页只会显示5~30条记录,因此,只对几十条记录采用PHP再排序,速度也是非常快的。
4、队列控制器中“时间控制”与“数量控制”相结合,实现搜索索引的1分钟内准实时更新:
①、Sphinx 0.9.9生产环境的建索引速度大约在5.5 Mbytes/秒、6400文档/秒。队列控制器可以设置10秒钟更新一次增量索引,只要Sphinx增量索引数据源的文档数在38万以内,就能保证增量索引在1~60秒内得到更新,这是从“时间”上进行控制。
②、为了避免增量索引数据源的文档数增长到38万,队列控制器在增量索引数据源的文档数超过1万时,还将激活增量索引合并入主索引的操作,合并完成的文档将从增量索引数据源中删除,这是从“数量”上进行控制。
5、自行编写的“搜索引擎查询API接口”调用说明:
6、搜索结果前台页面示例:

7、同一套服务器平台与API接口,通用于各类产品:
示例:
金山游戏文章与视频搜索:http://s.xoyo.com/result.php?w=%E5%89%91%E7%BD%913
金山游戏论坛帖子搜索:http://jx3.bbs.xoyo.com/search2.php?srchtxt=%E4%B8%83%E7%A7%80&select=title
前言:
2008年7月,我写过一篇文章《基于Sphinx+MySQL的千万级数据全文检索(搜索引擎)架构设计》。有不少网友希望阅读全文,我将该文档整理了一下,分享出来。文档解压后大小为7.33M,共19页。
本站下载地址: http://blog.zyan.cc/book/sphinx/sphinx_mysql.zip
新浪下载分流: http://ishare.iask.sina.com.cn/f/6728201.html
上述文档架构存在的局限,我在2008年12月的文章《亿级数据的高并发通用搜索引擎架构设计》中已经指出:一是MySQL本身的并发能力有限,在200~300个并发连接下,查询和更新就比较慢了;二是由于MySQL表的主键与Sphinx索引的ID一一对应,从而无法跨多表建立整站查询,而且新增加类别还得修改配置文件,比较麻烦;三是因为和MySQL集成,无法发挥出Sphinx的优势。虽然如此,但对于一些写入量不大的搜索应用,已经足够了,或许对很多人会有帮助。
正文:
在这之后,本人基于《亿级数据的高并发通用搜索引擎架构设计》开发的Sphinx分布式通用站内搜索引擎平台,已经在生产环境运行9个月以上,经过运营中的不断完善与改进,目前已形成了一套可扩展的分布式通用站内搜索引擎框架。CMS、视频、论坛等产品发生的增、删、改操作,文本内容实时写入自行开发的 HTTPSQS 高性能简单消息队列服务,通过队列控制器更新索引和存储。提供支持XML、JSON的API查询接口,支持亿级数据的索引、分布式、中文分词、高亮显示、自动摘要、准实时(1分钟内)增量索引更新。

下面是Sphinx新的搜索架构中技术关键点实现方式的一些介绍,与大家分享、交流一下:
1、一元分词和中文分词的结合:
①、一元分词位于索引更新模块。Sphinx索引引擎对于CJK(中日韩)语言(必须是UTF-8编码)支持一元切分,假设【反恐行动是国产主视角射击网络游戏】这段文字,Sphinx会将其切成【反 恐 行 动 是 国 产 主 视 角 射 击 网 络 游 戏】,然后对每个字建立反向索引。如果用这句话中包含的字组成一个不存在的词语,例如【恐动】,也会被搜索到,所以搜索时,需要加引号,例如搜索【"反恐行动"】,就能完全匹配连在一起的四个字,不连续的【"恐动"】就不会被搜索到。但是,这样还有一个问题,搜索【"反恐行动游戏"】或【"国产网络游戏"】就会搜索不到。对于这个问题,采用位于搜索查询模块的中文分词来处理。
sphinx.conf配置文件中关于UTF-8中文一元分词的配置如下:
...省略...
index t_source_main
{
source = t_source_main
path = /data0/search/sphinx/data/t_source_main
docinfo = extern
mlock = 0
morphology = none
min_word_len = 1
charset_type = utf-8
min_prefix_len = 0
html_strip = 1
charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
ngram_len = 1
ngram_chars = U+3000..U+2FA1F
}
...省略...
index t_source_main
{
source = t_source_main
path = /data0/search/sphinx/data/t_source_main
docinfo = extern
mlock = 0
morphology = none
min_word_len = 1
charset_type = utf-8
min_prefix_len = 0
html_strip = 1
charset_table = 0..9, A..Z->a..z, _, a..z, U+410..U+42F->U+430..U+44F, U+430..U+44F
ngram_len = 1
ngram_chars = U+3000..U+2FA1F
}
...省略...
②、中文分词位于搜索查询模块。搜索“反恐行动游戏”、“国产网络游戏”,先调用独立的中文分词系统,分别切分为“反恐行动 游戏”、“国产 网络游戏”,这时候,再给以空格分隔的词语加上引号,去Sphinx搜索【"反恐行动" "游戏"】或【"国产" "网络游戏"】,就能搜索到这条记录了。中文分词词库发生增、删、改,无需重建整个Sphinx搜索索引。
2、使用自行开发的HTTPSQS(http://code.google.com/p/httpsqs)开源简单队列服务程序,来缓冲高并发数据写入
新闻、论坛帖子、客服公告、SNS社区等发生的增、删、改操作,文本内容通过更新接口实时写入HTTPSQS队列,再通过队列控制器更新到Sphinx搜索引擎索引中。
3、Sphinx不能严格按照字段排序的小问题
如果不想使用权重,只希望严格按照时间、主键等排序,而匹配模式(Matching modes)又为非SPH_MATCH_BOOLEAN时(比较常用的是SPH_MATCH_ALL、SPH_MATCH_EXTENDED),Sphinx搜索结果在某一页中的排序会不太准确。例如:按照UNIX时间戳倒序排序,0,20为第一页,20,40为第二页,第一页的最小时间戳一定会大于第二页的最大时间戳,但是,第一页中的0,20条记录却不会严格按照时间戳排序,第二页亦是如此。因此,如果需要精确排序,用户翻到搜索结果的某一页,就需要对Sphinx在某一搜索结果页中的记录另行再排序,在我的这套搜索架构中,这一再排序操作由search.php查询接口使用array_multisort()函数处理。一般情况下,一页只会显示5~30条记录,因此,只对几十条记录采用PHP再排序,速度也是非常快的。
4、队列控制器中“时间控制”与“数量控制”相结合,实现搜索索引的1分钟内准实时更新:
①、Sphinx 0.9.9生产环境的建索引速度大约在5.5 Mbytes/秒、6400文档/秒。队列控制器可以设置10秒钟更新一次增量索引,只要Sphinx增量索引数据源的文档数在38万以内,就能保证增量索引在1~60秒内得到更新,这是从“时间”上进行控制。
②、为了避免增量索引数据源的文档数增长到38万,队列控制器在增量索引数据源的文档数超过1万时,还将激活增量索引合并入主索引的操作,合并完成的文档将从增量索引数据源中删除,这是从“数量”上进行控制。
5、自行编写的“搜索引擎查询API接口”调用说明:
http://xxx.xxx.xxx.xxx/search.php?query=%E9%87%91%E5%B1%B1 (搜索关键字。程序能够识别关键字是GBK编码还是UTF-8编码,能够识别关键字是否进行了URL编码)
&output=xml (输出类型支持:xml 或 json)
&excerpts=1 (是否开启高亮显示与文本摘要,1开启 或 0关闭)
&excerpts_before=<font color=red> (高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。在匹配的关键字前面插入的字符串。)
&excerpts_after=</font> (高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。在匹配的关键字之后插入的字符串。)
&excerpts_limit=256 (高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。摘要最多包含的符号(码点)数。)
&excerpts_field=c1,c2,c3,c4,c5 (仅对指定的字段进行高亮显示,其余字段不进行高亮显示,如果此参数为空,则默认所有的字符型字段都进行高亮显示)
&offset=0&limit=20 (相当于SQL语句中的limit 0,20)
&max_matches=30000 (最大搜索结果集数量)
&match_mode=SPH_MATCH_EXTENDED2
&ranking_mode=SPH_RANK_PROXIMITY_BM25
&sort_mode=SPH_SORT_EXTENDED&sort_by=@relevance DESC,u1 ASC,@id DESC (排序模式:@relevance和@id是内置变量,@relevance代表相关度权值,@id等于search_id,u1为字段名)
&field_weights=c1,7;c2,1 (权重设置:字段c1的权重为7,字段c2的权重为1)
&filter=u1:0_1_6,false;u2:4,true (整数值过滤器:匹配字段u1等于0、1或6,并且字段u2不等于4的结果集。false表示等于,true表示不等于)
&filter_range=u1:0,100,false;u2:50,90,true (整数范围过滤器:字段u1 >= 0并且u1 <= 100,字段u2 < 50并且u2 > 90)
&filter_range=u1:1.23,99.645,false;u2:1034.3,7834.56,true (浮点数范围过滤器:字段u1 >= 1.23并且u1 <= 99.645,字段u2 < 1034.3并且u2 > 7834.56)
&output=xml (输出类型支持:xml 或 json)
&excerpts=1 (是否开启高亮显示与文本摘要,1开启 或 0关闭)
&excerpts_before=<font color=red> (高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。在匹配的关键字前面插入的字符串。)
&excerpts_after=</font> (高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。在匹配的关键字之后插入的字符串。)
&excerpts_limit=256 (高亮显示与文本摘要,如果为空值则不进行高亮显示与文本摘要。摘要最多包含的符号(码点)数。)
&excerpts_field=c1,c2,c3,c4,c5 (仅对指定的字段进行高亮显示,其余字段不进行高亮显示,如果此参数为空,则默认所有的字符型字段都进行高亮显示)
&offset=0&limit=20 (相当于SQL语句中的limit 0,20)
&max_matches=30000 (最大搜索结果集数量)
&match_mode=SPH_MATCH_EXTENDED2
&ranking_mode=SPH_RANK_PROXIMITY_BM25
&sort_mode=SPH_SORT_EXTENDED&sort_by=@relevance DESC,u1 ASC,@id DESC (排序模式:@relevance和@id是内置变量,@relevance代表相关度权值,@id等于search_id,u1为字段名)
&field_weights=c1,7;c2,1 (权重设置:字段c1的权重为7,字段c2的权重为1)
&filter=u1:0_1_6,false;u2:4,true (整数值过滤器:匹配字段u1等于0、1或6,并且字段u2不等于4的结果集。false表示等于,true表示不等于)
&filter_range=u1:0,100,false;u2:50,90,true (整数范围过滤器:字段u1 >= 0并且u1 <= 100,字段u2 < 50并且u2 > 90)
&filter_range=u1:1.23,99.645,false;u2:1034.3,7834.56,true (浮点数范围过滤器:字段u1 >= 1.23并且u1 <= 99.645,字段u2 < 1034.3并且u2 > 7834.56)
6、搜索结果前台页面示例:

7、同一套服务器平台与API接口,通用于各类产品:
示例:
金山游戏文章与视频搜索:http://s.xoyo.com/result.php?w=%E5%89%91%E7%BD%913
金山游戏论坛帖子搜索:http://jx3.bbs.xoyo.com/search2.php?srchtxt=%E4%B8%83%E7%A7%80&select=title





