很显然,爬虫抓取的网页必须及时保存在硬盘上,因此网页库的首要挑战来自于能够快速存储大规模网页;其次这些网页必须能够被其他模块快速地读取,因此读写问题是围绕网页库的主要难点。
(1)可伸缩性(Scalability)
网页库的存储必须具有可伸缩性,可以将大规模网页平滑地分布在一组计算机的硬盘中。
(2)双访问模式(Dual access modes)
网页库必须能够有效地支持两种不同的访问模式,即随机访问模式和顺序访问模式。使用随机访问模式,任意给出一个网页的标识即可读取相应的网页;使用顺序访问模式,顺序读取全部网页或者一部分网页。随机访问模式主要为搜索系统的查询系统中网页缓存部分提供随机的读取需要(在第5章中还会提到);顺序访问模式主要用在索引系统中顺序读取网页按序索引的过程中。
(3)大规模更新(Large bulk updates)
万维网变化瞬息万变,网页库必须能够在网页删除后删除老版本的网页,如此处理可能会留下存储空洞。更新可以理解为删除后添加,而添加使用顺序添加到网页库的方法,这样不得不采用一些磁盘空间紧缩(space compaction)技术回收那些存储空洞。此外更新和访问还要保证互斥,避免同步出现的错误。
为了照顾这些特性,网页的存储方式大致分为以下3种类型。
(1)日志结构这(Log-structured)。
(2)基于哈希的结构(Hash-based)。
(3)哈希日志(Hashed-log)。
日志结构将磁盘看做一个连续存储的介质(可以想象为磁带机),这种存储方式只能顺序读及顺序写,因此存储介质对网页增加的操作非常有利。然而对于随机访问,则必须通过B- 树的索引方式,因此每次访问需要执行两次读操作,分别读取索引和目标网页。此外还需要维护索引的代价,因此日志结构不能理想地支持随机访问的需要。
基于哈希的结构将磁盘看做一个哈希桶(Hash bucket)的集合,每个集合都足以存放在内存中,不需要构建额外索引,因此对于随机访问非常有利。然而对于顺序读写将十分不利,因为哈希函数的不确定性,对于一次网页增加,往往读入内存一个哈希桶,然后写入新增的部分,再写入磁盘。对于那些哈希桶中不变的数据,这样的一次读写操作无疑是浪费的,不断新增的网页被哈希映射到同一个桶的概率极低。还是因为哈希函数的不确定性,这种频繁读入哈希桶、更新并写入的操作被不断重复,因此对于网页新增是极其不利的。
哈希日志的结构是将哈希和日志的优势相结合,哈希作为索引找到文件块后再顺序写入