网络爬虫 (spider) 中 LRU算法的设计与实现

转自:《程序员》 文/ 洪伟铭

cache的所有位置都用双向链表链接起来,当一个位置被命中后,就将通过调整链表的指向将该位置调整到链表的头位置,新加入的内容直接放在链表的头上。这样,在进行过多次查找操作后,最近被命中过的内容就向链表的头移动,而没有被命中的内容就向链表的后面移动。当需要替换时,链表最后的位置就是最近最少被命中的位置,我们只需要将新的内容放在链表前面,淘汰链表最后的位置就是想了LRU算法。

LRU算法的实现

对象设计

对于Cache的每个位置,我们设计一个对象来储存对象的内容,并实现一个双向链表。

其中属性next和prev时双向链表的两个指针,key用于存储对象的键值,value用户存储要cache的对象本身。

我们使用hash算法来从cache中查找对象。

我们使用一个hashmap作为cache,用hashmap的检索机制来实现cache查找;并用head和last两个属性来记录链表的头和尾。并提供put(),getEntry()方法来操作该cache。

算法实现

cache的put()方法可将要缓存的内容放到cache中,在该方法中,对象调用私有方法insert(),将内容放到双向链表的头位置,如果cache满了,则将链表最后的位置淘汰掉:

pubilc boolean put(Object key,Object value){

boolean res = false;

HashLinkEntry en = new HashLinkEntry(key , value);

if(map.isEmpty()) {

this.head = en;

this.last = en;

map.put(en.key,en);

res = true;

} else {

HashLinkEntry point = this.getEntry(key);

if(point = null) {

point.value = value;

} else {

this.insert(en);

res = true;

}

}

return res;

}

private void insert(HashLinkEntry en) {

if(map.size() >= this.maxsize) {

HashLinkEntry lastprev = last.prev;

if(lastprev != null) {

map.remove(last.key);

lastprev.next = null;

last = null;

last = lastprev;

} else {

log.error("hashlist get a null point\n" + this.toString());

}

}

map.put(en.key,en );

ent.next = head;

head.prev = en;

head = en;

}

cache的getEntry()方法可根据输入的内容键值key来查找内容是否存在于cache中,如果命中,这个内容就是最新被使用过的,就需要放到双向链表的头位置。

结束语

LRU算法是cache最常用的算法之一,基于双向链表的实现方式比较容易,并可满足大容量cache的需求,在对系统性能要求越来越高的今天,良好的cache算法有着非常广泛的用途和实现意义。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
分布式爬虫负载均衡算法实现可以参考以下的Python代码: ```python import requests import redis import random from urllib.parse import urlparse # Redis数据库连接 redis_conn = redis.StrictRedis(host='localhost', port=6379, db=0) # 请求头信息 headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.111 Safari/537.36' } # 定义爬虫spider_pool = ['http://spider1.com', 'http://spider2.com', 'http://spider3.com'] # 定义URL队列 url_queue = [ 'http://www.baidu.com', 'http://www.sina.com', 'http://www.qq.com', 'http://www.taobao.com', 'http://www.jd.com' ] # 负载均衡算法 def load_balance(): # 获取所有爬虫的负载情况 spider_load = {} for spider in spider_pool: spider_load[spider] = int(redis_conn.get(spider) or 0) # 使用随机算法选取负载最小的爬虫 spider = random.choice(sorted(spider_load.items(), key=lambda x: x[1])[0:1])[0] # 增加选爬虫的负载 redis_conn.incr(spider) return spider # 爬虫程序 def spider(url): # 获取选爬虫 spider = load_balance() # 解析URL url_parts = urlparse(url) # 构造请求URL request_url = spider + url_parts.path if url_parts.query: request_url += '?' + url_parts.query # 发送请求 response = requests.get(request_url, headers=headers) # 输出响应内容 print(response.content) # 减少选爬虫的负载 redis_conn.decr(spider) if __name__ == '__main__': for url in url_queue: spider(url) ``` 这段代码实现了一个简单的分布式爬虫程序,其包括了负载均衡算法。在这个程序,我们维护了一个爬虫池和一个URL队列,每次从URL队列选取一个URL进行爬取,并使用负载均衡算法选取一个空闲的爬虫进行请求。在请求完成后,我们需要减少选爬虫的负载。我们使用Redis数据库来维护爬虫的负载情况,每个爬虫对应一个计数器,记录当前正在处理的请求数量。在负载均衡算法,我们使用随机算法选取负载最小的爬虫

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值