八家国企大数据面经干货详细答案

4次阅读

共计 11854 个字符,预计需要花费 30 分钟才能阅读完成。

谢安生 (化名),末流 985 本科,非科班。18 年 10 月零基础学的大数据,错过了秋招,但在春招拿了 招商银行,光大银行,浪潮等国企大数据开发 offer

他是我学习群里的一个小伙伴,也是一个曾经在面试前一晚半夜 3 点打我电话问我问题的男人。。(后台回复 ”
加群 **”,加入学习群)


部分 offer


以下为正文,答案由我重新整理:


目录
北京柠檬微趣
途牛
光大银行·光大科技
悠易互通
乐言科技
多益网络
招商银行·招银网络科技
浪潮集团

①北京柠檬微趣

**
以下为两道方案题,觉得很有意思,记录一下。

  一次计算各时区的 DAU

假设有最近 48 小时的数据,如何 一次性 计算 24 个时区各自的 DAU,而不是计算 24 次。

分析:
考虑用 pipeline,在进入管道前对数据按时区进行“分类”,然后将数据放入管道,在管道内一次计算,求聚合值。

**
一些整数数据分布的存储在多台机器上,每台 20TB,需要求这些数的平均数。请简述计算方法和数据流。
分析:
20TB,数据量过于庞大,则需要考虑使用中间件。类比 mysql 的 mycat,利用中间件对过于庞大的数据进行维护等操作。



微信视频面试,感觉有一点点随意。两个面试官,特别和蔼,全程主动权在我手上 (就算是我不会的问题,也被我带着转移到我会的问题上,基本没有打断过。) 总共面了 40 分钟,其中 MR 流程我就跟他们讲了近 20 分钟(结合项目、举例、又从快排 / 归并排序扯到各种排序算法的比较,分区分组又拓展到数据倾斜问题……总之全程被我带着跑,一直说我会的。)
二次总结:面试官不打断不一定代表认为你答得好,可能他性格就是那样。答得不好以及不会的回答面试官还是看在眼里的,所以硬实力还是最关键的。

记录几个我答的不是很好的问题:



这个问题是最常被问到的问题之一,因为一个问题可以牵扯出很多数据结构的知识,很考验功底,建议有时间自己琢磨总结一下。画一画、理一理自己的回答思路线。
参考答案:
http://www.cnblogs.com/chenss…
https://www.cnblogs.com/holys…


**
创建线程(new Thread)、就绪(runnable)、运行(running)、阻塞(blocked)、等待队列、锁池队列、死亡(dead)

事务的特性、事务的隔离级别

事务的特性
原子性:
指事务是一个不可分割的工作单位,事务中的操作要么都发生,要么都不发生。
一致性:
事务必须使数据库从一个一致性状态变换到另外一个一致性状态。转账前和转账后的总金额不变。
隔离性:
事务的隔离性是多个用户并发访问数据库时,数据库为每一个用户开启的事务,不能被其他事务的操作数据所干扰,多个并发事务之间要相互隔离。
持久性:
指一个事务一旦被提交,它对数据库中数据的改变就是永久性的,接下来即使数据库发生故障也不应该对其有任何影响。

脏读:
脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。
不可重复读:
不可重复读是指在对于数据库中的某个数据,一个事务范围内多次查询却返回了不同的数据值,这是由于在查询间隔,被另一个事务修改并提交了。
虚读 (幻读):
幻读是事务非独立执行时发生的一种现象。例如事务 T1 对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务 T2 又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务 T1 的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务 T2 中添加的,就好像产生幻觉一样,这就是发生了幻读。

幻读和不可重复读都是读取了另一条已经提交的事务(这点就脏读不同),所不同的是不可重复读查询的都是同一个数据项,而幻读针对的是一批数据整体(比如数据的个数)。

现在来看看 MySQL 数据库为我们提供的四种隔离级别:

①Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
②Repeatable read (可重复读):可避免脏读、不可重复读的发生。
③Read committed (读已提交):可避免脏读的发生。
④Read uncommitted (读未提交):最低级别,任何情况都无法保证。

以上四种隔离级别最高的是 Serializable 级别,最低的是 Read uncommitted 级别,当然级别越高,执行效率就越低。像 Serializable 这样的级别,就是以锁表的方式 (类似于 Java 多线程中的锁) 使得其他的线程只能在锁外等待,所以平时选用何种隔离级别应该根据实际情况。在 MySQL 数据库中默认的隔离级别为 Repeatable read (可重复读)。

在 MySQL 数据库中,支持上面四种隔离级别,默认的为 Repeatable read (可重复读);而在 Oracle 数据库中,只支持 Serializable (串行化)级别和 Read committed (读已提交)这两种级别,其中默认的为 Read committed 级别。



我说公众号、csdn(且自己也有专栏)、极客时间、知识星球、github……



面试采取的是多对多形式 (国企常见形式,我个人表现时间应该 8 分钟都不到),我们那一组 6 个人(还是想吐槽一下,6 个人,其中 3 个名校研究生,除了我,清一色北科、北邮、北理名校的,我 emmm,国企真抢手)。
先是轮流自我介绍(指定 1 分钟,说主讲项目和实习经历),我开始时被“一分钟”吓到了 (我自我介绍准备的是 3 分钟!),最终,我“文理兼修”的特性都忘记讲了。(血的教训!!!赶紧准备下 1 分钟版本自我介绍!)
然后是挨个问问题 (部分问题有问其它人的看法)。
面试官比较犀利,问问题的时候,说偏了或者啰嗦了会直接打断你。



表中有很多重复的数据,怎么去重?
我答的 distinct、group by(我还巴拉巴拉说这两者的区别,一个跑内存一个是快排思想……被打断)、然后还说到 MR 项目中求 uuid 的去重个数,有在 reduce 端用set 集合 进行去重,count 值即为 set.size()……面试官接着问,还有吗?没人答了。

事后百度补充答案:
**
返回结果集分区内行的序列号,每个分区的第一行从 1 开始。
而且推荐使用 row_number(),对某一字段(tel)排序后分区去重,这样避免了其对不相干字段的数据干扰,影响数据处理的效率。

举例:

SELECT tel, link_name, certificate_no, certificate_type, modify_time
FROM order_info
WHERE deleted = ‘F’
AND pay_status = ‘payed’
AND create_time >= to_date(‘2017-04-23’, ‘yyyy-MM-dd’)
AND create_time < to_date(‘2017-04-24’, ‘yyyy-MM-dd’)
AND row_number() over(PARTITION BY tel ORDER BY tel DESC) = 1

建立临时表,利用 hive 的 collect_set 进行去重。

create table if not exists tubutest (
name1 string,
name2 string
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ‘,’
STORED AS TEXTFILE;
 
select from ods.wdtest;
1   1
1   1
1   2
1   2
1   3
2   3
2   3
2   4
 
select name1,collect_set(name2) from tubutest group by name1;
name1   _c1
1   [“2″,”3”]
2   [“2″,”4”]
 
create view ods.wdtestView as
select name1,collect_set(name2) as name2 from ods.wdtest  group by name1;
 
select
from ods.wdtestview;
name1   name2
1   [“2″,”3”]
2   [“2″,”4”]
 
select name1, name2 from tubuview  LATERAL VIEW explode(name2) tubuview as name2;
 
A,collect_set 完成把多行转化成一行的功能。
B,explode 完成把一行转化成多列的功能。而 lateral view 主要是辅助 explode 进行使用,来完成类似去重的功能。



没有复习到这个问题 (悔!!!),只是简单答了几句话,比如一个是处理离线的一个处理实时,spark 跑内存……
答案整理:
https://blog.csdn.net/zx81671…
1. Spark 把运算的中间数据存在内存中,迭代计算效率更高;MR 的中间结果需要落地,需要保存到磁盘。
2. Spark 有更高的容错性,它通过弹性分布式数据集 RDD 来实现高效容错,shuffle 之前的计算错误可以找到父 RDD 重新计算即可;而 MR 如果出错只能从头重新计算。
3. Spark 更加通用,提供了 transformation 和 action 两类算子,另外还有流式处理 streaming、图计算 GraphX 等;而 MR 只提供 map 和 reduce 两种操作。
4. Spark 对性能要求较高,通常需要根据不同的业务场景进行调优;而 MR 对性能的要求相对较低,运行更稳定,适合长期后台运行。



二次总结:快速记忆,物数网传会表应(“武术网传会表演”)。最重要的是第四层和第七层,TCP/UDP,HTTP 要有大概概念。
https://www.cnblogs.com/wxgbl…
1. 物理层:
原始比特流传输,一些物理接口,比如网卡、网线、集线器、中继器、调制解调器。
2. 数据链路层:
将原始比特流转换成逻辑传输线路,比如网桥、交换机。
3. 网络层:
控制子网的运行,如逻辑编址、分组传输、路由选择。具体表现,路由器。
4. 传输层:
接受上一层的数据,在必要时将数据进行分割,并将这些数据交给网络层,且保证这些    数据段有效到达对端。TCP 传输控制协议,UDP 用户数据报协议。
5. 会话层:
不同机器上的用户之间建立及管理会话。
6. 表示层:
信息的语法语义以及它们的关联,如加密解密、转换翻译、压缩解压缩。
7. 应用层:
各种应用程序协议。如 HTTP 超文本传输协议、FTP 文本传输协议、SMTP 简单邮件传输    协议、POP3 邮局协议第三版。

进程和线程通信方式?实际开发中,在哪些地方用上了,请说出具体场景?
每个进程有自己的地址空间,进程间的通信一般通过操作系统的公共区进行。
线程可以看作是轻量级的进程,同一进程中的线程属于同一地址空间,所以可以直接通信,而且可以共享全局变量和内存。总之,线程之间共享数据特别容易,这是它的优点,也由此带来了同步、异步、互斥的问题。
总结:**
线程通信,共享地址空间和数据空间,不必通过操作系统。
进程通信,需要通过操作系统,分为单机版和网络通信(通过 socket)。

进程通信方式:
管道(pipe):
管道是一种半双工的通信方式,数据只能单向流动,而且只能在具有亲缘关系的进程间    使用。亲缘关系一般指父子进程关系。
有名管道(namedpipe):
允许无亲缘关系的进程的通信。
信号量(semophore):
信号量是一个计数器,用来控制多个进程对共享资源的访问。类比锁机制。
消息队列(messagequeue):
消息队列是有消息的链表,存放在内核中并由消息队列标识符标识。消息队列克服了信    号传递信息少、管道只能承载无格式字节流以及缓冲区大小受限等缺点。
信号(sinal):
用于通知接收进程某个事件已经发生。
共享内存(shared memory):
共享内存就是映射一段能被其他进程所访问的内存,这段共享内存由一个进程创建,但    多个进程都可以访问。共享内存是最快的 IPC 方式,它是针对其他进程间通信方式运    行效率低而专门设计的。它往往与其他通信机制,如信号量配合使用,来实现进程间    的同步和通信。
套接字(socket):
用于不同机器间的进程通信。

线程通信方式:
锁机制:包括互斥锁、条件变量、读写锁。
互斥锁提供了以排他方式防止数据结构被并发修改的方法。
读写锁允许多个线程同时读共享数据,而对写操作是互斥的。
条件变量可以以原子的方式阻塞进程,直到某个特定条件为真为止。对条件的测试是    在互斥锁的保护下进行的。条件变量始终与互斥锁一起使用。
信号量机制 (Semaphore):
包括无名线程信号量和命名线程信号量
信号机制 (Signal):
类似进程间的信号处理。
线程间的通信目的主要是用于线程同步,所以线程没有像进程通信中的用于数据交换的    通信机制。

**
以下为个人整理的回答思路。(不一定正确,有时间可以自行阅读源码总结)
Spark 分区主要分为三部分,1. 读取文件(textFile);2.shuffle 过程;3. 输出文件。
1. 读取文件
会根据你设置的分区数量 a 进行计算。
计算逻辑为:文件总的大小除以设置的分区 a,
若得到的值大于 128MB,则按 128MB 一个分区(有冗余),依次填满 128MB 的分区,直至所有文件读取完。
若得到的值小于 128MB,则按设置的分区 a。
2. shuffle 过程
根据 Partitioner,即 RDD 的分片函数。当前 Spark 中实现了两种类型的分片函数,一个是基于哈希的 HashPartitioner,另外一个是基于范围的 RangePartitioner。只有对于 key-value 的 RDD,才会有 Partitioner,非 key-value 的 RDD 的 Parititioner 的值是 None。Partitioner 函数不但决定了 RDD 本身的分片数量,也决定了 parent RDD Shuffle 输出时的分片数量。
3. 输出文件
默认按照 Partitioner 分区,也可以自定义分区个数,coalesce(1)。



面试官是个超级“直接”的人,
不让自我介绍,上来就问,然后各种问题都一针见血,我们互相 get 不到对方的点,他想要的是直接说方案,而我总是先说思路 / 分析。总之,就是完全不在一个频道上。后来他也直接说了,他们小公司要的就是直接能干活的人,哪怕是应届生也要求很高,不像大公司一样愿意花三年五年去培养你(只要你基础好),毕竟小公司的生存环境摆在那。
所以最终 GG,总之就是他们公司在以社招的要求招应届生,所以完全不匹配。

ps: 虽然和面试官不在一个频道上,但是他的一些话还是想记录一下。
“面试时你总是拐弯抹角,不会的问题也往自己会的问题上去转移问题,会被你带着跑的面试官说明水平也不怎么样,其实你们就是在互相忽悠,最终入职,那糊弄的只是客户。”(因为他是一个超直接的人,所以对“不会的问题往会的问题上引”这种面试技巧特别反感。总结: 遇到“直接”的面试官,该说不会就说不会,毕竟有些人就是喜欢高效沟通)
“如果你想去大公司,就多复习基础;如果去小公司,就多了解一些问题的解决方案,让人家相信你来就能直接干活。”

问题:
1. 数据量特别大的情况下(例如 10g、100g、1t)如何用 mr 实现全局排序?
2.flatmap 算子的理解,flat 原理,返回类型?(iterator)



https://www.cnblogs.com/airne…
方式一:
reduce 数量只设置为 1 个。缺点:没有用到集群的优势,速度慢。
方式二:
自定义分区类 partition,按照 key 值进行分区。
例如:将排序 key 值为 1 -1000 的数据,使用两个分区,将 1 -500 的 key 发送到 partition1,将 501-1000 的 key 发送到 partition2。
缺点:1、当数据量大时会出现 OOM。2、会出现数据倾斜。
方式三(推荐):
利用 TotalOrderPartitioner 类。(hive 的 order by 底层也是该方法)
补充:该方法基本原理和方法二类似,只是不再是手动粗糙的进行分区,而是先通过采样,分析数据的分布特征,根据数据的具体特征进行合理的分区(片)。


flatmap 算子的理解,flat 原理,返回类型?(iterator?)
https://blog.csdn.net/DPnice/…
flatMap 其实就是将 RDD 里的每一个元素执行自定义函数 f,这时这个元素的结果转换成
iterator**,最后将这些再拼接成一个新的 RDD,也可以理解成原本的每个元素由横向执行函数 f 后再变为纵向。画红部分一直在回调,当 RDD 内没有元素为止。

⑤乐言科技

**

hive 的 metastore 的三种模式

https://www.cnblogs.com/snowb…
Hive 中 metastore(元数据存储)的三种方式:
1. 内嵌 Derby 方式:
这个是 Hive 默认的启动模式,一般用于单元测试,这种存储方式有一个缺点:在同一    时间只能有一个进程连接使用数据库。
2. Local 方式
例如本地 mysql:创建好用户:hive;database:hive。
ps:需要把 mysql 的驱动包 copy 到目录 <HIVE_HOME>/lib 中
如果是第一次需要执行初始化命令:schematool -dbType mysql -initSchema
配置完成后就可在 shell 中以 CLI 的方式访问 hive 进行操作验证。
3.Remote 方式
以 Mysql 数据库 (192.168.6.77) 为例:创建好用户:hive;database:hive_meta。Remote 方式需要分别配置服务端和客户端的配置文件。
hive metastore 服务端启动命令:
hive –service metastore -p <port_num>
如果不加端口默认启动:hive –service metastore,则默认监听端口是:9083

介绍一下 flume 及 Kafka

flume 和 Kafka 也超级重要,多次被问到。毕竟大数据,对数据的“流转”还是很看重的。
flume 各组件的作用必须了解,
参见 https://www.cnblogs.com/zhang…
Flume 的一些核心概念
Client:Client 生产数据,运行在一个独立的线程。
Event:一个数据单元,消息头和消息体组成。(Events 可以是日志记录、avro 对象等。)
Flow:Event 从源点到达目的点的迁移的抽象。
Agent:一个独立的 Flume 进程,包含组件 Source、Channel、Sink。(Agent 使用 JVM 运行 Flume。每台机器运行一个 agent,但是可以在一个 agent 中包含
多个 sources 和 sinks。)
Source:数据收集组件。(source 从 Client 收集数据,传递给 Channel)
Channel:中转 Event 的一个临时存储,保存由 Source 组件传递过来的 Event。(Channel 连接 sources 和 sinks,这个有点像一个队列。)
Sink:从 Channel 中读取并移除 Event,将 Event 传递到 FlowPipeline 中的下一个 Agent(如果有的话)(Sink 从 Channel 收集数据,运行在一个独立线程。)
Agent 结构
Flume 运行的核心是 Agent。Flume 以 agent 为最小的独立运行单位。一个 agent 就是一个 JVM。它是一个完整的数据收集工具,含有三个核心组件,分别是
source、channel、sink。通过这些组件,Event 可以从一个地方流向另一个地方,如下图所示。

Kafka 内容较多,建议自行复习总结。
kafka 的重要组件(重要)

Producer:
生产者负责将数据传入 Kafka,比如 flume、java 后台服务、logstash
生产者可以有多个,并且可以同时往一个 topic 中写数据,也可以同时往一个 partition 中传入数据。
每个生产者都是一个独立的进程,而且单个生产者就具有分发数据的能力。
一个生产者可以同时往多个 topic 中分发数据。(一般不会这么操作)

Kafka cluster:
Kafka 由多个 broker 组成,一个 broker 作为一个实例(节点)
Kafka 集群可以保存多种类型的数据,是由多个 topic 进行分类的
一个 topic 其实就是一个队列
每个 topic 可以创建一个或多个 partition,partition 的数量是可以更改的
每个 partition 是由多个 segment 组成的,segment 的大小是相同的,默认的是 1G
topic 中的数据是有多副本机制的,原始数据和副本数据不会在同一个节点上(所以若只有一个节点,副本数为 3,也并不会在同一个节点上存 3 份)

Consumer group:
消费者负责拉取数据,比如:streaming、storm、java 服务
消费者组中可以存在多个 consumer,在 stream 中,一个 consumer 作为一个线程
新增或减少 consumer 数量会触发负载均衡,目的是减少部分 broker 压力,提高 Kafka 的吞吐量
一个 consumer group 可以消费多个分区的数据
一个分区的数据最多在同一个时刻被一个 consumer 消费
在同一个 consumer group 中,数据是不可以重复消费(若想要重复消费,可以修改 group 名,或者设置 Kafka 集群映射,或者手动调整已经变化了的偏移量)

此外,Kafka 的 Receiver 和 Direct 方式、如何保证数据不丢失等问题也很重要。

streaming 消费 kafka 的两种方式 Receiver/Direct 优缺点
https://blog.csdn.net/weixin_…

Kafka 的消息传递语义(重要,若问 Kafka 基本必问),换种问法,Kafka 怎么保持数据的一致性(怎么保证数据 0 丢失)?
1. 幂等写入(idempotent writes)
需要设置好唯一主键等,比如用 redis、mysql
再比如每次往一个目录覆盖写数据,这样主键不容易获取。
一次语义:幂等写入
当获取到数据后,先写到 mysql,再保存 offset,如果在写到 mysql 数据后,在保存 offset 之前宕机,重启作业后也不会影响一次语义,因为会在 mysql 重复更新。
注:在软件开发领域,幂等写入即为同样的请求被执行一次与连续执行多次的效果是一样的,服务器的状态也是一样的,实际上就是接口的可重复调用(包括时间和空间上两个维度)。
2. 事务控制
保证数据和 offset 在同一个事务里面,比如用 mysql,这样需要事务存储的支持。
3. 自己实现 Exactly-once,offset 和数据绑定保存等。

**

**

⑥多益网络

**
40 分钟左右视频面试。
面试官挺和善的,不过问的问题挺多的。记录几个答的不是很好的问题。

   hive join 的类别(方式)?

二次总结:第一想法是内连接外连接全连接,但只答这个的话还表现的水平较低,建议了解以下三种 join 方式。
http://www.cnblogs.com/raymoc…
参考官网链接 https://cwiki.apache.org/conf…
Hive 的三种 join 方式:
Common/Shuffle/Reduce Join(正常 / 一般情况)、
Map Join(大小表 join、不等值 join、结合 union all)、
SMB(Sort-Merge-Buket) Join(大表 join 大表)。

Common/Shuffle/Reduce Join(正常 / 一般情况)

Reduce Join 在 Hive 中也叫 Common Join 或 Shuffle Join
如果两边数据量都很大,它会进行把相同 key 的 value 合在一起,正好符合我们在 sql    中的 join,然后再去组合。

Map Join(大小表 join、不等值 join、结合 union all)

1)大小表连接:
如果一张表的数据很大,另外一张表很少(<1000 行),那么我们可以将数据量少的那张表放到内存里面,在 map 端做 join。
Hive 支持 Map Join,用法如下

2)需要做不等值 join 操作(a.x < b.y 或者 a.x like b.y 等)
这种操作如果直接使用 join 的话语法不支持不等于操作,hive 语法解析会直接抛出错误
如果把不等于写到 where 里会造成笛卡尔积,数据异常增大,速度会很慢。甚至会任务无法跑成功~
根据 mapjoin 的计算原理,MapJoin 会把小表全部读入内存中,在 map 阶段直接拿另外一个表的数据和内存中表数据做匹配。这种情况下即使笛卡尔积也不会对任务运行速度造成太大的效率影响。
而且 hive 的 where 条件本身就是在 map 阶段进行的操作,所以在 where 里写入不等值比对的话,也不会造成额外负担。

3)MAPJOIN 结合 UNIONALL
某些情况下 join 特别慢,可以观察数据,取出特殊(数据特别多的)字段范围放在一组,并使用 mapjoin 与维表关联,放入内存中,除此之外的数据存入另一组,使用普通 join,最后 union all 放到一起。
设置:
当然也可以让 hive 自动识别,把 join 变成合适的 Map Join 如下所示
注:当设置为 true 的时候,hive 会自动获取两张表的数据,判定哪个是小表,然后放在内存中

SMB(Sort-Merge-Buket) Join(大表 join 大表)

大致原理:大表 join 大表时,SMB join 会根据(自动)相同的字段进行类似分区分桶的操作,将大表拆成更小一点的表再进行 join。
设置(默认是 false):

对一组数据频繁插入删除,选哪种数据结构?

我说的链表,因为链表相对于数组来说,更适合插入删除。然后面试官提示说可以用最小堆。
最小堆。https://blog.csdn.net/qq_3793…

给定一个长度为 n 的数组,求前 k 大的元素?

若是求第 K 大的元素,可以考虑用快排的思想,A[0…p-1]、A[p]、A[p+1…n-1]。
取一个中间点 A[p],使 A[p]前面的数都比 A[p]小,A[p]后面的数都比 A[p]大,
若 p +1=K,则 A[p]就是要求解的元素;若 K >p+1, 则在 A[p+1…n-1]中递归查找;若 K <p+1,同理。时间复杂度为 n /2+n/4+……=2n+1,为 O(n).

但要求是要求前 K 大的元素,参见博客(暂时未懂):
https://blog.csdn.net/frankin…

⑦招商银行·招银网络科技

**
一面:
25 分钟左右电话面试,问的问题很常规。只记得一个问题(当时没理解面试官意思):

hive 运行的环境?

面试官应该想问的是 hive 环境的搭建。大体就是 1.Hadoop 集群环境;2. 元数据管理配置。
参见博客 https://blog.csdn.net/qq_4185…”乐言科技 -hive 的 meta store 的三种模式”。

二面:
问的基本是大数据的知识,基本没有新的问题。比较轻松通过了。

三面:
是个秃头大叔(应该是技术总监级别的人物),各种怼成绩单、怼专业,然后手撕三道算法题。(凉)
1. 有 10G 的数据,2G 内存,取中位数。
2. 给你一个字符串(可能很长),字符串包含数字和字母,要求将字符串里的字母反转,但数字不动。
3. 一个整型数组 a,一个数 key,求数组 a 中所有相加等于 key 的子数组。(注:注意子集概念。可能有负数。)

**⑧浪潮集团

多对多,群面,4 个面试官,我那组 7 个应聘者。除了我,其余 6 个都是研究生,不过没有竞争关系,7 个人都是不同的岗位。
1 分钟自我介绍,然后面试官针对简历问了几个问题,分配到每个人的时间可能就 3 分钟左右。
浪潮的面试,感觉就是大概评估一下你的潜力,对技能考量没有太深。
比如,就简单问了下我的项目,问项目还主要问我 mysql 和 redis 是怎么用的,都不太算是大数据的问题。(感觉 4 个面试官好像没有一个懂大数据的)
最后有问我想留在北京的原因,我说 1. 北京就业机会多;2. 还年轻,想在大城市闯闯;3. 女朋友希望我去大城市。

记录一个面试官问另一位面试者的问题,感觉很新颖,回去搜索一下:

远程通讯(比如 ssh),底层是通过什么包进行的?

SSH 认证过程如下:
·  Client 将自己的公钥存放在 Server 上,追加在文件 authorized_keys 中。
·  Server 端接收到 Client 的连接请求后,会在 authorized_keys 中匹配到 Client 的公钥 pubKey,并生成随机数 R,用 Client 的公钥对该随机数进行加密得到 pubKey(R)
,然后将加密后信息发送给 Client。
·  Client 端通过私钥进行解密得到随机数 R,然后对随机数 R 和本次会话的 SessionKey 利用 MD5 生成摘要 Digest1,发送给 Server 端。
·  Server 端会也会对 R 和 SessionKey 利用同样摘要算法生成 Digest2。
·  Server 端会最后比较 Digest1 和 Digest2 是否相同,完成认证过程。

然而,面试官要问的应该不是这个 (至今没懂面试官意思),个人理解问题思路,面试官应该想问的是远程通讯原理。
比如 RPC 的 IO 通讯框架主要有 1.Java nio(基本弃用);2. 基于 mina(曾经火热,现在更新缓慢);3. 基于 netty,最常用,如阿里的 HSF、dubbo 等。底层主要以传输 socket 为主,例如 Hadoop 中存储 client 对象时,用 socket factory 作为 hash key,存储结构为 hashMap <SocketFactory, Client>。

–end–

正文完
 0