Skip to content


Twitter,架构的变迁[转]

Evan WeaverTwitter服务团队的总工程师,他的主要工作是优化与伸缩性。在QCon London 2009上,他谈到了Twitter的架构,特别是在过去一年当中为提升Web站点性能所执行的优化。

Twitter使用的大部分工具都是开源的。其结构是用Rails作前端,C,Scala和Java组成中间的业务层,使用MySQL存储数据。所有的东西都保存在RAM里,而数据库只是用作备份。Rails前端处理展现,缓存组织,DB查询以及同步插入。这一前端主要由几部分客户服务粘合而成,大部分是C写的:MySQL客户端,Memcached客户端,一个JSON端,以及其它。

中间件使用了Memcached,Varnish用于页面缓存,一个用Scala写成的MQ,Kestrel和一个Comet服务器也正在规划之中,该服务器也是用Scala写成,当客户端想要跟踪大量的tweet时它就能派上用场。

Twitter是作为一个“内容管理平台而非消息管理平台”开始的,因此从一开始基于聚合读取的模型改变到现在的所有用户都需要更新最新tweet的消息模型,需要许许多多的优化。这一改动主要在于三个方面:缓存,MQ以及Memcached客户端。

缓存

每个tweet平均被126个用户跟踪,所以这里有着明显的缓存需求。在最初的配置中,只有API有着一个页面缓存,当每次从一个用户那里来了一个tweet时就会失效,而应用的其它部分都是无缓存的:

image

第一个架构改动是创建一个直写式 向量缓存包含了一个tweet ID的数组,tweet ID是序列化的64位整数。这一缓存的命中率是99%。

第二个改动是加入另一个直写式 行缓存,它包含了数据库记录:用户和tweets。这一缓存有着95%的命中率并且使用了Nick Kallen的名为Cache Money的Rails插件。Nick是Twitter的一名系统架构师。

第三个改动是引入了一个直读式的 碎片缓存,它包含了通过API客户端访问到的tweets的序列化版本,这些tweets可以被打包成JSON,XML或者是Atom的格式,有着同样是95%的命中率。这一碎片缓存“直接消费向量,而且如果现在缓存了一个序列化的碎片,它不会加载你试图看到的该tweet的实际的行,因此它将在大量时间将数据库置于短路状态,”Evan这样说到。

还有另一个改动是为页面缓存创建一个单独的缓存池。根据Evan的说法,该页面缓存池使用了一个分代的键模式,而不是直接的失效,因为用户可以

发送HTTP的if-modified-since并且将任何他们想要的时间戳放入请求路径,我们需要将这一数组切片并只呈现给他们他们想要看到的tweets,但我们不想跟踪客户端所使用的所有可能的键值。这一分代的键模式有一个大问题,在于它不会删除所有失效的键值。每一个被加入的对应到人们所接收的tweets数目的页面都会向缓存推送有效的数据,最后变得我们的缓存仅仅只有五个小时的有效生命周期,因为所有的页面缓存都将流过。

当该页面缓存转移到其自己的池之后,缓存未命中降低了将近50%。

这是Twitter现在所使用的缓存模式:

image

因为80%的Twitter流量都来自API,因此还有额外的二层缓存,每一个最多将处理95%来自前一层的请求。整体的缓存改动总共有百分之二三十的优化,它带来了

10倍的容量提升,它本可以更多,但现在我们遇到了另一瓶颈…我们的策略是首先加入直读式缓存,确保它正确失效,然后再转移到直写式缓存并且在线修复,而不是当一个新的tweet ID进来时每次都要销毁。

消息队列

因为,平均来说一个用户有126个追随者,这就意味着每个tweet将有126个消息在队列里。同时,流量会有出现高峰的时候,就像在奥巴马就职的时候达到了每秒几百个tweet或者说是成千上万的消息在队列里,是正常流量的3倍。MQ应当去化解这一高峰并随着时间将其分散,这样就不用增加许多额外的硬件。Twitter的MQ很简单:基于Memcached的协议,job之间是无序的,服务器之间没有共享的状态,所有的东西都保存在RAM里,并且是事务性的。

第一版的MQ实现是用的Starling,以Ruby写成,伸缩性不佳,特别是Ruby的GC不是分代的。这将导致MQ在某一点上崩溃,因为GC完成工作时将会把整个队列处理中止。因此作出了将MQ移植到Scala上的决定,它有着更为成熟的JVM GC机制。现有的MQ仅仅只有1200行代码并且运行在3台服务器上。

Memcached客户端

Memcached客户端的优化目的是试图优化集群负载。现在的客户端用的是libmemcached,Twitter是其最重要的用户和其代码库最重要的贡献者。基于此,持续一年的碎片缓存优化带来了50倍的每秒页面请求服务增加。

image

因为请求来自的位置难以确定,处理请求最快的办法就是将预先计算好的数据存储在网络RAM上,而不是当需要的时候在每个服务器上都重新计算一次。这一方式被主流的Web 2.0站点所使用,它们几乎都是完全直接运行于内存之上。根据Evan的说法,下一步就是“既可伸缩的读持续了一年之后,(解决)可伸缩的写,然后就是多协同定位的问题”。

这一QCon的演示文件发布在Evan的站点上

中文原文:http://www.infoq.com/cn/news/2009/06/Twitter-Architecture

查看英文原文: Twitter, an Evolving Architecture

Posted in 技术, 网站架构.

Tagged with , .


豆瓣网技术架构变迁[转]

概要 罗马不是一天建成的,豆瓣的技术架构也是随着用户规模的增长一直在持续变化中。在本次演讲中,豆瓣的首席架构师洪强宁将与大家一起分享从上线时的单台服务器架构开始一直到现在的豆瓣架构变迁历程。

个人简介 洪强宁,2002年毕业于清华大学,现任北京豆瓣互动科技有限公司首席架构师。洪强宁和他带领的技术团队致力于用技术改善人们的文化和生活品质,在网站架构、性能、可伸缩性上进行深入研究。豆瓣网曾获软件中国2006年度最佳技术应用网站。

关于会议 QCon全球企业开发大会(QCon Enterprise Software Development Conference)是由C4Media媒体集团InfoQ网站主办的全球顶级技术盛会,每年在伦敦、旧金山、北京、东京召开。自2007年3月份在伦敦召开首次举办以来,已经有包括金融、电信、互联网、航空航天等领域的近万名架构师、项目经理、团队领导者和高级开发人员参加过QCon大会。

详细内容:

http://www.infoq.com/cn/presentations/hongqn-douban

Posted in 技术, 网站架构.

Tagged with , .


主流手机分辨率介绍[转]

我们的手机现在主要有两种分辨率: 220×176(?)320×240(QVGA)。以后新的手机可能会有640×480(VGA)的分辨率。
220×176的分辨率到底叫什么?确实,查遍相关的资料也无法得知此规格的定义,查过ARM的一些资料,OV系列的一些资料等……应该认为220×176是非标准分辨率规格。
看到现在网络上以及我们论坛内对220×176的错误称谓,我觉得有必要统一一下该规格的称呼了……其实规定都是人定义的么,叫的多了就大家认同了……
 
不过,定义该规格时也必须要有充足的依据,现在,我把我对该系列的定义阐述如下:
1.       我们先来列举一下需要引用的几个分辨率规格:
规格                                       宽高比        像素点
QQCIF               88           72          1.2222          6336
Sub-QCIF         128          96          1.3333          12288
QQVGA            160         120         1.3333          19200
QCIF                 176          144         1.2222          25344
                       208         176         1.1818          36608
                       220         176         1.2500          38720
                       240         176         1.3636          42240
QVGA                320         240         1.3333          76800
CIF                     352         288         1.2222          101376
VGA                   640         480         1.3333          307200
SVGA                 800         600         1.3333          480000
XGA                  1024        768         1.3333          786432
WXGA              1280        800         1.6000         1024000
UVGA                1280        960         1.3333         1228800
SXGA                1280        1024       1.2500         1310720
SXGA+              1400        1050       1.3333         1470000
USVGA              1600        1200       1.3333         1920000
WSUVGA+        1920       1080       1.7888         2073600
WSUVGA          1920       1200       1.6000          2304000
SUVGA               1920       1440       1.3333         2764800
UXGA                 2048       1536       1.3333         3145728
UWXGA             2560       1600       1.6000      4096000
USXGA               2560       2048       1.2500      5242880
上面的系列像素点相互的关系:
VGAQVGA*4=QQVGA*4*4;
CIF=QCIF*4=QQCIF*4*4;
Sub-QCIF大约是1/8CIF,近似等于1/2QCIF
 
2.       所以再根据精确比对和计算后,可以看出220×176VGA系列比较容易匹配。其关系是:
220×176近似等于1/8VGA,近似等于1/2QVGA。因此可以看做是Sub-QVGA
 
3.       在我们确定了220×176Sub-QVGA的规格后,我们参考了其他的分辨率定义方案,又定义了以下两个分辨率名称:
  208×176(Sub-QVGA-)
  240×176(Sub-QVGA+)
 
4.       最后我们将以上定义的三个非标准分辨率名称(这几个都是现在主流的,但是非标准规格),整理如下:
规格                                         宽高比        像素点
Sub-QVGA-       208         176         1.1818          36608
Sub-QVGA         220         176         1.2500          38720 
Sub-QVGA+       240         176         1.3636          42240
 
名词缩写解释:
  VGA              Video Graphics Array
  QVGA           Quarter Video Graphics Array
  QQVGA        Quarter QVGA
  Sub-QVGA   Sub Quarter QVGA
  CIF                Common Intermediate Format
  QCIF             Quarter Common Intermediate Format
  QQCIF          Quarter QCIF
原文:http://blog.chinaunix.net/u/25864/showart_240954.html

Posted in Wap, 技术.

Tagged with , .


移动web设计:标准的选择[转]

移动web(mobile web)?WAP? 大家都说WAP,为什么我说移动web?主要是想和以前的某些习惯区分开来,首先,复习一下定义:

WAP:无线应用协议,是在无线网络环境中应用层通讯的一个开放国际标准,主要用于手机等移动设备访问国际互联网。而WAP网站则是使用WML编写的网站的俗称。 移动web:是指可以用移动设备访问的WWW内容、应用和服务。

很明显,移动web应该包含了WAP。所以,我把能用移动设备访问的网站或应用称为移动web。

开发标准 移动web是客户端技术,如果要开发移动网站,自然我们需要选择一款合适的标准语言。主要技术标准有:

  • WML——古典的移动web标准,使用WML
  • i-mode——一个小日本的标准,使用iHTML,我们可以忽略
  • OMA领导的xHTML mobile profile,使用xHTML
  • W3C领导的xHTML Basic,使用xHTML
  • 以及所谓的Full Web,也就是普通的HTML——从iPhone开始流行起来

他们的演进如下:

目前仍在演进的,就是有HTML, 和XML了(Flash Lite另外讨论)。

技术特点还是贴图直观一点,我用网易来举例:

WML:代码紧凑,适合无线传输,被良好的支持,有许多移动特性。但是需要独立开发,实现样式困难。

xHTML:适合无线传输,被广泛地支持,易于开发,易于界面设计,mobile profile有部分移动特性。

Full Web:适合桌面习惯,丰富的表现,不过需要设备有大量内存和渲染能力,传输比较慢。

支持情况:

  • wml:可以接入互联网的手机都支持(除了iPhone),而MID和上网本默认情况下不支持。
  • xHTML mp:近代手机都支持,只要拥有256色以上的屏幕的手机是绝对支持的,MID和桌面电脑也支持。
  • xHTML Basic:近代手机都支持,如果支持到它的设备,mobile profile页面也能良好的渲染,MID和桌面电脑也支持。
  • Full Web:近几年的设备支持,一般是智能机和较主流的设备,例如操作系统是Symbian, Mac OS, windows, Android等的设备以及部分第三方浏览器如Opera, Fennec, Skyfire等等。

如果

如果你有如下条件,使用wml:

  • 面向所有年代的手机都要有良好的兼容
  • 界面效果要求不高
  • 极小的数据传输
  • 额外的wml编写经验

如果你有如下条件,使用xHTML:

  • 面向近几年的移动设备和桌面设备
  • 需要良好的移动界面
  • 较小的移动数据传输带宽
  • 要求丰富的多媒体内容

如果你有如下条件,使用Full Web:

  • 面向高机能的智能设备
  • 没有时间开发移动版本的内容
  • 大量的带宽
  • 不要求移动特性

当然上面的条件有点以偏概全了,不代表必须这样做。还是要根据实际情况,决定使用合适的技术标准。

转自:http://bbs.blueidea.com/thread-2920054-1-1.html

Posted in Wap.

Tagged with , .


25 个在 Web 中嵌入图表的免费资源[转]

 

在 Web 中嵌入图形图表的技术越来越丰富,我们可以选择 JavaScript 库,CSS,Flash,Silverlight,PHP 库,服务器端的组件,也可以选择 Google Chart API 这样的 Web 服务。本文介绍了25个在 Web 中嵌入图形图表的免费资源。

JS Charts (基于 JavaScript 的图表生成工具)

js-charts

Protovis (可视化 javaScript 图表生成工具)

chart4

Visifire (基于 Silverlight 和 WPF 的开源图表组件)

chart6

pChart (PHP图表类库框架)

pchart

Ejschart (Javascript)

chartx

XML/SWF Charts

chart3

Chronoscope (开源)

timeline

Open Flash Chart 2

chart7

FusionCharts Free

top5

JFreeChart (flash)

jfr

Flare (Flash ActionScript 库)

flare

Google Chart API

google

Google Chart Generator

chart_01

Timeplot (基于 DHTML 的 AJAX 饰件)

timeplot

CSS Chart Generator (基于 CSS 的即时 Web 图表生成)

viper

YUI Library

chart9

PlotKit (JavaScript 图表库)

chart10

Flotr (基于 Prototype框架的图表类库)

flotr

Rapha?l (JavaScript library)

chart11

Protochart (开源类库,基于 Prototype 和 Canvas)

points

Bluff (Rubby 下的 Gruff 图表类库的 JavaScript 移植)

bluff

Pure Css Line Graph (纯粹基于 CSS 的线形图)

chart12

Pure Css Data Chart

css3

CSS Stacked Bar Graphs

stacked

Illustrator tutorial

illustrator

本文资料来源:http://blogof.francescomugnai.com/2009/04/25-great-free-resources-for-making-charts/ 编译:COMSHARP CMS 官方网站

Posted in 其它, 网站建设.

Tagged with , .


数据之美(三)[转]

片图抵千言,任何数据报告都不如一幅图来得形象,6月中旬,我们曾译介了 Webdesigner Depot 的一篇文章,《数据之美》()。本文是 Webdesigner Depot 推出的另一篇同题材文章,介绍了25幅令人赞叹的计算机数据图形(Infographics),再次领略数据之美。

1. Web 趋势图


2. 字体周期表


3. 全球 Internet 流量图


4. 经验的归结


5. Flickr 用户模型


6. 浏览器之战


7. 垃圾信息阅读报告


8. 网络文章的生命周期


9. 在线沟通地图


10. 用 1001 个 Web2.0 标志组成的世界地图


11. 全球海底光缆地图


12. SEO毒药

13. Google PageRank 之视觉解释

14. 用社会媒体开一间公司

15. SEO 清单

16. 博客文章的生命周期


17. 软件战势图


18. 美国网民结构图


19. 看看1600万色的模样


20. 可视化表示方式周期表


21. Internet 周期表


22. 国家编码地图

23. 苹果产品分布图


24. 美国 50年来消费电子市场与价格分布


25. Yahoo 所有 API 与服务分布图


26. 数字存储媒介的重量与尺寸


27. 同国家不同时期对色彩的喜好


28. Facebook vs. Twitter

本文国际来源:http://www.webdesignerdepot.com/2009/06/25-useful-infographics-for-web-designers/ 中文翻译来源:COMSHARP CMS 官方网站

Posted in 其它, 分析报告.

Tagged with .


数据之美(下)[转]

数据是抽象的,尤其是海量数据,人的大脑很难直接对大量数据进行分析并获得印象,然而从另一个角度看,数据也可以异常美丽,人们设计了很多工具,让枯燥的数据图形化,本文介绍了50个数据图形化工具,它们以令人难以置信的方式让我们看到了数据美丽的一面。这是本文档第二部分,第一部分请参阅数据之美(上)。

其它

Visualizing Information Flow in Science

显示学术刊物被引用的关系,借此评价一份学术刊物的份量。  

Micro Fashion Network: Color

该图显示了时装风格的持续变化,尤其是基本的色彩元素。使用一架固定相机加专业软件拍摄并分析剑桥大学里面人们的服装颜色。  

TED Sphere

将 TED 大会的视频以 3D 形式展示在一个球体上,你可以从内部或外部观看这个球体,视频的摆放基于语义关联。  

Visualizing The Bible

圣经中63000个相互引用的行文关系,纯粹为了显示一种漂亮效果。  

Walrus

在一个 3D 界面中通巨量图形进行交互。选择一个节点,让图形以该点位中心放大。  

We Feel Fine

这是一个很有趣的数据可视化工具,显示某一天博客圈的总体情绪,你可以根据年龄,地点,性别,天气等进行筛选,该图反映了互联网当前的情绪。  

One Week of The Guardian

展示了英国 Guardian 报一周来所有文章的关系,标题,作者,页数以及目录。  

Nemulator

一个心理模拟项目。  

Voyage

一个基于 Web 的 RSS 阅读器,在时间轴上可视化显示你的 RSS 订阅。  

Blooming Numbers

该项目旨在研究不同文化背景下人们对不同数字的偏好。  

CIA World Factbook Visualization

根据 CIA 数据,显示不同国家之间的关系,包括邻国,语言,水源以及疆界等。  

TextArc Visualization of The History of Science

《科学史》一书的结构图。  

Newspaper Map

没看明白,原文链接已经失效 – 译者。  

GraphNews

Libero WebNews 推出的新闻可视化浏览器。  

Newsmap

显示 Google News 当前新闻标题,显示不同新闻之间在不同文化下的关系。  

FreeMind

一个基于 Java 的工具,可以让用户快速建立数据可视化应用,生成的数据地图可以输出到 XHTML 格式的文件。  

Resource System Reference Database

曾作为 IEEE 2004 年会 InfoVis2004 的海报,该图中,曲线的粗细代表关系的强弱。  

Is the New

大量某某某是新的某某某一类的句式,如“紫色是一种新式粉红”,“技术是一种新式宗教”。  

WikiMindMap

以结构地图的形式显示 Wiki 内容。  

How Scientific Paradigms Relate

显示了大约700个科学范例之间的关系,以及他们是如何被超过80万篇科学论文所涉及。  

Universe

某个搜索条目的复杂而海量的可视化结果。  

visualcomplexity.com

众多数据库可视化图标的总汇,包括商业,艺术,互联网,知识网络,生物,交通,社会等。  

The Strengths of Nations

10个不同国家的科学水平可视化展示,包括美国,英国,法国,中国,澳大利亚等,分23个不同领域,包括数学,生物学,天文学等。 本文国际来源: http://www.webdesignerdepot.com/2009/06/50-great-examples-of-data-visualization/ 中文翻译来源: COMSHARP CMS 官方网站

Posted in 其它, 分析报告.

Tagged with .


数据之美(上)[转]

数据是抽象的,尤其是海量数据,人的大脑很难直接对大量数据进行分析并获得印象,然而从另一个角度看,数据也可以异常美丽,人们设计了很多工具,让枯燥的数据图形化,本文介绍了50个数据图形化工具,它们以令人难以置信的方式让我们看到了数据美丽的一面。这是本文档第一部分

音乐相关

Narratives 2.0

将不同声轨的音乐用该系统进行分析,下面是贝多芬第五交响曲的样子。

 

Liveplasma

输入乐队,歌手,电影,演员的名字,该工具会帮你列出他们之间的关联。

 

Tuneglue

输入任何歌手或乐队的名字,点搜索,可以以该乐队或歌手为中心向外扩展,找到与之关联的更多资料。

 

MusicMap

和 TuneGlue 的界面类似,搜索一个乐队或歌手,会列出他们全部专辑,选中一个专辑,并以此为中心可以发现更多相关专辑和资料。

 

Last.Forward

一个可下载的,开源工具,用来分析 Last.fm 用户的社会网络。

 

Fidg’t

一个桌面工具,根据 Flickr 和 Last.fm 中的 Tag 分析你的 Web 活动倾向。

 

Digg, Twitter, Delicious, Flickr 相关

Looks Del.icio.us

Delicious 的书签分析图形,基于 python 下的一个图形库。

 

Arc

来自 Digg 实验室的一个产品,显示最新的 Diggs 及那些发布和分享这些 Digg 的用户关系。

 

Stack

Digg 提供的最实际用的数据分析工具,实时显示 Digg 当前的活动状况,什么文章最受欢迎等。

 

Swarm

Digg 实验室出品的分析工具中,用户界面较好的一个,文章和用户分散到屏幕上,当某人 Digg 了一篇文章,这个用户就会飞到那篇文章旁边并建立链接,还可以将这个工具作为屏保安装。

 

Research Chronology

在学生本学期的功课和 Delicious 书签之间建立关联,该项目将继续包括的书签站点超过270个。

 

TwittEarth

在一个 3D 地球模型上实时显示 Twitter 全球活跃状况,显示 Twitter 上那些 Tweets 来自什么地区,什么地区的人在跟。只是坐在那里观赏也很奇妙。

 

Tag Galaxy

搜索 Flickr 的标签,并将它们显示在一个虚拟的星系中。

 

Flickr Related Tag Browser

搜索 Flickr 标签与相关标签,点击不同标签,显示相关标签,点击选中的标签,可以看到该标签下对应的 Flickr 图片库。

 

Internet 分析

Mapping the Blogosphere

全球博客圈的分布图。

 

Twingly Screensaver

全球博客圈的实时活跃状况图。

 

Web Trend Map 4

显示当前全球网络在线趋势图,目前是第四版。

 

The Bloom Diagram

来自 IBM Watson 研究中心的一个项目,显示开源项目的活跃状况。

 

Akami Real-time Web Monitor

在一张世界地图上实时显示全球互联网流量,以及当前网络攻击状况,使用颜色区分不同活动。

 

Mapa de Conocimiento (Map of Knowledge)

对某些课题的知识分布图,基于 Flash,将一些主要课题的链接地址组织到一起,目前只有英文和西班牙文版本。

 

Akami Network Performance Comparison

显示不同城市之间互谅网连接速度及丢包情况。(可以帮我们验证世界上最远的距离不是北京和纽约,而是网通和电信,现在是联通和电信)

 

Internet Health Report

使用网格,显示全球主要 ISP 和骨干网之间潜在的丢包以及网络活动状况。

Hierarchical Structure of the Internet

显示了 Internet 是如何组织的,可以看到,Internet 的核心是大约80个主要节点,不过即使这些核心节点出现故障,其余的70%的节点也会以点对点模式继续保持 Internet 运转。

 

Rootzmap—Mapping the Internet

Internet 地图。由 NASA 提供, Philippe Bourcier 设计。

 

Websites as Graphs

显示一个网站源代码中的标签地图,不同颜色代表不同标签,比如蓝色代表链接,红色代表 table。

 

Schemaball

SQL 数据库结构图,基于表之间的外键,显示表间的关联。

 

Opte Project

显示世界上所有 C 网段结构图,目的是为全球互联网建立一个完整的地图。

本文国际来源:http://www.webdesignerdepot.com/2009/06/50-great-examples-of-data-visualization/ 中文翻译来源:COMSHARP CMS 官方网站

Posted in 其它, 分析报告.

Tagged with .


Sphinx搜索语法

参考:http://www.coreseek.com/uploads/pdf/sphinx_doc_zhcn_0.9.pdf

1.匹配模式 有如下可选的匹配模式:

  • SPH_MATCH_ALL, 匹配所有查询词(默认模式)
  • SPH_MATCH_ANY, 匹配查询词中的任意一个
  • SPH_MATCH_PHRASE, 将整个查询看作一个词组,要求按顺序完整匹配
  • SPH_MATCH_BOOLEAN, 将查询看作一个布尔表达式
  • SPH_MATCH_EXTENDED, 将查询看作一个Sphinx内部查询语言的表达式

还有一个特殊的“完整扫描”模式,当如下条件满足时,该模式被自动激活:

1. 查询串是空的(即长度为零)
2. docinfo 存储方式为extern

在完整扫描模式中,全部已索引的文档都被看作是匹配的。这类匹配仍然会被过滤、排序或 分组,但是并不会做任何真正的全文检索。这种模式可以用来统一全文检索和非全文检索的 代码,或者减轻SQL服务器的负担(有些时候Sphinx扫描的速度要优于类似的MySQL查 询)

2. 布尔查询 布尔查询允许使用下列特殊操作符:  显式的与(AND)操作符 hello & world  或(OR)操作符 hello | world  非(NOT)操作符 hello -world hello !world  分组(grouping) ( hello world ) 以下是一个使用了如上全部操作符的例子:

布尔查询示例 ( cat -dog ) | ( cat -mouse)

与(AND)操作符为默认操作,所以“hello world”其实就是“hello & world” 或(OR)操作符的优先级高于与操作符,因此“lookingfor cat | dog | mouse”意思是”looking for ( cat | dog | mouse )” 而不是 “(looking for cat) | dog | mouse” 像“-dog”这种查询不能被执行,因为它差不多包括索引所有文档。这既有技术上的原因, 也有性能上的原因。从技术上说,Sphinx并不总是保持一个全部文档ID的列表。性能方面, 当文档集非常大的时候(即10-100M个文档),对这种执行查询可能需要很长的时间。

3. 扩展查询 在扩展查询模式中可以使用如下特殊操作符:  或(OR)操作符 hello | world  非(NOT)操作符 hello -world hello !world  字段(field)搜索符: @title hello @body world  词组搜索符 “hello world”  近似搜索符 “hello world”~10  阀值匹配符 “the world is a wonderful place”/3 下例使用了上述大多数操作符:

扩展查询示例 “hello world” @title “example program”~5 @body python -(php|perl) 与(AND)操作为默认操作,因此“hello world”意思是“hello”和“world”必须同时存在文档才 能匹配。 或(OR)操作符的优先级要高于与操作符,因此”looking for cat | dog | mouse” 意思 是”looking for ( cat | dog | mouse )” 而不是”(looking for cat) | dog | mouse”; 近似距离以词为单位,随词数变化而变化,并应用于引号中的全部词。举个例子,”cat dog mouse”~5 这个查询的意思是必须有一个少于8个词的词串,它要包含全部的三个词,也就 是说”CAT aaa bbb ccc DOG eee fff MOUSE” 这个文档不会匹配这个查询,因为这个词串正好 是8个词。 阀值匹配符引入了一种模糊匹配。它允许至少含有某个阈值数量个匹配词的文档通过。上述 例子(”the world is a wonderful place”/3)会匹配含有指定的六个词中的至少三个的那些文档。 类似如下查询中嵌套的括号 aaa | ( bbb ccc | ( ddd eee ) ) 目前还是不允许的,但是这会在今后得以改进。 取否(也就是非(NOT)操作符)只允许用在最外一层且不能在括号(也就是分组)里。这 个特性不会改变,因为支持嵌套的非操作会大大提高词组相关度计算实现的复杂性。

4. 权值计算 采用何种权值计算函数(目前)取决于查询的模式。 There are these major parts which are used in the weighting functions: 权值计算函数进行如下两部分主要部分:

  1. 词组评分
  2. 统计学评分 词组评分根据文档和查询的最长公共子串(LCS,longest common subsequence)的长度进行。 因此如果文档对查询词组有一个精确匹配(即文档直接包含该词组),那么它的词组评分就 取得了可能的最大值,也就是查询中词的个数。 统计学评分基于经典的BM25函数,该函数仅考虑词频。如果某词在整个数据库中很少见 (即文档集上的低频词)或者在某个特定文档中被经常提及(即特定文档上的高频词),那 么它就得到一个较高的权重。最终的BM25权值是一个0到1之间的浮点数。 在所有模式中,数据字段的词组评分是LCS乘以用户指定的数据字段权值。数据字段权值 是整数,默认为1,且字段的权值必须不小于1。 在SPH_MATCH_BOOLEAN模式中,不做任何权重估计,每一个匹配项的权重都是1。 在SPH_MATCH_ALL和SPH_MATCH_PHRASE模式中,最终的权值是词组评分的加权和。 在SPH_MATCH_ANY模式中,于前面述两模式的基本思想类似,只是每个数据字段的权重 都再加上一个匹配词数目。在那之前,带权的词组相关度被额外乘以一个足够大的数,以便 确保任何一个有较大词组评分的数据字段都会使整个匹配的相关度较高,即使该数据字段的 权重比较低。 在SPH_MATCH_EXTENDED模式中,最终的权值是带权的词组评分和BM25权重的和,再 乘以1000并四舍五入到整数。 这个行为将会被修改,以便使MATCH_ALL和MATCH_ANY这两个模式也能使用BM25算 法。这将使词组评分相同的搜索结果片断得到改进,这在只有一个词的查询中尤其有用。 关键的思想(对于除布尔模式以外的全部模式中)是子词组的匹配越好则评分越高,精确匹 配(匹配整个词组)评分最高。作者的经验是,这种基于词组相似性的评分方法可以提供比 任何单纯的统计模型(比如其他搜索引擎中广泛使用的BM25)明显更高的搜索质量。

5. 排序模式 可使用如下模式对搜索结果排序:  SPH_SORT_RELEVANCE 模式, 按相关度降序排列(最好的匹配排在最前面)  SPH_SORT_ATTR_DESC 模式, 按属性降序排列 (属性值越大的越是排在前面)  SPH_SORT_ATTR_ASC模式, 按属性升序排列(属性值越小的越是排在前面)  SPH_SORT_TIME_SEGMENTS 模式, 先按时间段(最近一小时/天/周/月)降序,再按 相关度降序  SPH_SORT_EXTENDED 模式, 按一种类似SQL的方式将列组合起来,升序或降序排 列。  SPH_SORT_EXPR 模式,按某个算术表达式排序。 SPH_SORT_RELEVANCE忽略任何附加的参数,永远按相关度评分排序。所有其余的模式 都要求额外的排序子句,子句的语法跟具体的模式有关。SPH_SORT_ATTR_ASC, SPH_SORT_ATTR_DESC以及SPH_SORT_TIME_SEGMENTS这三个模式仅要求一个属性名。 SPH_SORT_RELEVANCE模式等价于在扩展模式中按”@weight DESC, @id ASC”排序, SPH_SORT_ATTR_ASC 模式等价于”attribute ASC, @weight DESC, @id ASC”,而 SPH_SORT_ATTR_DESC 等价于”attribute DESC, @weight DESC, @id ASC”。 SPH_SORT_TIME_SEGMENTS模式 在SPH_SORT_TIME_SEGMENTS模式中,属性值被分割成“时间段”,然后先按时间段排 序,再按相关度排序。 时间段是根据搜索发生时的当前时间戳计算的,因此结果随时间而变化。所说的时间段有如 下这些值:  最近一小时  最近一天  最近一星期  最近一个月  最近三个月  其他值 时间段的分法固化在搜索程序中了,但如果需要,也可以比较容易地改变(需要修改源码)。 这种模式是为了方便对Blog日志和新闻提要等的搜索而增加的。使用这个模式时,处于更 近时间段的记录会排在前面,但是在同一时间段中的记录又根据相关度排序-这不同于单纯 按时间戳排序而不考虑相关度。 SPH_SORT_EXTENDED 模式 在 SPH_SORT_EXTENDED 模式中,您可以指定一个类似SQL的排序表达式,但涉及的属 性(包括内部属性)不能超过5个,例如: @relevance DESC, price ASC, @id DESC 只要做了相关设置,不管是内部属性(引擎动态计算出来的那些属性)还是用户定义的属性 就都可以使用。内部属性的名字必须用特殊符号@开头,用户属性按原样使用就行了。在上 面的例子里,@relevance和@id是内部属性,而price是用户定义属性。 已知的内部属性:  @id (match ID)  @weight (match weight)  @rank (match weight)  @relevance (match weight)  @id(匹配的ID)  @weight(匹配权值)  @rank(匹配权值)  @relevance(匹配权值) @rank和@relevance只是@weight的额外别名。 SPH_SORT_EXPR 模式 表达式排序模式使您可以对匹配项按任何算术表达式排序,表达式中的项可以是属性值,内 部属性(@id和@weight),算术运算符和一些内建的函数。例如: $cl->SetSortMode ( SPH_SORT_EXPR, “@weight + ( user_karma + ln(pageviews) )0.1″ ); 支持的运算符和函数如下。它们是模仿MySQL设计的。函数接受参数,参数的数目根据具 体函数的不同而不同。  Operators: +, -, , /, =, =, .  Unary (1-argument) functions: abs(), ceil(), floor(), sin(), cos(), ln(), log2(), log10(), exp(), sqrt().  Binary (2-argument) functions: min(), max(), pow().  Ternary (3-argument) functions: if().  运算符: +, -, , /, =, =, .  一元函数(一个参数):abs(), ceil(), floor(), sin(), cos(), ln(), log2(), log10(), exp(), sqrt().  二元函数(两个参数):min(), max(), pow().  三元函数(三个参数):if(). 全部的计算都以单精度32位IEEE754浮点数进行。比较操作符(比如=和<=)在条件为真 时返回1.0,否则返回0.0。例如(a=b)+3在属性“a”与属性“b”相等时返回4,否则返回 3。与MySQL不同,相等性比较符(即=和)中引入了一个小的阈值(默认是1e-6)。 如果被比较的两个值的差异在阈值之内,则二者被认为相等。 全部的一元和二元函数的意义都很明确,他们的行为跟在数学中的定义一样。但IF()的行为 需要点详细的解释。它接受3个参数,检查第一个参数是否为0.0,若非零则返回第二个参 数,为零时则返回第三个参数。注意,与比较操作符不同,IF()并不使用阈值!因此在第一 个参数中使用比较结果是安全的,但使用算术运算符则可能产生意料之外的结果。比如,下 面两个调用会产生不同的结果,虽然在逻辑上他们是等价的: IF ( sqrt(3)sqrt(3)-30, a, b ) IF ( sqrt(3)sqrt(3)-3, a, b ) 在第一种情况下,由于有阈值,比较操作符返回0.0(逻辑假),于是IF()总是返回 ‘b’。在第二种情况下,IF()函数亲自在没有阈值的情况下将同样的 sqrt(3)sqrt(3)-3与零值做比较。但由于浮点数运算的精度问题,该表达式的结果与 0值会有微小的差异,因此该值与零值的相等比较不会通过,上述第二种情况中IF()会返 回‘a’做为结果。

6. 结果分组(聚类) 有时将搜索结果分组(或者说“聚类”)并对每组中的结果计数是很有用的-例如画个漂亮 的图来展示每个月有多少的blog日志,或者把Web搜索结果按站点分组,或者把找到的论 坛帖子按其作者分组。 理论上,这可以分两步实现:首先在Sphinx中做全文检索,再在SQL服务器端对得到的ID 分组。但是现实中在大结果集(10K到10M个匹配)上这样做通常会严重影响性能。 为避免上述问题,Sphinx提供了一种“分组模式”,可以用API调用SetGroupBy()来开启。 在分组时,根据group-by值给匹配项赋以一个分组。这个值用下列内建函数之一根据特定的 属性值计算:  SPH_GROUPBY_DAY,从时间戳中按YYYYMMDD格式抽取年、月、日  SPH_GROUPBY_WEEK,从时间戳中按YYYYNNN格式抽取年份和指定周数(自年 初计起)的第一天  SPH_GROUPBY_MONTH,从时间戳中按YYYYMM格式抽取月份  SPH_GROUPBY_YEAR,从时间戳中按YYYY格式抽取年份  SPH_GROUPBY_ATTR,使用属性值自身进行分组 最终的搜索结果中每组包含一个最佳匹配。分组函数值和每组的匹配数目分别以“虚拟”属 性@group和@count的形式返回。 结果集按group-by排序子句排序,语法与SPH_SORT_EXTENDED 排序子句的语法相似。除 了@id和@weight,分组排序子句还包括:  @group(groupby函数值)  @count(组中的匹配数目) 默认模式是根据groupby函数值降序排列,即按照“@group desc” 排序完成时,结果参数total_found会包含在整个索引上匹配的组的总数目。 注意:分组操作在固定的内存中执行,因此它给出的是近似结果;所以total_found报告的数 目可能比实际给出的个分组数目的和多。@count也可能被低估。要降低不准确性,应提高 max_matches。如果max_matches允许存储找到的全部分组,那结果就是百分之百准确的。 例如,如果按相关度排序,同时用SPH_GROUPBY_DAY函数按属性“published”分组,那 么:  结果中包含每天的匹配结果中最相关的那一个,如果那天有记录匹配的话。  结果中还附加给出天的编号和每天的匹配数目  结果以天的编号降序排列(即最近的日子在前面)

7. 分布式搜索 为提高可伸缩性,Sphnix提供了分布式检索能力。分布式检索可以改善查询延迟问题(即缩 短查询时间)和提高多服务器、多CPU或多核环境下的吞吐率(即每秒可以完成的查询 数)。这对于大量数据(即十亿级的记录数和TB级的文本量)上的搜索应用来说是很关键 的。 其关键思想是将待搜索数据做水平分区(HP,Horizontally partition),然后并行处理。 分区不能自动完成,您需要:  在不同服务器上设置Sphinx程序集(indexer和searchd)的多个实例  让这些实例对数据的不同部分做索引(并检索)  在searchd的一些实例上配置一个特殊的分布式索引  然后对这个索引进行查询 这个特殊索引只包括对其他本地或远程索引的引用,因此不能对它执行重新建立索引的操作, 相反,如果要对这个特殊索引进行重建,要重建的是那些被这个索引被引用到的索引。 当searchd收到一个对分布式索引的查询时,它做如下操作:

  1. 连接到远程代理
  2. 执行查询
  3. (在远程代理执行搜索的同时)对本地索引进行查询
  4. 接收来自远程代理的搜索结果
  5. 将所有结果合并,删除重复项
  6. 将合并后的结果返回给客户端 在应用程序看来,普通索引和分布式索引完全没有区别。 任一个searchd实例可以同时做为主控端(master,对搜索结果做聚合)和从属端(只做本地 搜索)。这有如下几点好处:
  7. 集群中的每台机器都可以做为主控端来搜索整个集群,搜索请求可以在主控端之间获 得负载平衡,相当于实现了一种HA(high availability,高可用性),可以应对某个 节点失效的情况。
  8. 如果在单台多CPU或多核机器上使用,一个做为代理对本机进行搜索的searchd实例 就可以利用到全部的CPU或者核。 更好的HA支持已在计划之中,到时将允许指定哪些代理之间互相备份、有效性检查、跟踪 运行中的代理、对检索请求进行负载均衡,等等。

8. searchd 日志格式 searchd将全部成功执行的搜索查询都记录在查询日志文件中。以下是一个类似记录文件的 例子: [Fri Jun 29 21:17:58 2007] 0.004 sec [all/0/rel 35254 (0,20)] [lj] test [Fri Jun 29 21:20:34 2007] 0.024 sec [all/0/rel 19886 (0,20) @channel_id] [lj] test 日志格式如下 [query-date] query-time [match-mode/filters-count/sort-mode total-matches (offset,limit) @groupby-attr] [index-name] query 匹配模式(match-mode)可以是如下值之一:  “all” 代表 SPH_MATCH_ALL 模式;  “any” 代表 SPH_MATCH_ANY 模式;  “phr” 代表 SPH_MATCH_PHRASE 模式;  “bool” 代表 SPH_MATCH_BOOLEAN 模式;  “ext” 代表 SPH_MATCH_EXTENDED 模式. 排序模式(sort-mode)可以取如下值之一:  “rel” 代表 SPH_SORT_RELEVANCE 模式;  “attr-” 代表 SPH_SORT_ATTR_DESC 模式;  “attr+” 代表 SPH_SORT_ATTR_ASC 模式;  “tsegs” 代表 SPH_SORT_TIME_SEGMENTS 模式;  “ext” 代表 SPH_SORT_EXTENDED 模式.

Posted in sphinx, 技术.

Tagged with .


Sphinx增量索引

Sphinx+Mysql+中文分词安装

在实际应用中往往有这么一种情况,数据库数据很大,比如我们的歌曲表,如果我们每次都去更新整个表的索引,对系统得开销将非常大,显然这是不合适,这时我们会发现,每天我们需要更新的数据相比较而言较少,在这种情况下我们就需要使用“主索引+增量索引”的模式来实现实时更新的功能。

这个模式实现的基本原理是设置两个数据源和两个索引,为那些基本不更新的数据建立主索引,而对于那些新增的数据建立增量索引。主索引的更新频率我们可以设置的长一些(可以设置在每天的午夜进行更新),而增量索引的更新频率,我们可以将时间设置的很短(几分钟左右),这样在用户搜索的时候,我们可以同时查询这两个索引的数据。

下面,我们通过一个简单的例子来描述一下怎样实现这种模式

以sphinx.conf中默认的数据为例:

1.先在mysql中插入一个计数表和两个索引表

CREATE TABLE sph_counter( counter_id INTEGER PRIMARY KEY NOT NULL, max_doc_id INTEGER NOT NULL );

//主索引使用(确认之前是否已经建立过该表,如果已经建立,这里就不需要重新建了)

CREATE TABLE `sphinx` ( `id` int(11) NOT NULL, `weight` int(11) NOT NULL, `query` varchar(255) NOT NULL, `CATALOGID` INT NOT NULL, `EDITUSERID` INT NOT NULL, `HITS` INT NULL, `ADDTIME` INT NOT NULL, KEY `Query` (`Query`) ) ENGINE=SPHINX DEFAULT CHARSET=utf8 CONNECTION=’sphinx://localhost:3312/test1′

//增量索引使用

CREATE TABLE `sphinx1` ( `id` int(11) NOT NULL, `weight` int(11) NOT NULL, `query` varchar(255) NOT NULL, `CATALOGID` INT NOT NULL, `EDITUSERID` INT NOT NULL, `HITS` INT NULL, `ADDTIME` INT NOT NULL, KEY `Query` (`Query`) )ENGINE=SPHINX DEFAULT CHARSET=utf8 CONNECTION=’sphinx://localhost:3312/ test1stemmed ‘

2.修改sphinx.conf

source src1 { sql_query_pre = SET NAMES utf8 sql_query_pre = SET SESSION query_cache_type=OFF sql_query_pre = REPLACE INTO sph_counter SELECT 1, MAX(id) FROM documents sql_query = SELECT id, group_id, UNIX_TIMESTAMP(date_added) AS date_added, title, content FROM documents \ WHERE id( SELECT max_doc_id FROM sph_counter WHERE counter_id=1 ) } index test1 //主索引 { source = src1 … } index test1stemmed : test1 //增量索引 { source = src1throttled … }

3.重建索引

/usr/local/sphinx/bin/searchd –stop /usr/local/sphinx/bin/indexer –config /usr/local/sphinx/etc/sphinx.conf –all /usr/local/sphinx/bin/searchd –config /usr/local/sphinx/etc/sphinx.conf

插入测试数据

INSERT INTO `test`.`documents` ( `id` , `group_id` , `group_id2` , `date_added` , `title` , `content` ) VALUES ( NULL , ‘3’, ’11’, NOW( ) , ‘索引合并’, ‘合并两个已有的索引比重新对所有数据做索引更有效率,而且有时候必须这样做(例如在“ 主索引+增量索引”分区模式中应合并主索引和增量索引,而不是简单地重新索引“主索引对应的数据)。因此indexer有这个选项。合并索引一般比重新索引快,但在大型索引上仍然不是一蹴而就。基本上,待合并的两个索引都会被读入内存一次,而合并后的内容需要写入磁盘一次。例如,合并100GB和1GB的两个索引将导致202GB的IO操作(但很可能还是比重新索引少)’ );

执行

SELECT doc . * FROM documents doc JOIN sphinx ON ( doc.id = sphinx.id ) WHERE query = ‘索引’

你会发现你刚添加的数据没有被检索出来 然后执行:

SELECT doc.* FROM documents doc join sphinx1 on (doc.id=sphinx1.id) where query=’索引’

你会发现数据是空的,这时我们就需要来更新增量索引了。

通过执行:

/usr/local/sphinx/bin/indexer –rotate –config /usr/local/sphinx/etc/sphinx.conf test1stemmed

命令来更新增量索引(正式使用时,我们可以将该命令配置到系统计划任务中,每隔几分钟执行一次) –rotate: 该参数可以使我们在不需要停止searchd的情况下,直接加载索引 执行完命令该命令后,我们再来查看一下增量索引的数据

SELECT doc.* FROM documents doc join sphinx1 on (doc.id=sphinx1.id) where query=’索引’

你会发现新添加的数据被检索出来的。

主索引的更新:

/usr/local/sphinx/bin/indexer –rotate –config /usr/local/sphinx/etc/sphinx.conf test1 collected 997 docs, 1.4 MB sorted 0.3 Mhits, 100.0% done total 997 docs, 1430054 bytes total 1.428 sec, 1001459.38 bytes/sec, 698.19 docs/sec

(我们可以设置成每天的午夜执行)

只有在更新了主索引后,结果才会被更新

SELECT doc.* FROM documents doc join sphinx on (doc.id=sphinx.id) where query=’索引’

我们也可以通过合并索引的方式使主索引的数据保持更新

/usr/local/sphinx/bin/indexer –merge test1 test1stemmed –rotate

可以将增量索引test1stemmed合并到主索引test1中去

为创建2个shell脚本,一个用来创建主索引、一个用来创建增量索引(此步可以省略)

1.创建主索引脚本build_main_index.sh

#!/bin/sh #/usr/local/sphinx/bin/searchd –stop /usr/local/sphinx/bin/indexer test1 –config /usr/local/sphinx/etc/sphinx.conf >> /var/log/sphinx/mainindexlog #/usr/local/sphinx/bin/searchd

2.创建增量索引脚本build_delta_index.sh

#!/bin/sh #/usr/local/sphinx/bin/searchd –stop /usr/local/sphinx/bin/indexer test1stemmed –config /usr/local/sphinx/etc/sphinx.conf –rotate>> /var/log/sphinx/deltaindexlog /usr/local/sphinx/bin/indexer –merge test1 test1stemmed –config /usr/local/sphinx/etc/sphinx.conf –rotate >> /var/log/sphinx/deltaindexlog #/usr/local/sphinx/bin/searchd

每隔5分钟进行索引增量合并,每天2:30重建索引

*/5 * * * * /bin/sh /opt/shell/build_delta_index.sh > /dev/null 2>&1 30 2* * * /bin/sh /opt/shell/build_main_index.sh > /dev/null 2>&1

每周一至周六上早6点增量合并,同日重建索引

1 6 * * 1-6 /bin/sh /opt/shell/build_delta_index.sh > /dev/null 2>&1 1 6 * * 7 /bin/sh /opt/shell/build_main_index.sh > /dev/null 2>&1

参考: http://www.coreseek.com/uploads/pdf/sphinx_doc_zhcn_0.9.pdf

2009-06-26修订

Posted in sphinx, 技术.

Tagged with , .