在使用爬虫爬取URL时,我们总会要使用到队列这一数据结构,在示例里,使用java写一个队列类可以解决此问题,但这种队列存储的数据只能存储在内存中,一旦断电,所有数据全部清空,下次又得重来。所以,这种队列不能用于解决问题,我们必须实现一个能够持久化数据的队列。
下面是我用Berkeley DB实现的一个队列,BerkeleyDB是一个内存嵌入式数据库,当内存中存储的数据大于它缓冲区大小时,它就会把数据自动持久化到磁盘中。
Berkeley DB使用键值对存储方式,所以我就用了Java里的BigInteger作为key,而URL作为value进行存储。key采用递增方式,BigInteger可以实现在1后面加上几千个0,完全符合URL数量庞大的要求。
队列会维护两个队头和队尾两个BigInteger,分别保存此时队列的头部值和尾部值;出队操作时,会删除头部保存的数据,并将头部值加1;入队时,会将数据添加进来,并将尾部值加1;size用于返回队列长度;此外,还有first、current、next、prev、last等几个游标操作,用于遍历队列。
队列的实现基于我以前封装的MyBerkeleyDB类,只有几个简单的API,使用起来很方便,这也算是代码重用了。下面是代码:
package com.nosql;
import java.math.BigInteger;
/*********************************
* 使用BerkeleyDB封装了一些数据库操作
* 包括设置缓冲区,设置编码,设置数据可库
* 路径,存储键值对,根据键查找值,关闭数
* 据库等操作。
* @author Administrator
*********************************/
public class MyBerkeleyDBQueue {
private MyBerkeleyDB database; //数据库
private static final BigInteger
BigIntegerIncrement = BigInteger.valueOf(1); //key值的递增值
private BigInteger head; //队列头部
private BigInteger tail; //队列尾部
private BigInteger current; //用于遍历数据库的当前位置
private static final String headString = "head";
private static final String tailString = "tail";
public MyBerkeleyDBQueue(){
database = new MyBerkeleyDB();
}
//初始化数据库
public void open(String dbName){
database.setEnvironment(database.getPath(),database.getChacheSize());