细读:关于搜索引擎及其开发,我的疑问和思考

来源:互联网 发布:网络拓扑结构的作用 编辑:程序博客网 时间:2024/05/20 06:29

细读:关于搜索引擎及其开发,我的疑问和思考

原文:http://blog.csdn.net/xwjbs/archive/2007/09/16/1787264.aspx 作者xwjbs
(方括号是援引他的文字)

1.[1. 网页如何尽量不重复的下载。网络带宽资源是有限的,本地硬盘资源也是有限的,下载的时间也是有限制的,重复的下载系统受不了。]
我认为这个应该更正一下:重复下载一个网页是错误的做法。因为某个节点是唯一的。虽然在url的指向上会出现交叉重复。但节点只有一个。所以就不能重复下载。(一个节点可以有无数的内链接和外链接)

2.[我们对Url做md5映射,把它映射成一个64位的整形值。]
我在想,如果其它需要比较或者计算时,比如文件扩展名(.asp;.html)以及domain名称是否也有作MD5的必要?一个url如果domain不同,那地址肯定不同。文件类型不一样,则链接也肯定不一样。不晓得我的这个想法能用到什么地方?
另外一个问题是MD5的计算效率。而且每个url包括如关键字的字串识别都需要用到。

3.[对ID值取模(mod)是一个非常重要的思想]
其实对其它内容。比如下载任务,WordKey我认为分桶都是必要的。因为一个复杂的系统必然有很多组,每个组有很多单元组成。切分是一个全局概念。甚至可能每个地方都要把处理任务进行切分。比如查询也是。唯一不切分的应该是控制台。因为需要一个中心。切分的意义是说小批量任务可以在多个机器,进程,线程同时进行。没有这个概念可以想一想公司工厂的运作就比较形象。公司有多个职能部门,而部门有多个同事,如果比如人事部只有一个人,则容易出现流程挂起。而中心调度比如总经理,只有一个。

4.[都是64位值得比较。最简单的办法,你可以利用平衡二叉树,这是一个非常方便的动态查找的办法。不过,数据量一大,64位值也会占用很多的内存。我们可以算一下。1亿*8约等于800M,而且树节点左右指针也要占8个字节,平衡二叉树还有一个标记变量,这样算下来,放完1亿大约需要1.8G]
我想说存放long64位数据应该不会这么存放吧。因为借鉴lucene中的变长数据类型和索引压缩模式(前向值+偏移量)应该不会要这么大的空间。我突然想,如果用位模式来表示呢?可能还要小。(某个数字成为内存中的bit占位)而对bit容易寻找到偏移量。

inserted at 20071219凌晨
简单的说。比如一段: 1000-1999这1000个数字,如果用int64来表示,则需要8000个bytes,64000个bits,如果数字出现的概率很小,倒用不了多少存储空间,但搜索的url在进入一个预期扫描互联网后,url会趋向于满。比如1000-1999中平时只会存在100个数字,而900个位置是空的,我们可以指定1000的指针,然后其他数字出现时用这个数字比如1050与1000的差异(offset)来表示,也就是压缩了存储空间,可以用一个int16来表示。当然怎么合理划分而不浪费int16能表示的0-65535这么多偏移量,切段是需要精巧设计的。比如2的16次方为一段。正好能最小化存储空间占用。

而如果1000-1999中平时(搜索中,url在一定时间后就会占满或者趋于满),则我想用数来表示,不如用位来表示某个数存在。比如指针指向1000,偏移的第一个byte如果为:10001001则表示1000+1,1000+5,1000+8是存在的。而一个位就可以表示一个数,而且比上面的方法来看,直接用线性地址的偏移来确定值,省去了offset的开销。妙。这就是位模式能表示最大数量的数据而除位模式外,任何数据类型,比如char,wchar_t,int16,int32都是用编码的方式用多位来表示一个数字或字符。
而对位的取得,以及计算偏移因为都是基于地址本身权值和相对偏移方式,然后(unsigned char*)指针取数,然后用bit-mask与操作就可以获得位值。简单的说也就是某个数,比如1050到底存在不?看第6个字节的第2位是否为1,是1就表示1050存在。指针的概念在这里得到最好体现。
现实世界的模型就是标尺。只有起始和刻度,并不用记录每个刻度的数,而只记录偏移。

另外在lucene中作者定义了与语言和机器无关的以byte作为基数长度的基本数据类型和变长数据类型。比如用左边一位(bit)表示后面的数字是否是该位的后继。。妙。对于连一个byte都要精良设计和考虑,只有在搜索中和压缩中。足以显示了人的智慧。

5.[垂直搜索的下载和大搜索的下载是不一样的:难度不可同日而语]
其实角度不一样。我最近跟一个朋友讨论到。其实用户对搜索的要求是变本加厉的。对大搜索要求更新,如果只能作到一个月更新一次,也能接受,但是对垂直搜索又有新要求,比如数据pop,时效性,对比,类聚,准确性。数据量是小了。但也无法做好。

6.下载问题
有五个问题1.某个时刻需要抓某个domain的1000个网页,抓取过于集中,会影响服务器--需要将url_list打散。比如下载10个sina的网页,再下载sohu的十个网页。?
2.分派url时,将其打散。分发给多个电脑处理(包括异地的蜘蛛,这样网络和IP都比较分散。可能也不会引起管理员注意)这涉及到一些简单的算法,但是非常有见地的思想。
3.SEO,场这些问题,需要专门的策略处理。痛杀之。
4.如果遇到某个domain不能访问。我觉得即可丢掉它。将其写入fail_list里。因为就故障和恢复的时效来看。服务器故障至少也需要一个小时。一个小时后再尝试。如果不行,若干小时后再处理,并提示控制台。实在不行,退会去。给人工判定。因为url中有些可能就是无效地址。比如拼写错误。所以必须要高效。
5.关于线程,就打算你开10个线程,服务器也可能只允许一个IP执行3个线程。所以另外七个线程会挂起,或者立即返回一个错误界面。。这个值得想想。如果蜘蛛认为返回了错误
就是算法有问题了。当然如果另外七个线程空等待,也是有问题的。这时应该如派发url一样。尽量打散。

7.[正文解析:1. 基于模板;2. VIPS:基于视觉的Web页面分页算法]
我想模板始终是需要的.一个网不可能天天换格式。关键是,如果某个时刻改编了,不能抽取或者抽取的数据成了垃圾信息。怎么发现?怎么检查抽取数据的正确性?
视觉倒不如说是基于段落。我觉得html标签里很好判断段落。而且段落比较长。有的人说将比较短的数据都去掉。但基于视觉真的很难说。再说技术和格式层出不穷。倒不是说算法有多难。而是千差万别造成程序的困惑。

8.排重
这个难题我想就是首先不晓得哪个网站的跟哪个网站的重复。可能对标题或者首段落处理能得到一个疑似判断。当然我注意到一个问题,就是有些机器自动抓取的文章,抓得不完整有头无尾。可能算法就会出错。当中,我认为标题,关键字。高频字词(google采用得方法),以及段落首尾,加上随即抽样,可能都有助判断。但因为要遍历很多。所以只能用折衷得速度快得处理方法。

9.基于链接分析
这个pagerank曾经名燥一时。但是在现在也出现很多弊病。比如SEO,链接场。改进得有权重的rank也没有改善这种情况。可能对网页质量的评定还是需要人工的反馈结合。以及网页停留时间等。
在垂直搜索方面。更多的需要行业的特性值。加上时效性如发布时间,地域优先,用户喜好优先等。
很多半吊子垂直网站把VIP会员的网站排在最前面,有失公允。是恶劣的。

10.快照
大搜索的困难在于下载一次文件。所以会特别珍惜的保存文件。而垂直搜索数量比较少。更新周期短。有的能作到几个小时一次。而且因为有抽取过程。或许并不需要保存文件。

我的看法简直可以作完索引和概要之后删除以节省空间。比如对招聘的信息,我作了全文检索,而且抽取了必要内容,则整个页面就可以删除了。

11.分词
第一。词典的完整性。如果没有农产品专用词典。估计很难对苦瓜凉瓜,太阳花,向日葵这样书名,学名,俗名作切词。所以词典齐全是个问题。另外某篇文章你怎么决定该主要利用哪个词典?是否要先用通用词典切词。剩下不能切的,再找可能的词典来切?
第二。比如一句话:我们都知道氯化钠俗名叫食盐。在这个句子,或者整个文章讲的都是盐或者食用盐的问题。但是我们看到这样一片文章。里面切出的通用词比如"我们","知道",其实是与文章主题没有任何专业联系的。除了”的,地,得“应该算停止词外,我认为与文章意义不相关的通用词我们也应该忽略。比如用户查询”我们“或者"知道”这个词,我们给出一篇食盐的文章似乎有点牵强。
第三。新词发现。对于不能切分的字块。也就是发现很多字会无独有偶的结合在一起,那就是新词的萌芽。比如原文中提到的“鲁棒”,在开发时,大家可以想想,你有没有方法去发现这个新词?似乎不能,采用什么算法也难于发现,因为这个词在一片文章里可能就出现两次而已。这就想到一个人工提报的问题。就是居于统计原则,把疑似的字块交给人去判断。

//append@20071219

突然在看blog-log发现一些用户访问时提交的关键字。另外发现一些CSDN的蜘蛛对文章的全文检索规律,突然引申到新词发现:1. 学习和统计(需要针对不同专业,当然论文和新闻是比较好的源);2. 用户提交的tag和查询关键字中当前字典中没有的,将其归类到新词里,比如"WTO+谈判+进展",当字典里没有WTO时,我们只能切出"谈判","进展"但我们知道人工提交都是一些keyword,所以"WTO"可以再由机器或人工确认。3.垂直搜索因为趋向于精确内容,肯定有编辑人员参与,而且他们有一定专业知识,能整理和发现一些新词。4.切词时经常出现单字的情况,可以归类提报人工,比如上面提到的"鲁棒性"如果没有加入新词,总是会切出三个单字:鲁-棒-性。而在汉字中(文言文除外)词语是以双字居多。而常用的单字只是一些stop word比如"的","还","和"等。如果出现名词或者形容词那多半出现新派生词的概率比较大。

//apend@20071230

有这样一句话:人行上海总部提醒贷款人士
这种"人行"的简写在上下文由人识别时是没有一点问题,不过在机械分词处理上就是个大问题。我们在论文里,在其他的一些文章里,也经常会看到"以下简称为什么什么..",这样的简称具有比较短的有效性。

12.[当然,在全面的解决办法临之前,并不是说我们就堵在这里就没有办法前进了]
这一段的内容其实发人深思。因为技术的确是一个公司的决胜资本。但也并不全是,而且还不是主要因素。发人深思啊。昨天碰到一个北京的朋友想搞垂直搜索。我说。这个问题太复杂了。技术是门槛,而且还不是一天两天的事。而且就算有技术,离成功还远得很。所以最后我告诉他。试验,尝试是可以的。但是不要觉得自己的钱在往外蹦。也许他在这个过程中会熟悉这个行业的水有多深。
这当中也体会到一个服务细化和深化的过程。以前满足机器搜索。现在还有社区,wiki模式,论坛,博客,应该所有提供知识的都应该会归结到搜索,搜索才算能提供完善服务。
比如一个朋友他在开发一个前所未有的技术。我估计搜索里绝对没有他需要的资料。但是通过社区,他可以结识朋友,可以得到支持。因为搜索不生产知识。这是必须要明白的。

13.[多个机器之间的合作:这个时候,一组机器都是统一去做的,你就得将就那个最“无能的”。呵呵。典型的木桶理论的诠释。]
我想阐述的是:如果一个任务只能固定一台机器,而且任务不可拆分,或者只能有前到后,那就没有办法。否则如果可以切分,理论上我们应该避免最短板的问题。我想现在的机器,服务器都是配置非常好的。所以不存在切分小了的任务不能运行在配置低的机器上。我认为长期的测试和运行,居于统计,会得出一个经验的调度值,使得机器的桶板一致,或者基本一致。为什么这么自信的认为呢?因为现实世界里有复杂的现代化分工协作,有效率很高的流水生产线。有正常调度和异常处理机制,当生产出现缺料时,还有提前预处理组装等变通方法,来达到最短交货期。则在计算机也应该可以模拟这种算法。只是个逐渐完善的过程。在电路中有负反馈控制和自动增益,在工厂,生产任务可以根据订单的交期以及材料到位的情况作灵活而准确的调整,车间的指令或者流水线的指令也是在不断调整的。目标就是最小库存和最短交货期。而计算机在搜索中自然也能作一些低端的模拟。只要大致平衡即可。

#另外一个需提出的问题是:如果50台spider需要48Hour才能下载完一次,而5台电脑5Hour可以作出索引,那平时这5台专门作索引的电脑是否一直开着?即使开着也要到50Hour后才能有新索引出来,那怎么解决这个问题?值得研究。

14.[如果他们没有都做完你指定动作,你就不能要求他们做下一步动作]
也就是不能制造错误,引入垃圾,数据库中有所谓脏读。实际就造成了错误了。就会一直错下去并导致后续的连锁反映.当然系统复杂后,这个错误可能要到很久才会发现。所谓错上加错。比如词典错了。那切词就是错的。

15.[监控端,关于他的有个名词叫做心跳。你在看其他的资料的时候会看到这个。每一个间隔都向服务器端报告自己的状态(通过socket)。一般是间隔一秒。呵呵。其他的也没有什么可以说的,本来是一个简单的东西。]
我倒觉得没必要说1S/次。因为繁重的任务下,1S根本作不了什么。觉得5-10分钟报告一次足够,当然像服务与查询端的机例外。因为他们可能向客户投送错误或者拒绝的错误。
而蜘蛛申请一次url估计也要下载很久,所以也没必要时时汇报。

16.cache技术。
如果没有cache技术。google不能接受一天上亿次查询。他的服务器足够当机十万次。
因为从索引里检索数据特别慢。特别是如果你要下翻到100页。检索是没有起始点的,每次检索都是一样的,只是返回的段不同。我们可以在google里检索一个生僻词。可以发现需要很久才返回。

例子:白领裸照事件。
我在想,cache技术应该分两层或者三层。如果关键词被命中,他会进入cache服务器,但地位不高,如果某个时段检索突然命中很多次。则它可能进入能快速反映的地方,比如一级cache。而且"白领裸照事件",用户可能只输入"白领"或者"裸照",或者"裸照事件"或者"白领事件"那保存三个词的cache比保存三个词组合起来的列表,更能容易命中检索。而这些cache我认为也可以存在硬盘中。(或者专门的cache服务器),因为我想,直接读一个列表总比重新检索快。

然后cache的清除也基于一定的策略。比如渐渐没人查询了,根据单位时间的命中,决定去留。据说google能保留七天以上。是足够厉害的。

17.[Strlen. Strlen函数是用的很多的函数,你可测试过他的时间耗费?每调用一次,程序都需要遍历一次你的字符串,直到碰到0为止。]
现在很多人包括自己。早忘记了效率,比如:
for(int i=0;i<obj.size();i++){
 do it;
}
//很多人习惯了。不会在乎效率了。其实最敏感的部分我觉得就是循环,应该精确到一个变量是否需要初始化赋值。节省到这个程度。才能使得效率最高。
另外引伸一点就是正则。执行一次。几乎就是要扫描一次。我觉得是否自己处理:比如寻找文本是否存在("abc","cba","bac",bac")用正则,估计效率就很低。而扫描出所有“a”,“b”,“c”开头得的出现位置。并取得三个字长的word进入数组,在数组中在查找,势必快很多。

继续第二篇SD2C之后写的:

http://blog.csdn.net/xwjbs/archive/2007/12/16/1941467.aspx

18.[在一个我们认为运行时间超出了我们预定值的系统里边,明确的知道,那一个或者是哪些步骤是耗费的时间最多!]
我目前还没体会。但是曾经作的一个电讯报表系统需要缓存省公司FTP数据并导入到本地数据库。理想模式是没有任何错误。但是实际情况非常难受。比如FTP文件没按时导出来,或者文件里错误,或者文件根本没更新。所以后台处理程序我写了完整日志。包括进入处理的时间,处理的行数,返回值,忽略的错误等。当然搜索要记录一些日志我认为还有个原因是平衡负荷。就是看一个服务器或者一个组的负荷程度。长期统计就能算出它的产能(制造业术语,此借用一下),产能的倒数就是它的效率。借此数据我想能有办法平衡机器间的负荷。使得桶板平衡。一个程序或者一个函数处理一定量数据是基本恒定时间的,但有时一次可能有100个文件处理,而有时会是500个文件而就有必要统计时间,文件个数,处理单元数,对于平衡负荷,优化算法,改进效率应该都是参考。

19.硬盘读写瓶颈。
google最先放出信息说他们的程序是强大的,而瓶颈是IO,所以这个知识点不算新。尽量合适的buffer和减少读写次数。(lucene索引时有个Ram索引模式,然后有先作小索引,既而合并,我想都是考虑磁盘IO.),还有就是尽量将同时读写的文件放在不同硬盘上。这些原则都不是新原则了。现在几个G的内存一定程度上减少读盘次数应该也是应该也是一个改善。我还有一个想法就是像google这些是否应该专门制造大容量的RAM缓冲设备来代替物理硬盘,文件操作尽量在全硬件的RAM或者内存文件上操作。不晓得有没有这样的设备。以现在RAM的价格,完全可以制造比硬盘还大的RAM组,那操作速度是非常快的。或许他们已经定制了这样的设备。(纳秒级)google将文件块定义得比较大,也是居于读取速度考虑的。但是估计国内还没有这些尝试。只能抱怨磁盘太慢。

//append@071220

另外一个考虑的就是能否把读写分布在不同的机器上去执行。用多台机器来模拟硬盘矩阵。因为在一台电脑内作随机或者大面积读写,CPU,MDA,硬件接口都会是一个问题。那能否通过网络在其他地方分散读取和写入。比如同时需要ABC三块数据,本机存放的是A块。读A块时向其他电脑发送预读B,C块内容到内存,等本机读完A块时,再从另外两台获得B,C块内容。现实中如到仓库申请物料,通知单给一个仓管,他需要分别在十个仓库按顺序备好十种材料,而同时把领料单通知到十个仓管,会在一个单位时间同时备好,而先备好的材料就可以先用,其他物料能第二时间到位。大任务的模式就在大而化之,分而治之,我想应该在整个思路中贯穿这种思想。

另外一个考虑就是读写的顺序安排:如果ABC三个环节,A,B环节是比较耗时的环节,但任务比较轻,而在C环节需要调入一个300M的文本,那应该能在A,B环节的空档就预先读入C环节所需的文件,在内存比较小的PC机上运行程序时,我们总是小心翼翼的节省内存并及时释放资源,而在内存上8G-16G的大内存机器上,我认为只要不设计成用到什么文件才想起读什么文件,是可以一定程度上避免无计划的读写。如果一定要实时的读写文件,再快的硬盘应该也是瓶颈,因为硬盘的速度跟CPU,跟缓存,跟内存实在不在一个级别上。当然这在一定程度上会打乱我们按顺序编程和执行的既有思路。实际上机械的读取速度再怎么优化,始终是无法快速提升的,有的人想方设法榨干硬件的潜力,但都不如改进算法和程序架构来的实在。而且硬盘本身也没多少提升的空间。像Google一样还要考虑使用普通硬盘。并不是读写速度最快,缓存最大的高档硬盘,软件在其中的作用就更大了。

20.搜索引擎为什么不用数据库
其实我经过这么久算想明白了。搜索用到的是基于文件的索引方式。跟关系数据库扯不上关系。搜索就是编制字典的过程。与关系数据库没有任何关系。
而最近出现的垂直搜索。倒不排除将数据放入关系数据库中的形式。因为抽取出来的数据是格式统一的.而且查询形式与关系数据库很接近。不同的是对字符字段还要进行倒排索引。当然,数据量小也是另外一个方面。在搜索中,索引就是它特殊的数据库,只不过每个作的人有自己的特殊做法,可以不受到关系数据库的局限。而且关系数据库对大块头数据管理效率,存放杂乱也是不行的。

//-------------------------------------------------------------------------------------------------------------------------------------------------

#另外我想补充的一点就是搜索应该对语言特殊性的处理上有一个分层(或抽象多一层)。就是说算法独立于语言。对不同的语言提供不同的处理接口。还有我国周围的亚洲语言环境,或许在未来还有拓展的必要,因为汉语解决了一些问题,应该能运用到其他非英文语系。但我们认识到,除了切词和表示法不同外,处理思路应该是一样的。只是实现时需要非常注意。

#20080106今天在看<<软件技术基础(电子科技大学)>>里讲到操作系统的缓冲池,设备管理,通道,假脱机,主存等技术,我感觉一个大搜索,或者是一个垂直搜索,都应该不是一个简单编程和玩优雅的问题,这个涉及到非常多的底层处理技术,有融合好多底层技术甚至复杂过操作系统。很多人弄垂直搜索,估计不会想这么多吧,或许就是几个简单程序。

//-------------------------------------------------------------------------------------------------------------------------------------------------

我写的这些都是自己的想法,有的是猜想。因为对这个内部也不了解。只是我认为活跃的思维有利于作一些事情。生活中司空见惯的事情也是可以借鉴的。就比如把倒排索引比喻为查字典容易理解一样。思维只需要任意去想象,而不需要局限在既有模式。