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. 设计模式 --- 模型-视图-控制器(Model View Controller)

    模型-视图-控制器(Model-View-Controller,MVC)是Xerox PARC在20世纪80年代为编程语言Smalltalk-80发明的一种软件设计模式,至今已广泛应用于用户交互应用程 ...

  2. C/S架构程序多种类服务器之间实现单点登录(转)

    (一) 在项目开发的过程中,经常会出现这样的情况:我们的产品包括很多,以QQ举例,如登陆.好友下载.群下载.网络硬盘.QQ游戏.QQ音乐等,总不能要求用户每次输入用户名.密码吧,为解决这个问题,高手提 ...

  3. cocos2d-x之多点触碰初试

    bool HelloWorld::init() { if ( !Layer::init() ) { return false; } Size visibleSize = Director::getIn ...

  4. JQ插件

    什么是插件 插件(plugin)是JQuery的扩展(Extension),以JQuery的核心代码为基础,是一种遵循一定规范的应用程序接口编写出来的程序. 插件的引入 引入jquery.js文件 引 ...

  5. zabbix安装排错过程

    在讲安装过程之前需要先把zabbix的工作流程简单的讲一遍:zabbix是个开源监控软件,通过web才能更直观的监控我们想要监控的主机,同时,zabbix从被监控主机获取到的信息需要存放在数据库中,因 ...

  6. 基于Retrotfit2.1+Material Design+ijkplayer开发的一个APP(新闻,gif 动图,视频播放)

    此项目主要目的还是为了练习框架的使用,仅供学习用途. 数据来源 新闻 直接用的聚合数据提供的接口:https://www.juhe.cn/docs/api/id/235gif动图 通过jsoup爬的某 ...

  7. Android+Sqlite 实现古诗阅读应用(一)

    不说网络app,很多本地的app都有一些随机的内容推送,比如随机推送一些小知识,古诗,名言名画什么的,界面制作的好看一点就能看起来特别的文艺范, 最近就是看了这样的一些应用,就想自己实现一下,这种方法 ...

  8. 读高性能JavaScript编程学英语 第一章第三页第一段话

    When the browser encounters a <script> tag, as in this HTML page, there is no way of knowing w ...

  9. gnuplot Python API

    源文件 #!/usr/bin/env python from os import popen class gnuplot_leon: # Author : Leon Email: yangli0534 ...

  10. CORDIC原理与FPGA实现(1)

    CORDIC算法的来历与用途大家网上随处可以见到,这里写 一下自己的理解. 将P(x,y)旋转角度a得到新的坐标P’(x’,y’).这里的坐标变换为: x’= x cos(a) – y sin(a)  ...