面试经历

481 阅读32分钟

积梦智能 因为工作中没有了解过my sql,业务不符合从这里开始就挂了吧,记下来几个问题
1.mysql的锁有了解吗?行锁,表锁,业锁?
2.oauth2.0实现过程?
3.分布式锁有了解吗?回答知道redis的setnx,继续问实现过程?问etcd做锁不可以吗?
分布式锁

4.如何限制goroutine的并发数?
5.用过context的那些用法?有没有用context设置goroutine执行时间?
6.用过go的那些调试工具?回答就是IDE里面界面调试,继续问调试又分性能调试,错误调试,有用过pprof吗?

1.MySQL中按照锁的粒度可以细分为行锁、页锁、表锁

  • 行锁
    行锁的锁定颗粒度在MySQL中是最细的,应用于InnoDB存储引擎,只针对操作的当前行进行加锁。并发情况下,产生锁等待的概率较低,支持较大的并发数,但开销大,加锁慢,而且会出现死锁。 在InnoDB中使用行锁有一个前提条件:检索数据时需要通过索引!因为InnoDB是通过给索引的索引项加锁来实现行锁的。 在不通过索引条件查询的时候,InnoDB会使用表锁,这在并发较大时,可能导致大量的锁冲突。此外,行锁是针对索引加锁,存在这种情况,虽然是访问的不同记录,但使用的是同一索引项,也可能会出现锁冲突。 提示:不一定使用了索引检索就一定会使用行锁,也有可能使用表锁。因为MySQL会比较不同执行计划的代价,当全表扫描比索引效率更高时,InnoDB就使用表锁。因此需要结合SQL的执行计划去分析锁冲突。 行锁会产生死锁,因为在行锁中,锁是逐步获得的,主要分为两步:锁住主键索引,锁住非主键索引。如:当两个事务同时执行时,一个锁住了主键索引,在等待其他索引;另一个锁住了非主键索引,在等待主键索引。这样便会发生死锁。InnoDB一般都可以检测到这种死锁,并使一个事务释放锁回退,另一个获取锁完成事务。
  • 表锁
    表锁的锁定颗粒度在MySQL中是最粗的,InnoDB、MyISAM引擎中都有应用,对当前整张表加锁。不适合高并发的场景,但开销小,加锁快,不会出现死锁,发生锁冲突的概率最大。
  • 页锁
    页锁的粒度介于行锁和表锁之间,应用于BDB引擎,并发度一般,开销和加锁速度也介于行锁和表锁之间

4.限制并发数,用一个无阻塞的通道就可以了,并发开始写入一个数,并发结束释放

5.context有几种用法? context包里有几个重要函数

func WithCancel(parent Context) (ctx Context, cancel CancelFunc)
func WithDeadline(parent Context, deadline time.Time) (Context, CancelFunc)
func WithTimeout(parent Context, timeout time.Duration) (Context, CancelFunc)
func WithValue(parent Context, key, val interface{}) Context

withCancel函数用法 这个函数可以创建一个可取消的子Context,然后当作参数传给goroutine使用,这样就可以使用这个子Context跟踪这个goroutine。 在goroutine中,使用select调用<-ctx.Done()判断是否要结束,如果接收到值的话,就可以返回结束goroutine了;如果接收不到,就会继续进行监控。 调用context.WithCancel(parent)函数生成子Context的时候返回的cancel函数是CancelFunc类型的。我们调用它就可以发出取消指令,然后我们的监控goroutine就会收到信号,就会返回结束 具体是这个函数会将ctx.Done()返回的通道关闭,关闭的通道是可以读取值的,所以select调用<-ctx.Done() 就从阻塞变成可以读,就会结束了,default处理过程中cancel了,需要在default处理完,才会到<-ctx.Done(),不会出现一旦cancel了,强行终止default,立马执行<-ctx.Done()case语句

func main() {
	ctx, cancel := context.WithCancel(context.Background())
	go watch(ctx,"【监控1】")
	go watch(ctx,"【监控2】")
	go watch(ctx,"【监控3】")

	time.Sleep(10 * time.Second)
	fmt.Println("可以了,通知监控停止")
	cancel()
	//为了检测监控过是否停止,如果没有监控输出,就表示停止了
	time.Sleep(5 * time.Second)
}

func watch(ctx context.Context, name string) {
	for {
		select {
		case <-ctx.Done():
			fmt.Println(name,"监控退出,停止了...")
			return
		default:
			fmt.Println(name,"goroutine监控中...")
			time.Sleep(2 * time.Second)
		}
	}
}

WithDeadline函数 这个应该就是面试官问的问题了,怎样利用context设置goroutine的执行时间 WithDeadline函数,和WithCancel差不多,它会多传递一个截止时间参数,意味着到了这个时间点,会自动取消Context,当然我们也可以不等到这个时候,可以提前通过返回的取消函数进行取消

WithTimeout和WithDeadline基本上一样,这个表示是超时自动取消,是多少时间后自动取消Context的意思

WithValue函数 可以传递元数据到goroutine当中,相当于给并发函数传参数,只不过通过context传递

最后Context是线程安全的,可以放心的在多个goroutine中传递

6.错误调试可以直接用IDE里面的debug就可以了,性能调试的话需要用go自带工具pprof pprof

工具型应用,运行一下就结束,可以在代码里将信息保存在文件中

服务性应用,如web应用,导入"net/http/pprof包后,会自动创建默认路由,访问路径可以得到相应诊断信息,CPU 的内存的等

滴滴一面记录
1.golang中的channel底层实现原理?采用什么机制接收发送数据?
2.事件处理方式select poll epoll区别? epoll如何实现不用遍历就获得ready文件描述符?
3.golang是如何实现高并发的?假设现在有多个物理核,高并发是怎么实现的?
4.golang中协程和线程的区别?
5.编程语言面向对象的特点有哪些?
6.虚函数表在内存中是如何分配的?一个空类占多少内存?类有一个int类型变量?有一个虚函数表?有一个自己的成员变量分别占多少内存?
7.MQTT协议怎么解析的?
8.tcp 和 udp的区别?四次握手实现阐释?为什么三次握手结束四次握手?time_wait在什么情况下会出现? tcp在那些场景下会返回reset?
9.redis适合场景? redis中有两个锁,两者有什么区别?
10.mongodb和mysql有什么区别?mongodb a b c复合索引,通过a b能找到吗?
11.进程和线程有什么区别?多进程有什么好处?多进程和多线程分别适用于那些场景?好坏?

1.channel底层是一个结构体,新建一个通道也就是分配一块内存给这个结构体,结构体里面有缓冲buf(有缓冲的通道才有buf),是一个环形链表,如果缓冲满了,有一个协程在发送数据,就会阻塞,底层是看到buf满了,把这个协程给放到结构体中的发送协程队列中,这个协程用调度器将自己等待,让出资源让其他协程使用,直到有读数据,从buf读取衣蛾数据,channel会将阻塞的协程从队列拿出来,将数据写到buf,协程重新放回可执行协程队列,具体看文章

2.这个问题在这里,详细问了epoll为什么不需要遍历所有文件描述符就可以得到准备好的文件描述符,回答 中间加了一层,用一个链表存放所有准备好的文件描述符,应该对了就没再继续往下问了,但是还是要自己深究弄更明白

3.golang 并发采用二GPM模型,G是goroutine,P是逻辑处理器,M是系统线程,创建一个goroutine先会放到全局队列当中,然后调度器将可执行的goroutine分配给一个逻辑处理器,放到逻辑处理器的本地队列当中,逻辑处理器与一个可用的系统线程绑定,线程处理队列里面的goroutine,如果有一个goroutine阻塞了,会将goroutine和线程两个从逻辑处理器上分离,给逻辑处理器在找一个可用的线程,处理队列里面其他的goroutine,如果我们在一个Goroutine中通过go关键字创建了大量G,这些G虽然暂时会被放在同一个队列, 但如果这时还有空闲P(系统内P的数量默认等于系统cpu核心数),Go运行时系统始终能保证至少有一个(通常也只有一个)活跃的M与空闲P绑定去各种G队列去寻找可运行的G任务,该种M称为自旋的M。一般寻找顺序为:自己绑定的P的队列,全局队列,然后其他P队列。如果自己P队列找到就拿出来开始运行,否则去全局队列看看,由于全局队列需要锁保护,如果里面有很多任务,会转移一批到本地P队列中,避免每次都去竞争锁。如果全局队列还是没有,就要开始玩狠的了,直接从其他P队列偷任务了(偷一半任务回来)。这样就保证了在还有可运行的G任务的情况下,总有与CPU核心数相等的M+P组合 在执行G任务或在执行G的路上(寻找G任务) 所以阻塞的时候,和线程逻辑处理器主动寻找可执行的goroutine这些策略对高并发都有帮助
阅读文章 总结一下高并发:
1.GPM模型
2.阻塞执行策略
3.主动寻找任务
4.协程切换不涉及内核,资源消耗小,代价小等
多个物理核,默认逻辑处理器和CPU个数一致,将goroutine平均分配到所有逻辑处理器上,让系统线程执行。

  1. 协程 线程区别 好文章
  • 栈大小区别 线程栈大小是固定的值,一般2mb,协程不是,go采用了动态扩张收缩的策略:初始化为2KB,最大可扩张到1GB
  • goroutine没有id 每一个线程有唯一id,可以通过id操作某个线程,协程没有
  • 切换
    协程和线程的区别在于:线程切换需要陷入内核,然后进行上下文切换,切换时间点也是内核决定,而协程在用户态由协程调度器完成,不需要陷入内核,而且切换时间点由调度器决定,这代价就小了

5.面向对象特点 封装、继承、多态
封装,也就是把客观事物封装成抽象的类,并且类可以把自己的数据和方法只让可信的类或者对象操作,对不可信的进行信息隐藏

6.空类占1个字节,有虚函数,类里面只是存储了一个指针,指针指向虚函数表,无论有多少个虚函数,都占4个字节,表示表的地址,当我们说类大小实际是说类实体的大小,成员函数还是以一般的函数一样的存在,不再实体里面。即成员函数的大小不在类的对象里面,同一个类的多个对象共享函数代码,所以不占空间

关于多态,基类指针指向派生类地址

8.之前写的 time_wait就是第四次握手之后等待时间,tcp 返回reset这个实际项目没有碰到不会没关系

9.redis适合小而热场景,两个锁 红锁和setnx
红锁讲的很详细的文章 文章一 文章二
基于单Redis节点的分布式锁在failover的时候会产生解决不了的安全性问题,因此antirez提出了新的分布式锁的算法Redlock,它基于N个完全独立的Redis节点

antirez提出的redlock算法大概是这样的:

在Redis的分布式环境中,我们假设有N个Redis
master。这些节点完全互相独立,不存在主从复制或者其他集群协调机制。我们确保将在
N个实例上使用与在Redis单实例下相同方法获取和释放锁。现在我们假设有5个Redis
master节点,同时我们需要在5台服务器上面运行这些Redis实例,这样保证他们不会同时
都宕掉。

为了取到锁,客户端应该执行以下操作:

获取当前Unix时间,以毫秒为单位。
依次尝试从5个实例,使用相同的key和具有唯一性的value(例如UUID)获取锁。当向Redi
s请求获取锁时,客户端应该设置一个网络连接和响应超时时间,这个超时时间应该小于
锁的失效时间。例如你的锁自动失效时间为10秒,则超时时间应该在5-50毫秒之间。这样
可以避免服务器端Redis已经挂掉的情况下,客户端还在死死地等待响应结果。如果服务
器端没有在规定时间内响应,客户端应该尽快尝试去另外一个Redis实例请求获取锁。
客户端使用当前时间减去开始获取锁时间(步骤1记录的时间)就得到获取锁使用的时间
。当且仅当从大多数(N/2+1,这里是3个节点)的Redis节点都取到锁,并且使用的时间
小于锁失效时间时,锁才算获取成功。
如果取到了锁,key的真正有效时间等于有效时间减去获取锁所使用的时间(步骤3计算的
结果)。
如果因为某些原因,获取锁失败(没有在至少N/2+1个Redis实例取到锁或者取锁时间已经
超过了有效时间),客户端应该在所有的Redis实例上进行解锁(即便某些Redis实例根本
就没有加锁成功,防止某些节点获取到锁但是客户端没有得到响应而导致接下来的一段时
间不能被重新获取锁)。

10写不动了,区别 复合索引 mongodb索引类型有

默认创建的_id索引
单索引
复合索引
全文索引
地理空间索引

mongodb a b c复合索引,通过a b能找到吗,面试官考察的应该是复合索引的prefix概念,

使用 compound 索引需要满足 prefix 原则
Index prefix 是指 index fields 的左前缀子集,考虑以下索引:
{ "item": 1, "location": 1, "stock": 1 }
复制代码这个索引包含以下 index prefix:
{ item: 1 }
{ item: 1, location: 1 }
复制代码所以只要语句满足 index prefix 原则都是可以支持使用 compound index 的

所以a b满足a b c的前缀要求可以查找到

11.进程线程区别 多进程相比较来说,进城之间独立,比较可靠稳定,一个线程挂了就会导致整个进程挂掉。

腾讯网络协议开发电话面试
1.grpc底层协议是怎么实现的? 有抓过包吗?
2.http2了解吗? https和http有什么区别?https具体怎么加密的?
3.tcp的状态机是什么样的?tcp三次握手?第一次握手发送syn包后socket处于什么状态? tcp流量控制和拥塞控制的区别?
4.MQTT报文格式?都有什么主题?MQTT和websocket区别?MQTT轻量体现在哪里?MQTT有心跳机制吗?如果有一个链接长期不发数据还会一直保持链接吗?
5.数据库索引底层实现原理?(其中一种是B树,B+树)
6.多线程之间有哪些同步方法? (加锁?)
7.malloc底层系统调用? (brk)

5.MongoDB 索引选择B-树,而 Mysql 索引选择B+树 mongodb专栏

7.看了一下,和stl差不多维护一个链表,然后也有整合之类的文章

天壤智能
1.sync.map 怎么实现读写进程安全的?
2.restful用过?gin框架路由底层实现?
3.linux信号了解吗?kill -9 pid -9是什么,为什么用-9就可以杀死进程?
4.进程之间如何通信?
5.如何程序运行不中断情况下修改日志打印级别?
6.我问了怎么学操作系统?

1.说了两个重要函数load store,load返回的参数2ok true代表找到这个键,false代表没有找到, store没有返回值

2.restful用了gin开源框架,Gin的路由实现使用了类似前缀树的数据结构,只需遍历一遍字符串即可,时间复杂度为O(n) 这个我之前不知道,但是蒙对了,嘿嘿

3.当你执行一个"kill"命令,你实际上发送了一个信号给系统,让它去终结不正常的应用,总共有60个你可以使用的信号,但是基本上你只需要知道SIGTERM(15)和SIGKILL(9)。可以用kill -l查看所有信号列表,
SIGTERM - 此信号请求一个进程停止运行。此信号是可以被忽略的。进程可以用一段时间来正常关闭,一个程序的正常关闭一般需要一段时间来保存进度并释放资源。换句话说,它不是强制停止。
SIGKILL - 此信号强制进程立刻停止运行。程序不能忽略此信号,而未保存的进度将会丢失。

4.linux进程间通信有6种方式

  • 消息队列 在内核中创建一队列,消息队列可以认为是一个全局的一个链表,链表节点钟存放着数据报的类型和内容,有消息队列的标识符进行标记

  • 管道
    匿名管道:在内核中申请一块固定大小的缓冲区,程序拥有写入和读取的权利,一般使用fork函数实现父子进程的通信。
    命名管道FIFO:在内核中申请一块固定大小的缓冲区,程序拥有写入和读取的权利,没有血缘关系的进程也可以进程间通信。

  • 信号
    信号是比较复杂的通信方式,用于通知接受进程有某种事件发生,除了用于进程间通信外,进程还可以发送信号给进程本身,linux kill -9 就是给进程发送一个信号

  • 信号量
    信号量是一个计数器,可以用来控制多个进程对共享资源的访问。它常作为一种锁机制,防止某进程正在访问共享资源时,其他进程也访问该资源。因此,主要作为进程间以及同一进程内不同线程之间的同步手段

  • 共享内存
    将同一块物理内存一块映射到不同的进程的虚拟地址空间中,实现不同进程间对同一资源的共享,共享内存是最快的 IPC 方式

  • socket通信
    可用于不同机器之间的进程间通信

总结 是一个计数器。信号量用于实现进程间的互斥与同步,而不是用于存储进程间通信数据

5.是第四个问题的延伸,我回答了可以用一个http接口,设置修改程序内全局变量,日志打印会查看全局变量的值,这样做到动态更新配置。面试官说不想暴露接口在外面,所以就可以用上面几种进程通信的方法,比如共享内存,找到共享内存的地址将里面的值更新就可以,只用几行命令就可以实现,但一般会写个小程序,往共享内存更新数据

6.面试官人很好,给了很多意见,让我看C++里面用一个包epoll实现一台机器10万链接,网上可以搜一台机器10万连接,go里面也实现了epoll,还有nginx也是C写的,实现机制也是select epoll poll 可以看一下,redis集群也可以了解一下

B站直播开发

1.了解那些排序?排序稳定是指?那些排序算法是稳定的?
2.堆排序是怎么实现的?一千万个数找到第100大的数?
3.Mac地址和IP关系或者区别?
4.redis和memcached区别?redis数据结构了解吗?ziplist数据结构是什么样的?
5.做一个简单的会议室预订系统,数据库应该怎么建表?怎么查询是否可以约定某一时间段?
6.channel有几种类型?
7.我问面试官对我的评价,建议?

1.稳定是相等数据的相对位置保持不变,堆排序,快速排序,选择排序是不稳定的
2.堆排序从下到上建堆,找到第一百大的数,建立一个最大堆,根节点是100个数里面最大值,每次跟根节点比较,如果比根节点大就直接扔掉,如果比根节点小就替换根节点,然后下溯,维持堆排序,直到找到比他大节点交换位置,直到叶节点,比完一千万个数,这100个是所有数里面最小的100个,根节点就是第100大的数

3.Mac地址是数据链路层及以下使用地址,IP是网络层及以上使用地址,IP数据报放在Mac帧的数据部分,IP地址在数据链路层是看不到的,利用ARP协议找到IP地址对应的Mac地址
4.

redis mamcached
数据结构 丰富 string list set zset hash 简单k-v类型
使用核 单核 多核
持久化 可以持久化 不可以
性能 适合小数据 100k以上的数据中,Memcached性能要高于Redis

redis总结

5.表里面应该有 谁预定了哪个房间 开始时间 结束时间 四个字段 查询某个房间startTIME endTIME时间段有没有预约 查询语句应该是 开始时间《endTIME && 结束时间》startTIME 如果找到数据则说明已经有预约 6.channel有阻塞 无阻塞
7.会议室约定系统那里可以表现更好一点,一般面试这种题目很常见,让你设计一个建议的系统,比如浏览器只需要输入短网址就可以自动替换成完整网址怎么设计(用哈希映射)或者设计一个发号器保证数字全局唯一(41bit作为毫秒数 10bit作为机器编号 12bit作为毫秒内序列号类似,机器编号确保不同主机号码不同,毫秒数记录确保同一机器不同毫秒号码不同 毫秒内序列号确保同意主机同一毫秒号码不同)

b站 智能云平台 (一个半小时,最后还没有问我有什么问题吗 好变态哦)

1.gin 框架里面路由像 A/B A/:B实际用的时候会处理的模糊,出现错误吗?
2.怎么应对高并发情况?有什么优化方法?
3.grpc为什么要用?有从性能方面考虑吗?
4.linux文件格式了解吗?
5.cgroup namespace了解吗?
6.网络三次握手?
7.linux一些命令 查找文件 内核版本 机器启动时间 查看进程 CPU 端口号 查看DNS路由 文本查找某字段 截取文本字段
8.双向链表?反转链表实现思路?
9.二叉树中序遍历实现思路?
10.各种算法 以及复杂度?哪些不稳定?B站真的很喜欢问算法 感觉说的算法种类还不够多。他问我还有吗? 快排,堆排具体怎么实现的?

11.kubectl 各种命令 不知道的有kubectl edit kubectl create 怎么查看一个deployment的yaml文件,kubectl get deployment -o yaml
k8S master节点里面又有哪些组件?controllermanager 做什么工作? scheduler分配pod给节点如何确定给哪一个节点?

12.docker 后端存储格式哪些?直到shim吗?docker相关cgroup namespace了解吗? docker一些常见命令 查看容器信息 查看所有容器

13.git 常用命令 如果一些文件修改已经add到暂存区,怎么回退?(git reset -hard HEAD^) 合并冲突怎么解决? git rebase了解吗?(将分叉的提交历史变直)

1.gin有个缺点 :符号不支持路由排序,会认为是路由冲突。 比如: 路由Get("/name")和 Get("/:id") ,一般来说,只要把Get("/name")放在Get("/:id")前面,就是不冲突的。路由模块,会先尝试匹配前面那个,没匹配上,再去匹配后面的。gin会给出提醒,不让编译通过

2.应对高并发 )系统集群化部署,分布式部署,防止单机宕机,负载均衡流量分摊 )数据库分库分表 + 读写分离 分库,机器请求数变少,读写分离也是 )缓存集群引入,加快查询热数据速度 )引入消息中间件集群,异步处理,减轻服务压力

3.gRPC是由Google主导开发的RPC框架,使用HTTP/2协议并用Protobuf作为序列化工具。与REST不同的是,REST是基于HTTP1.1 JOSN格式的一种轻量级服务模式,那么从这两方面来对比gRPC与REST就比较容易了。

首先可以从JOSN与Protobuf之间的差别入手进行对比,Protobuf很难读,它是面向机器的文字格式,而JOSN则是面向人的;Protobuf相对于JOSN而言编解码速度都非常快;最后就是兼容性,现在基本所有浏览器都支持JOSN格式,而Protobuf目前仅部分语言支持。 HTTP/2 采用二进制格式传输数据,而非 HTTP 1.x的文本格式,二进制协议解析起来更高效

7.查看路由信息 traceroute 内核版本 uname 机器启动时间 uptime cat /proc/uptime

黑凤梨 电话面试
1.gin框架里面中间件限流?
gin中间件两大功能 限流 身份验证
rate-limit 限流中间件,下面设定1qps,超过则报“服务繁忙,请稍后再试...

lmt := tollbooth.NewLimiter(1, nil)
lmt.SetMessage("服务繁忙,请稍后再试...")

2.mongodb索引哪些类型?怎么提高查找性能?
默认,单,复合,地图索引 加索引
3.sync.map怎么实现线程安全的?
解释

今日头条

1.数组和切片有什么区别?

	a := make([]int,0,4)
	a=append(a,1)
	a=append(a,2)
	a=append(a,3)
	a=append(a,4)
	c := a[2:4]
	c[3]=5
	c=append(c,6)
	c=append(c,7)
	c=append(c,8)
	c=append(c,9)
	c[3]=6
	i := a[3]
	print(i)

以上题目a[3]为多少?

妈的,挖坑让我往里跳,c[3]=5根本运行会出错,c只有两个元素,哪有第4个元素,头条面试官真的坏! 主要考察点就是从一个切片创建出另一个切片,两者会共享同一个底层数组,所以修改共享部分,另一个切片也会感知到

2.redis为什么设计这么多数据类型?如果让你设计一个redis,应该怎么做?
头条面试果然水深,都是考理解力的,死记硬背不奏效 设计redis我说了底层用一个redisObject封装每一个键 值,用一个字典存储所有的键值对,过期的也用一个字典存储,expires 字典的键是一个指向dict 字典(键空间)里某个键的指针,而字典的值则是键所指 向的数据库键的到期时间,面试官问我定期删除的时候去哪里找,内存还是磁盘?我说磁盘他说对

3.考了一个深度优先遍历的算法题,类似于leetcode 200题岛屿数量

寒武纪
1.deployment 和 statefulset 有什么区别?

在 Kubernetes 的世界中,ReplicaSet 和 Deployment 主要用于处理无状态的服务,无状态服务的需求往往非常简单并且轻量,每一个无状态节点存储的数据在重启之后就会被删除,虽然这种服务虽然常见,但是我们仍然需要有状态的服务来实现一些特殊的需求,StatefulSet 就是 Kubernetes 为了运行有状态服务引入的资源,例如 Zookeeper、Kafka 等 StatefulSet 会为每个 Pod 设置一个单独的持久标识符,这些用于标识序列的标识符在发生调度时也不会丢失 它为了解决有状态服务的问题,它所管理的Pod拥有固定的Pod名称,启停顺序 RC、Deployment、DaemonSet都是面向无状态的服务,它们所管理的Pod的IP、名字,启停顺序等都是随机的,而StatefulSet是什么?顾名思义,有状态的集合,管理所有有状态的服务,比如MySQL、MongoDB集群等。

2.damonset了解吗?
DaemonSet 确保全部(或者某些)节点上运行一个 Pod 的副本。当有节点加入集群时,也会为他们新增一个 Pod 。 当有节点从集群移除时,这些 Pod 也会被回收。删除 DaemonSet 将会删除它创建的所有 Pod

3.kubelet是干什么的?如果kubelet突然挂掉了然后又重启了,他是怎么实现当前node状态和想要状态一样呢?
4.算法题,一个一维数组,一个整型值target 求数组中所有元素和为target的组合 1 1 2 3 4 5 target=5 [1,4] [1,1,3] [2,3] [5] 注意不能有相同数组,比如这里两个1 不能都和4组

思路:先排序 遍历数组,以每一个元素为起点深度遍历,遍历时哈希去重,前面已经有该值作为起点,则跳过,比如上面第2个1就不能作为起点,因为前面的1已经把所有可能都遍历过了

华为南京研究所
1.C++中基类析构函数为什么是虚函数?
这样做是为了当用一个基类的指针删除一个派生类的对象时,派生类的析构函数会被调用,如果基类析构函数不是虚函数,用一个基类指针指向派生类对象,delete时候不会调用派生类析构函数,可能造成内存泄露

2.如果git修改已经上传到了远程分支,怎么取消

Git 撤销已经 push 到远端的 commit
情况1:本地不需要回退(即让远端回退到本地的版本)
提交到远端
git push origin <分支名> --force
情况二:本地需要回退
先在本地回退到需要的版本
git reset --hard <需要回退到的版本号(只需输入前几位)>
版本号可用如下指令查看
git log remotes/origin/分支名
提交到远端
git push origin <分支名> --force

3.给一个整型数组,求三数之和乘积最大?

思路:1排序 2最小两个数和最大一个数的乘积  最大三个数的乘积 取两者最大值

探探
1.golang 和C++?

C++ golang
运行速度
变量初始化 变量前面要加类型名 简短声明
数组/切片 数组,固定长度 切片动态增长
支持泛型 支持 不支持
继承/组合 继承 组合

Go语言并不包括如异常处理、继承、泛型、断言、虚函数等功能,但增加了slice型、并发、管道、垃圾回收、接口(interface)等特性的语言

2.业务里面为什么用mongodb不用mysql
MongoDB的灵活数据模型,文档可以灵活的添加删除字段

3.golang内存管理?
Go中的内存管理机制,一个方面是内存池,另一个方面是垃圾回收 关于内存池,先讲一下stl里面内存分配,然后golang里面更复杂一点,分的更细, Go中为每个系统线程分配一个本地的MCache(前面介绍的结构体M中的MCache域),少量的地址分配就直接从MCache中分配,并且定期做垃圾回收,将线程的MCache中的空闲内存返回给全局控制堆,大对象直接从全局控制堆上以页(4k)为单位进行分配

Go语言中使用的垃圾回收使用的是标记清扫算法。进行垃圾回收时会stoptheworld。不过,在当前1.3版本中,实现了精确的垃圾回收和并行的垃圾回收,大大地提高了垃圾回收的速度,进行垃圾回收时系统并不会长时间卡住。

4.golang线程和Java线程不同? JVM 会为每个线程分配 1M 的栈,Go 的栈是动态分配大小的,随着存储数据的数量而增长和收缩, Goroutine 只有大约 4KB 的栈 因为 JVM 使用了操作系统线程,所以依赖操作系统内核来调度它们。当内核从一个线程切换至另一个线程时,有很多的工作要做,golang用自己的调度器完成切换

5.redis 跳跃表怎么插入数据?

6.redis里面一些设计很多键的操作可能会花费很多时间,怎么优化?

7.乐观锁,悲观锁?应用?

悲观锁
总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。
乐观锁
总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的
乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适

作者:SnailClimb
链接:https://juejin.cn/post/1fc8
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

腾讯 1.如何不使用额外空间交换两个数的值?

方法1:

int a = 10;
int b = 20;
a = a^b;
b = b^a;
a = a^b;
这个方法用到了一个事实:任何数自己和自己异或(XOR)后等于0.
方法2:

int a = 10;
int b = 20;
a = a + b;
b = a - b;
a = a - b;

这两种方法最好选用第一种,因为第二种会有溢出的情况发生
————————————————
版权声明:本文为CSDN博主「beiyeqingteng」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/beiyeqingteng/article/details/7105446

2.tcp传输中,ack为什么要取随机值,不是一个固定值? 协议统一规定,防止一些不法分子掌握其中规律,传递非法数据回来

3.为什么要三次握手?

4.500万个数找第100万大的? -用最大堆,时间复杂度O(Nlogn) N=500万 n=100万 空间 o(n) n=100万 -用bitmap,每一位表示一个数,如果是500万里面的数则置1,最大值是2的32次方,则需要这些个位 时间O(N) 空间o(2的32次方位)换算一下除以8就是字节 -用快排的方式,找第100万大的数,没有找到就在左半部分或者有半部分查找,面试官说时间可以达到O(N),但是我觉得这样是O(NlgN),空间为O(1)

5.一对夫妻有两个小孩,其中一个是男孩,另一个是女儿的概率是多少?
首先,两个小孩概率上四中情况,男男,女女,男女,女男,一个为男生,排序女女情况,还有三种情况,其中两种有女孩,所以2/3

魔门塔面试 挺难 1.C++ golang共同点

2.C++有的数据结构golang里面有吗

3.如何在golang里面实现C++里面的set,应该考虑那些问题?

4.redis插入数据api接口是什么?

5.dockrfile里面都有那些常用命令? endpoint 和 cmd 区别?

CMD 指令允许用户指定容器的默认执行的命令。
此命令会在容器启动且 docker run 没有指定其他命令时运行。
如果 docker run 指定了其他命令,CMD 指定的默认命令将被忽略。
如果 Dockerfile 中有多个 CMD 指令,只有最后一个 CMD 有效
下面看看 CMD 是如何工作的。Dockerfile 片段如下:
CMD echo "Hello world"
运行容器 docker run -it [image] 将输出:
Hello world
但当后面加上一个命令,比如 docker run -it [image] /bin/bash,CMD 会被忽略掉,命令 bash 将被执行:
root@10a32dc7d3d3:/#

ENTRYPOINT 看上去与 CMD 很像,它们都可以指定要执行的命令及其参数。不同的地方在于 ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令
ENTRYPOINT 中的参数始终会被使用,而 CMD 的额外参数可以在容器启动时动态替换掉。
比如下面的 Dockerfile 片段:
ENTRYPOINT ["/bin/echo", "Hello"]  
CMD ["world"]
当容器通过 docker run -it [image] 启动时,输出为:
Hello world
而如果通过 docker run -it [image] CloudMan 启动,则输出为:
Hello CloudMan