[CareerCup] 10.7 Simplified Search Engine 简单的搜索引擎
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 简单的搜索引擎的更多相关文章
- 微软的一篇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 ...
- 开源搜索 Iveely Search Engine 0.6.0 发布 -- 黎明前的娇嫩
快两年了,Iveely Search Engine已经走过了5个版本的岁月,虽出生“贫寒”,没有任何开源基金会的支持,没有优秀的“干爹.干妈”,它凭着它的爱好者的支持,0.6.0终于破壳而出,7年前, ...
- [0.0]Analysis of Baidu search engine
Rencently, my two teammates and I is doing a project, a simplified Chinese search engine for childre ...
- Iveely Search Engine 0.4.0 的发布
千呼万唤始出来,Iveely Search Engine 0.4.0 的发布 经过无数个夜晚的奋战,以及无数个夜晚的失眠,Iveely Search Engine 0.4.0 终于熬出来了,这其中 ...
- leetcode 10 Regular Expression Matching(简单正则表达式匹配)
最近代码写的少了,而leetcode一直想做一个python,c/c++解题报告的专题,c/c++一直是我非常喜欢的,c语言编程练习的重要性体现在linux内核编程以及一些大公司算法上机的要求,pyt ...
- 42 Bing Search Engine Hacks
42 Bing Search Engine Hacks November 13, 2010 By Ivan Remember Bing, the search engine Microsoft lau ...
- 解读论文《Agglomerative clustering of a search engine query log》,以解决搜索推荐相关问题
<Agglomerative clustering of a search engine query log> 论文作者:Doug Beeferman 本文将解读此篇论文,此论文利用搜索日 ...
- [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 ...
- [Search Engine] 搜索引擎分类和基础架构概述
大家一定不会多搜索引擎感到陌生,搜索引擎是互联网发展的最直接的产物,它可以帮助我们从海量的互联网资料中找到我们查询的内容,也是我们日常学习.工作和娱乐不可或缺的查询工具.之前本人也是经常使用Googl ...
随机推荐
- IOS设计模式-抽象工厂
抽象工厂的灵活性要比简单工程的灵活性强. 抽象工厂的UML图(第一次画UML图,可能关系和箭头的图意义有错误,但是请不要以建模规范去看图,以最基本的结合后面OC代码,理解相关关系): 抽象工厂原理:抽 ...
- 魔改——MDI多视图模板Tab/标签页 初始化/操作控件
==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完 ...
- Oracle数据库十大常见性能问题
错误的连接管理 oracle的连接是耗时耗力的操作,不应像sqlserver那样使用连接 错误的使用游标和共享池 一般是没有使用绑定变量 不好的SQL语句 使用大量资源的SQL语句都应该好好检查是否可 ...
- Spring配置文件外部化配置及.properties的通用方法
摘要:本文深入探讨了配置化文件(即.properties)的普遍应用方式.包括了Spring.一般的.远程的三种使用方案. 关键词:.properties, Spring, Disconf, Java ...
- rpm安装rpm-package报错:Header signature NOKEY 和 error: Failed dependencies:
以前经常遇到这个问题,一直未有记录,今天记录下来: 在安装rpm包的时候报错误如下: Question 1: warning: *.rpm: Header V3 DSA signature: NOKE ...
- windows 进程管理器中的内存是什么意思?
*内存 - 工作集:私人工作集中的内存数量与进程正在使用且可以由其他进程共享的内存数量的总和. *内存 - 峰值工作集:进程所使用的工作集内存的最大数量. *内存 - 工作集增量:进程所使用的工作集内 ...
- td内元素居顶,td元素不随高度的撑开而变位置
如下图,右边内容变高了,左边元素位置就下降到居中 设置居顶不变的方法 <table width="200" border="1"> <tr&g ...
- [学习嵌入式开发板]iTOP-4412实现NFS网络文件系统
本文转自迅为:http://www.topeetboard.com 学习平台:iTOP-4412开发板 本文讲解如何在 iTOP-4412 开发板上实现 NFS 网络文件系统. 我们使用的软硬件环境是 ...
- Sample: Write And Read data from HDFS with java API
HDFS: hadoop distributed file system 它抽象了整个集群的存储资源,可以存放大文件. 文件采用分块存储复制的设计.块的默认大小是64M. 流式数据访问,一次写入(现支 ...
- Qt与VC编程合作起龌龊
由于历史原因,某软件项目的界面采用QT,而后台用了VC,界面静态调用了VC生成的dll,一直以来都能够快乐的合作,然而最近出现两个小问题,觉得两者之间的合作并没有想象的那么美好. 在VC下用多媒体定时 ...