10.7 Imagine a web server for a simplified search engine. This system has 100 machines to respond to search queries, which may then call out using processSearch(string query) to another cluster of machines to actually get the result. The machine which responds to a given query is chosen at random, so you can not guarantee that the same machine will always respond to the same request. The method processSearch is very expensive. Design a caching mechanism for the most recent queries. Be sure to explain how you would update the cache when data changes.

这道题说假设有一个简单搜索引擎的网络服务器,系统共有100个机子来响应检索,可以用processSearch(string query)来得到其他机子上的结果,每台机子响应检索是随机的,不保证每个机子都会响应到同一个请求。processSearch方法非常昂贵,设计一个缓存机制来应对近期检索。根据书中描述,我们先来做一些假设:

1. 与其说根据需要调用processSearch,倒不如设定所有的检索处理发生在第一个被调用的机子上。

2. 我们需要缓存的检索是非常大量的。

3. 机器之间的调用很快。

4. 检索的结果是一个有序的URL链表,每个URL由50个字符的标题和200个字符的概要组成。

5. 最常访问的检索会一直出现的缓存器中。

系统需求:

主要需要实现下列两个功能:

1. 高效查找当给定了一个关键字时

2. 新数据会代替旧数据的位置

我们还需要更新和清楚缓存当搜索结果改变了。由于一些检索非常的常见病永久的在缓存器中,我们不能等缓存器自然失效。

步骤一:设计单个系统的存存器

我们可以混合使用链表和哈希表来实现,我们建立一个链表,当某个节点被访问了,自动将其移到开头,这样链表的末尾就是最老的数据。我们用哈希表来建立检索和链表中节点的映射,这样不仅可以让我们高效的返回缓存的结果,而且可以把节点移到链表前段,参见代码如下:

class Node {
public:
Node *pre;
Node *next;
vector<string> results;
string query;
Node(string q, vector<string> res) {
results = res;
query = q;
}
}; class Cache {
public:
const static int MAX_SIZE = ;
Node *head, *tail;
unordered_map<string, Node*> m;
int size = ;
Cache() {}
void moveToFront(Node *node) {
if (node == head) return;
removeFromLinkedList(node);
node->next = head;
if (head != nullptr) {
head->pre = node;
}
head = node;
++size;
if (tail == nullptr) {
tail = node;
}
}
void moveToFront(string query) {
if (m.find(query) == m.end()) return;
moveToFront(m[query]);
}
void removeFromLinkedList(Node *node) {
if (node == nullptr) return;
if (node->next != nullptr || node->pre != nullptr) {
--size;
}
Node *pre = node->pre;
if (pre != nullptr) {
pre->next = node->next;
}
Node *next = node->next;
if (next != nullptr) {
next->pre = pre;
}
if (node == head) {
head = next;
}
if (node == tail) {
tail = pre;
}
node->next = nullptr;
node->pre = nullptr;
}
vector<string> getResults(string query) {
if (m.find(query) == m.end()) return vector<string>();
Node *node = m[query];
moveToFront(node);
return node->results;
}
void insertResults(string query, vector<string> results) {
if (m.find(query) != m.end()) {
Node *node = m[query];
node->results = results;
moveToFront(node);
return;
}
Node *node = new Node(query, results);
moveToFront(node);
m[query] = node;
if (size > MAX_SIZE) {
for (unordered_map<string, Node*>::iterator it = m.begin(); it != m.end(); ++it) {
if (it->first == tail->query) m.erase(it);
}
removeFromLinkedList(tail);
}
}
};

步骤二: 扩展到多个机子

对于多个机子,我们有许多中选择:

选择1:每个机子有自己的缓存器,这种方法的好处是快速,因为没有机子间的调用,但是缺点是不高效

选择2:每个机子都有缓存器的拷贝,当新项目添加到缓存器,发送给所有的机器,设计目的是为了让常用检索存在于所有机子上,缺点是缓存器的空间有限,无法保存大量数据

选择3:每个机器保存缓存器的一部分,当机器i需要得到一个检索的结果,它需要找出哪个机子有这个结果,并到那个机子上取结果。但是问题是机子i怎么知道那个机子上有结果,我们可以用哈希表来建立映射,hash(query)%N,能快速知道哪个机子有想要的结果。

步骤三:更新结果当内容改变

有些检索很常用,所以会永远存在缓存器中,我们需要一些机制能更新结果,当其内容改变了,缓存器中的结果页应该相应变换,主要有下列三种情况:

1. URL的内容改变了

2. 当网页的排行改变了,那么结果的顺序也变了

3. 对于特定的检索有了新的页面

对于1和2,我们建立单独的哈希表告诉我们哪一个检索和哪个URL之间有映射,这个可以在不同的机子上分别完成,但是可能会需要很多数据。另外,如果数据不需要即时刷新,我们也可以周期性的来更新缓存器。对于3,我们可以实现一个自动超时机制,我们设定一个时间段,如果在这个时间段里没有检索,不管它之间被检索的有多频繁,我们都清除它,这样保证了所有数据都会被周期性的更新。

步骤四:进一步地增强

一个优化是当某个检索特别频繁时,比如一个检索占了1%的比重时,我们与其让机器i发送请求给机器j,倒不如在机器i上将结果存在自己的缓存器中。

再有就是我们将检索根据哈希值分别不同机器,而不是随机分配。

另外一个优化就是之前提到的自动超时Automatic Time Out机制,就是x分钟后自动清除数据,但是有时候我们对不同的数据希望设定不同的x值,这样每一个URL都有一个超时值基于此页面过去被更新的频率。

[CareerCup] 10.7 Simplified Search Engine 简单的搜索引擎的更多相关文章

  1. 微软的一篇ctr预估的论文:Web-Scale Bayesian Click-Through Rate Prediction for Sponsored Search Advertising in Microsoft’s Bing Search Engine。

    周末看了一下这篇论文,觉得挺难的,后来想想是ICML的论文,也就明白为什么了. 先简单记录下来,以后会继续添加内容. 主要参考了论文Web-Scale Bayesian Click-Through R ...

  2. 开源搜索 Iveely Search Engine 0.6.0 发布 -- 黎明前的娇嫩

    快两年了,Iveely Search Engine已经走过了5个版本的岁月,虽出生“贫寒”,没有任何开源基金会的支持,没有优秀的“干爹.干妈”,它凭着它的爱好者的支持,0.6.0终于破壳而出,7年前, ...

  3. [0.0]Analysis of Baidu search engine

    Rencently, my two teammates and I is doing a project, a simplified Chinese search engine for childre ...

  4. Iveely Search Engine 0.4.0 的发布

    千呼万唤始出来,Iveely Search Engine 0.4.0 的发布   经过无数个夜晚的奋战,以及无数个夜晚的失眠,Iveely Search Engine 0.4.0 终于熬出来了,这其中 ...

  5. leetcode 10 Regular Expression Matching(简单正则表达式匹配)

    最近代码写的少了,而leetcode一直想做一个python,c/c++解题报告的专题,c/c++一直是我非常喜欢的,c语言编程练习的重要性体现在linux内核编程以及一些大公司算法上机的要求,pyt ...

  6. 42 Bing Search Engine Hacks

    42 Bing Search Engine Hacks November 13, 2010 By Ivan Remember Bing, the search engine Microsoft lau ...

  7. 解读论文《Agglomerative clustering of a search engine query log》,以解决搜索推荐相关问题

    <Agglomerative clustering of a search engine query log> 论文作者:Doug Beeferman 本文将解读此篇论文,此论文利用搜索日 ...

  8. [DataMining]WEEK1 - text-retrieval and search engine

    What does a computer have to do in order to understand a natural language sentence? What is ambiguit ...

  9. [Search Engine] 搜索引擎分类和基础架构概述

    大家一定不会多搜索引擎感到陌生,搜索引擎是互联网发展的最直接的产物,它可以帮助我们从海量的互联网资料中找到我们查询的内容,也是我们日常学习.工作和娱乐不可或缺的查询工具.之前本人也是经常使用Googl ...

随机推荐

  1. Effective Java 27 Favor generic methods

    Static utility methods are particularly good candidates for generification. The type parameter list, ...

  2. Effective Java 76 Write readObject methods defensively

    Principle readObject method is effectively another public constructor, and it demands all of the sam ...

  3. nginx中使用srcache_nginx模块构建缓存

    nginx中可以将lua嵌,让nginx执行lua脚本,可以处理高并发,非阻塞的处理各种请求,openresty项目中可以使用nignx可以直接构建 srcache_nginx + redis 缓存, ...

  4. P2P行业专业术语(最全)

    网贷:P2P网络借款,指个体与个体之间通过网站实现借贷,中间网站称为网贷平台,简称平台. 角色类 投资者:在网站上把钱借出去的用户,年龄必须是18周岁以上具有中国国籍的公民. 借款者(贷款者):是指有 ...

  5. Kafka原理与java simple producer示例

    brokers和消费者使用zk来获取状态信息和追踪消息坐标. 每一个partition是一个有序的,不可变的消息序列. 只有当partition里面的file置换到磁盘文件以后,才开放给消费者来消费. ...

  6. Oracle Stored Procedure demo

    1.how to find invalid status stored procedure and recompile them? SELECT OBJECT_NAME , status FROM u ...

  7. MongoDB日志过大怎么办?

    MongoDB 日志文件过大怎么办? MongoDB的日志文件在设置 logappend=true 的情况下,会不断向同一日志文件追加的,时间长了,自然变得非常大. 解决如下:(特别注意:启动的时候必 ...

  8. 二分法 codevs 1432 总数统计

    codevs 1432 总数统计  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond   题目描述 Description 给出n个数,统计两两之和小于k的方 ...

  9. JavaWeb学习----http协议

    一.什么是HTTP协议: 1.概念: 客户端连上web服务器后,若想获得web服务器中的某个web资源,需遵守一定的通讯格式,HTTP协议用于定义客户端与web服务器通迅的格式(规定客户端和服务器如何 ...

  10. SVN代码的回滚二

    SVN代码的回滚: 不丢失新建的文件,获得最新的SVN版本控制.TortoiseSVN-ShowLog-选中你要回滚的版本-右键-Export,之后将修改的文件覆盖到你的最新版本,commit即可. ...