Chinaunix首页 | 论坛 | 博客
  • 博客访问: 17616
  • 博文数量: 14
  • 博客积分: 454
  • 博客等级: 下士
  • 技术积分: 145
  • 用 户 组: 普通用户
  • 注册时间: 2011-05-12 15:02
文章分类
文章存档

2011年(14)

我的朋友

分类: IT业界

2011-05-12 16:41:16

今天经历了迄今为止最长的一次面试,历时两个半小时,百度工程师GG不厌其烦的问着各种问题,很有耐心,并不断的给予指引。系统设计、算法设计、智力题等各种题目扑面而来,整个面试下来,受益匪浅,发现了很多不足,也学到了很多知识。

 

昨晚接到百度的面试通知,今天上午十点半到珞珈山国际大酒店面试,不到十点就赶到面试地点了,等到十点半左右,面试官出来说上一个面试的还没完,让我再等一会,对面试官GG的第一印象很好,能考虑到面试者焦急等待的心情。

 

面试在10:50正式开始了。(PS,我投的是研发工程师_云计算系统方向)

 

面 试官首先让我介绍一下我做过的项目,我说既然投的云计算,我就先介绍跟云计算联系最紧密的分布式文件系统开发的项目吧,然后简单的介绍了项目的基本情况、 目标及应用环境,先给他一个大概的认识,然后从系统架构、数据流交互、数据分配算法、存储节点集群管理等方面介绍了系统的设计原理,由于这个项目自己每个 细节都动手做过,设计原理也很清楚,而且经过几次面试向面试官讲过很多次了。

 

接下来面试官开始发难了,只记得一部分了

问:你们系统通过副本机制保证可靠性,怎么实现的?

答: 每个文件的数据被分成多块(块大小通常为8M64M,具体设置根据应用环境而定),每一个数据块都会被复制多份存储到多个存储节点上,即使由一份丢失了,还能通过其他的备份访问到数据。

问:多个副本通过什么方式写到存储节点的?

答:客户端在写数据的时候创建多个线程,同时往多个存储节点写(存储节点是由元数据服务器负责管理和分配的)。

问:对于同一个块,所有的进程都可以随便写么?

答:分几种情况,同一机器上的多个进程实现的UNIX文件系统语义(读写不受限制),对于不同机器上的进程数据块的更新会有排它锁的保护。

问:怎么实现的?

答:对于每个更新的数据块,有更新时记录对应客户端的IP地址,下一次更新请求如果IP来源相同,则更新不受限制,否则,下一次请求必须等待本次更新结束。

问:怎么控制副本的写入顺序?

答:副本写入的顺序是不固定的,客户端发出多个写请求,各个节点实际完成数据的写操作,没有固定的完成顺序。

问:那这样可能出现数据不一致啊,比如2个客户端,2个副本,客户端1先获取副本1的写锁并写1,同时客户端2获取副本2的写锁并写2,然后,客户端1又写2,客户端2又写1,此时两个副本的数据不一致。

答:(想了一下,发现这些问题当时根本没有考虑个,最初的时候功能上实现已经很Happy了)这个问题的确存在,但我们系统的应用环境是读多写少(比如视频存储、地理信息存储),数据一次写(创建)就不会再修改,上面的问题也没有出现过。

问:也就是只支持文件的创建、追加,不支持更新。

答:差不多是这样吧,更新方面的确存在问题,而且系统还有很多方面设计都不是很成熟。

: 那你觉得上面的问题为什么会出现呢,怎么避免?

答:主要是多个副本之间的更新是独立的,缺乏一种协调机制吧。可以借鉴HDFS里的方法,采用流水线更新的方式,客户端更新11更新22更新3…,然后依次反馈,这样就不会出现上面这个问题了。

问:如果每一个节点宕掉了会出现什么情况?

答:因为每块数据都有多个副本,一个节点坏掉对系统不会有影响。

问:那如果存其他副本的机器也同时宕掉了呢?

答:会导致数据不可访问,因为我们暂时没有对存储节点维护全局的块信息,在存储节点宕机之后也就没有数据迁移机制,这会增加系统失效的概率。

问:数据迁移?

答:不好意思,说错了,应该是复制,将宕掉那台机器上的数据(在其他节点都有副本的)复制到其它节点,并更新元信息。

这个项目中还问了一些问题,已经记不太清楚了。

 

面试官稍微停顿了一会,由接着问问题了。

问:你做过分布式文件系统的设计,现在要做一个分布式缓存系统,缓存的对象是网页,将常用的网页数据缓存在内存中以加速访问,你应该怎么做,应该考虑些什么问题。

答:(面试官刚说到分布式缓存,我立马想起memcached,听完题目,发现memcached的实现可以满足需求,估计就是考我对主流的一些云计算相关的设施是否了解)能否借助现有系统的一些方法,我想memcached的方法可以借鉴一下。

问:任何方法都可以,具体怎么做?

答:从缓存数据的分配上采用一致性hash算法(把一致性hash的具体做法描述了一下),每次访问之前对网页url计算hash值,并使用一致性hash定位具体的缓存节点,然后到对应的缓存节点查找对应的网页数据是否存在。

问:一致性hash有什么好处?

答:采用hash算法能保证对缓存节点的快速定位,一致性hash的优势在于能保证在某个节点失效时,保证最少的缓存失效(画图说明了一下),这对于缓存系统来说很重要。

问:当节点数比较少时,可能一致性hash在数据分布上很不均匀,导致负载不均,怎么解决?

答:可采用虚拟节点的方式解决这个问题(把一个物理节点看成是多个虚拟节点),Dynamo就是这么做的。

 

问:(面试官看我对分布式缓存比较了解,就又增加了限制)现在仍然是设计一个分布式缓存系统,但各个节点之间不是对等的,有一个主控节点,系统应该怎么设计(给了我提示说,现在数据分配的任务就转移到主控节点上了)?

答:(想了一下,感觉分布式缓存系统要主控节点根本就是浪费,在纸上画了画,面试官又提醒我不要考虑扩展,假设节点数是固定的)将url乱转着分配各个存储节点上,或采用hash取模的方式,但这个过程不需要主控节点的参与也可以实现啊,还是感觉主控节点有点浪费。

问:那你想什么办法让主控节点发挥作用呢?

答:(想了几秒,没有思路,于是就加了个场景)我觉得主控节点可以起一个分类(分流)的作用,比如url对应的都是百度的网页,包含mp3, 学术, 文库等各种应用的页面,百度现在已经有各个应用的访问特性,主控节点可以根据url来讲网页分配到不同的缓存节点上,比如将mp3搜索下的页面都缓存到一个节点,将学术的缓存到另一个节点,主控节点则维护这个对应关系。

问:现在假设url没有那么多特性,都是随机的,又该怎么做?

答:(想了一会,仍然没有什么头绪,中间面试官也给了一些提示,进展仍然不大,还好想到了Tair中的对照表)于是把Tair的对照表的思路跟他说了一遍。

问:当有新节点加入或节点失效时,对照表如何更新?

答:Blabla  把对照表的更新和方法给面试官讲了一遍

http://blog.chinaunix.net/space.php?uid=20196318&do=blog&id=155709

问:这个还有没有什么方法优化呢?

答:(想不到什么好的方法)思考中。

问:客户端能不能在加一层缓存呢?

答:没往这个方向想,我觉得这个是可以的,而且也应该在客户端缓存对照表,因为对照表只有在节点增加或减少的情况下才会改变,比较适合缓存,从而客户端每次不用到主控节点上获取映射信息了。

 

面试官又扫瞄了一个简历,看了几秒钟,说你这个海量元数据组织与检索的项目是怎么样的,简单的介绍一下。

 

还是老套路,把项目的基本信息、目标简单的说了一通,然后把分区策略,还有过滤表的设计(包括BloomFilter的原理),建索引的方式,索引的流程介绍了一下,面试官很满意,没多问什么。对于这个项目,我感觉挺遗憾的,因为没有完整的把整个design实现过,虽然自己很想做,而且硕士开题也是按这个思路写的,可惜由于某种原因,后来完全不是朝这个方向发展的。

 

接下来面试官设定了一个场景,也是跟cache相关的(C/S模式),cache在客户端,针对cache可能由两种操作,一种是查找(F),当查找发现cache不存在时(1),就从服务器读取(2),然后再把读取到的数据加到缓存中(3);一种是更新(U),客户端的每一次更新都直接写到服务器(1),写完之后让当前客户端的cache失效(2)。(数字和字母是为方便描述加上去的)

 

问:有没有可能客户端的cache一直是无效的?

答:(在纸上画了画,刚开始说错了,第二次才描述清楚)F1, F2执行完后,U1执行,接着U2执行,接着F3执行,此时缓存中数据就会是无效的,之后的读取就一直会读到无效的数据。

问:有什么方法解决这个问题呢?

答:给数据加个时间戳,只有更新的数据才会被写到缓存。

问:这里更新操作只是让缓存失效,并没有写入新的数据到缓存,如果是写新数据加时间戳是可以的,但这里不行。

答:那就加个锁,保证F的三个过程不能被打断。

问:如果客户端某个进程加锁后挂起了,它将一直占用着锁,别的进程就不能使用缓存了,这个问题该怎么解决?

答:为锁设置一个超时时间,当超过指定时间后,客户端进程加的锁就会失效。

问:那如果一段时间之后挂起的进程又恢复了,又该怎么办?

答:(瀑布汗+沉思)

问:可以考虑让进程放弃请求并重做。

后面关于这个话题还问了很多诡异的问题,好多都记不清楚了。

 

感觉已经面了有一段时间了,是不是该结束了,这时面试官的问题有来了。

 

问:一个海量数据处理的问题,有一个文件记录了一些词及其出现的次数(word count序列),各个词在文件中可能重复出现,求出出项次数最多的那个词,文件大小1G,内存限制10M

答:可以建立临时文件吗?

问:可以

答:由于文件的内容远大于内存限制的大小,故需先缩小问题的规模,使用hash的方式将原始文件的数据进行分类。10M内存,估算了一下,可以加载10^6条记录,然后建立N个临时文件(N为记录条数/10^6),保证同一个word被分到同一个文件即可。然后对每个临时文件中同一个word的出现次数进行合并,并求出出现次数最多的那个word,然后对比每个文件中出现次数最多的word,得到最终的结果。

问: 如果某一类的词出现次数很多,导致其中一个文件的大小超过了内存的大小,该怎么办。

: 对于这类的词设置一组文件,每个文件大小的上限为内存的大小,再对这多个文件进行合并。

问:怎么合并?

答:有两种方法,第一种对文件组内第一个文件的每个词,查找器是否在第二(第三..)个文件中,然后更新第一个文件中的统计信息;第二种是先对组内每个文件的统计信息排序,然后使用归并排序合并。

问:那种方法好呢?

答:排序后再归并效率比较高。

问:要是现在又多台机器,你可以怎样利用起来呢?

答:(应该是考对MapReduce的了解)可以把临时文件换成机器节点,把同一类的统计任务分发到不同的节点上,计算完后再回收结果并合并。

 

面试官又在一张纸上看了一会(貌似是个题库),又问了个问题,现在有一种树,不一定是二叉树,树的孩子节点的顺序是不影响树的结构的,即某个节点有ABC三棵子树和BACCAB三棵子树是一样的效果,然后给定两棵树,判断两棵树的结构是否一样,要求写出伪代码。

 

简单的说了下思路,维护两个临时队列(或者数组),首先将两棵树的根入队列,排序队列中的节点,判断两个队列是否相同,不相同则两棵树的结构不同;如果不同,则对于当前判断的节点,依次递归判断其子树的结构是否相同。伪代码大致写了一下,面试官也没多问什么。

 

接下来问了两个智力题,个人感觉我解决这类问题的能力很差。

1.  操场上有21个人,每两个人之间的距离都不等,每个人对离他距离最近的人进行监听。

证明:至少有一个人没有被监听。

2.  A, B, C三个人设计的命中率分别为30%50%100% ABC得顺序站成一圈,有一把枪从A开始按ABC的循环顺序被传递,获得枪的人可以选择对其他的人开枪,问A开始应该打B还是打C

 

第一道题最后再他的指引下,运用反证法解决。假设每个人都被监听,则监听链中必然存在一个环(3个节点以上的,因为21为奇数)。对于3个人的情况,假设A监听BB监听CC监听A。则CA>AB(CA的距离大于BA的距离) AB>BC, BC > CA显然是矛盾的,也就是说三个节点的环是不可能出现的,同理多余3个节点的环也是不可能出现。

 

第二道题我直接说先打C,因为万一把B打死了,A就肯定会被C打死。面试官说要详细分析下AB和打C后自己存活的概率,说把每种可能出现的情况都罗列出来对比一下就知道了,但直到最后还是没有得到答案,最后不了了之。

 

最后一道题,一个队列有头指针和尾指针,如果对入队列和出队列进行加锁,则不会出现数据一致性问题。现在没有提供加锁的操作,但提供了一个原子操作CAS(P, A, B),这个操作的功能是如果P指向的位置的值不为A则不执行任何操作,如果为A则将其值设置为B,问:通过这个原子操作,怎么协调出队和入队操作。

 

想了一会,没什么思路,关键是这个CAS只执行设置工作,感觉不能帮什么忙啊,面试官提示可以先不要考虑头指针、尾指针,假设就是个栈,该如何协调入栈和出栈操作。

 

把入栈和出栈的过程写出来,分析了一下:

入栈 { 1)取栈顶指针 2)存入栈数据 3)更新栈顶 }

出栈 { 1)取栈顶指针 2)取出栈数据 3)更新栈顶 }

 

对于两次出栈,如果第一次的(1)(2)完成了,第二次的(1)(2)(3)执行,第一次的(3)执行,则两次出栈的结果是一样的,这显然是有问题的。

 

对于先入栈后出栈,当入栈的(1)(2)完成后,出栈的(1)(2)(3)执行,入栈的(3)执行,则出栈的元素不是刚刚入栈的元素,也是不合理的。

对于先出栈后入栈,出栈的(1)(2)完成后,入栈(1)(2)(3)执行,出栈(3)执行,则最后栈顶元素仍然是操作前的元素,而不是后入栈的元素,这也是不合理的。

 

发现上面序列出现的问题都有一个共同特点,那就是先执行的操作在最后更新栈顶的时候,栈顶已经不是在第(1)步中取的栈顶了,只要在更新栈顶前加个判断就行了,CAS原子操作刚好做这个的,问题也就解决了。

 

问 题再回到队列上,分析了一下发现由于队列由于入队和出队操作不同的指针,除了在两者重合的时候(可能空队,可能满队)需要做额外的处理,这是面试官自个去 外面吃热干面了,听他吃面的声音都听得直流口水,他回来后我把想法告诉他,他问那能否让队列的头尾指针不重合呢,我说增加一个额外的存储单元,这样对于队 列判空与判满也方便,OK问题到这里都结束了。

 

最后面试官问有没有什么需要问他的,我问了下百度云计算的规划,要把云计算系统做成什么样子,有没有计划提供像Amazon那样的计算租赁模式面试官大致的回答了一下,最后面试官告诉我说回去评估一下,可能直接三面,如果需要的话北京那边会加一轮电话二面。

 

面试终于结束了,到电梯了看了下时间1323,整整面了两个半小时,刚接到百度的电话,说二面就算过了,三面的面试官明天来武汉,这几天会安排三面,让我耐心等待,两个半小时也算是没有白熬啊,希望能顺利通过这次面试,加油!

阅读(323) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~