腾讯面经

书中人 2022年09月04日 799次浏览

一面

询问项目经历;

 项目架构

hashmap理解。

hash数组加拉链法链表组成的一个(k,v)结构的基础存储容器。 16 * 0.75 8 * 6  

redis分布式锁的理解?

在 jdk 中为我们提供了多种加锁的方式:
(1)synchronized 关键字
(2)volatile + CAS 实现的乐观锁
(3)ReadWriteLock 读写锁
(4)ReenTrantLock 可重入锁
锁的准则:
	互斥性。
	不会发生死锁。
	具有容错性。
	解铃还须系铃人。
	具备可重入特性
	高性能 & 高可用
	锁的公平性

如果redis作为分布式锁的时候,主节点挂掉了,但是数据还没有同步到从节点,这种情况怎么办?

脑裂问题-> 使用RedLock红锁概念,布置多台机器,每次只有超过半数的机器获取到锁时才算真正拿到锁,否则就释放掉当前锁。

12306网站设计架构。

用户系统
余票查询系统
	复杂的余票动态查询系统
订单系统
支付系统
通知系统

mysql两种存储引擎的区别

InnoDB:支持事务,行锁,B树索引、集群索引、支持外键、批量插入数据慢,数据可压缩
MyIsAM:不支持事务,表锁、B树索引、全文索引、不支持外键、批量插入较快,数据不可压缩

如果由大量的增删操作,那么应该选择哪个存储引擎,为什么?

innerdb,因为增删是操作类,容易产生数据不一致情况,所以需要事物保证数据安全

谈谈对面向对象的理解,谈谈对多态的理解。


tcp四次挥手过程?为什么等待2MSL。

如果Client直接CLOSED了,那么由于IP协议的不可靠性或者是其它网络原因,导致Server没有收到Client最后回复的ACK。
那么Server就会在超时之后继续发送FIN,此时由于Client已经CLOSED了,就找不到与重发的FIN对应的连接,最后Server就会收到RST而不是ACK,
Server就会以为是连接错误把问题报告给高层。这样的情况虽然不会造成数据丢失,但是却导致TCP协议不符合可靠连接的要求。
所以,Client不是直接进入CLOSED,而是要保持TIME_WAIT,当再次收到FIN的时候,能够保证对方收到ACK,最后正确的关闭连接。

拥塞控制的算法有哪几种?慢开始前期是指数型增长还是线性增长?


一个无序数组,求topk。

1,排序 o(nlogn + k)
 Arrays.sort(arr);
 int val = arr[arr.length - k];
2,优先队列 o(n+logok)
PriorityQueue<Integer> queue = new PriorityQueue<>((k1, k2) -> k1 - k2);
		for (int i : arr) {
			if (queue.size() < k) {
				//add 超出队列会报错,offer不会报错
				queue.offer(i);
			} else {
				//peek返回不移除
				if (queue.peek() < i) {
					//移除头部,如果没有为null
					queue.poll();
					queue.offer(i);
				}
			}
		}
	System.out.println(queue.poll());

分库分表是以什么维度来划分的?划分的算法是怎样的,会不会出现数据分配不均衡的情况。

	根据不同的业务比如租户来分库
	根据账户id来分表
	

myisam和innodb支持锁的粒度是怎样的?

InnoDB:支持事务,行锁,B树索引、集群索引、支持外键、批量插入数据慢,数据可压缩
MyIsAM:不支持事务,表锁、B树索引、全文索引、不支持外键、批量插入较快,数据不可压缩

解决缓存击穿的方式有哪几种?

击穿:主要是`热点数据` 穿透缓存直接搭载db上,导致出现数据库压力过大。
	1,设置热点数据不过期,
	2,加互斥锁,比如用redis的setnx,如果setnx失败返回0那么就说明有线程已经去查询了,本一直循环get就行了;
穿透:缓存中没有,请求打到数据库	
	布隆过滤器 一个大的bitmap中保存了所有数据,没有的直接给拦截掉
	查询出来的没有值也给缓存成默认只,但是给失效时间短点,一般不超过5分钟
雪崩:在同一时间,大量的缓存集中失效,导致大量的请求打到数据库,造成数据库压力大
	缓存失效时间家随机数,保证不再同一时间大量失效
	热点数据永不过期
	分布式的情况,将热点数据均匀分布到不同的缓存数据机器上

加锁的时候什么时候选择本地锁,什么时候选择分布式锁?

如果是单项目,单服务部署,采用本地锁,不走网络io性能快,效率高,实现简单;
如果是分布式项目,多服务器部署,采用分布式锁,多服务器共享一个锁,解决多地同时执行出现的错误数据;

排序算法你知道那些?快速排序平均时间复杂度和最差时间复杂度。partition过程中最差情况是什么样的,描述一下。

	交换类型:冒泡排序,快速排序,
	插入排序:简单插入,希尔排序
	选择排序:简则选择,堆排序
	归并排序:二路归并排序,多路归并排序
	
快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序,它采用了一种分治的策略,通常称其为分治法。快速排序算法通过多次比较和交换来实现排序,其排序流程如下:
(1)首先设定一个分界值,通过该分界值将数组分成左右两部分。
(2)将大于或等于分界值的数据集中到数组右边,小于分界值的数据集中到数组的左边。此时,左边部分中各元素都小于或等于分界值,而右边部分中各元素都大于或等于分界值。
(3)然后,左边和右边的数据可以独立排序。对于左侧的数组数据,又可以取一个分界值,将该部分数据分成左右两部分,同样在左边放置较小值,右边放置较大值。右侧的数组数据也可以做类似处理。
(4)重复上述过程,可以看出,这是一个递归定义。通过递归将左侧部分排好序后,再递归排好右侧部分的顺序。当左、右两个部分各数据排序完成后,整个数组的排序也就完成了。

一个屋子有100栈灯,序号分别是1-100,有打开或关闭两种状态,然后有100个人,序号分别是1-100,然后每个人都会进到屋子里面,且每个人都会把自己序号倍数的等执行一次操作(打开或关闭),问最终会有几盏灯打开?

2 * 2 * 2 * 2 * 2 * 2 = 64 == 6 盏灯

二面

询问项目经历。

	

分布式锁如何设计?

避免死锁: 可以通过 超时时间来控制
可用性:搭建多台机器,采用Redlock的思想,比如5台机器,每次获取超过3台机器加锁成功才算成功 ---》master-slave
分布式锁提高可用性主要是网络问题,部署内网,降低网络故障率

网络io模型,搜索引擎。

	搜索引擎,主要是倒排索引的建立。

java的虚引用是什么用的?

强引用-》软引用-》弱引用-》虚引用
虚引用在任何时候都能被gc回收,无法通过虚引用获取一个对象实力,
他的存在可以用来判断对象什么时候被gc回收的,可以利用虚引用在销毁之前做一些操作,比如记录释放资源时间等。

设计一个登录态系统。如何保证密码加传输。如果你想服务器请求非对称加密的公钥时,请求被拦截篡改你怎么办?

服务器发送给客户端的登陆页面里嵌上一个一次性且有时效性的字符串Salt,客户端在传回密码时将Salt和密码连接在一起进行Hash再提交。
这样客户端每次登录,由于获取到的Salt不同,产生的Hash值也不同,且登录后本次使用的Salt/Hash值立刻作废,攻击者无法通过重放截获的信息登录。
	
	1,简单的用户名家密码成功tokne的登陆方式即jwt,每次请求都会携带token,服务段通过token反解析出用户,进行操作
	但是这样局限性必须知道用户名加密码,不能授权给其他用户,否则就会泄露用户名密码
	2,oauth登陆:
	

数据库主从复制时如何做的?但是如果突然挂掉了,如何保证挂掉那段时间的数据?

	MySQL支持单向、异步复制,复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。
	从服务器通过订阅住服务起的binlog来实现数据同步的,把binlog写到relay-log(中继日志中),就是从服务器在执行一遍ddl或者dml
	如果突然挂掉:可以采用一下方法 (必须在主备两端都同时启用)
	semi-synchronous replication(半同步分片)在每次写完master数据后,等待至少一个订阅了master的slave确认收到了该事件并将其写入relay-log之后,才会返回。
	

一个电商系统,有id,商品名称字段,问你架构怎么设计,会涉及到模糊查询商品。

	

双写过程会有分布事务问题,如何解决。如果采用最终一致性的思想,那么并发请求来了好几个发现数据不一致怎么办?

	

订单号不能重复,你怎么设计生成订单号?

雪花算法:
	第一个部分,是 1 个 bit:0,这个是无意义的。
	第二个部分是 41 个 bit:表示的是时间戳。
	第三个部分是 5 个 bit:表示的是机房 id,10001。
	第四个部分是 5 个 bit:表示的是机器 id,11001。
	第五个部分是 12 个 bit:表示的序号,就是某个机房某台机器上这一毫秒内同时生成的 id 的序号,0000 00000000。

一个排序数组,可能有重复元素,要求返回不重复元素个数,并且数组前几位去重。例如1,2,2,3,3,4 --》要求前四位是1,2,3,4后面无所谓,返回4.

	

一个台阶每次最多能走一个,或走两个,问有多少中走法。

	public static long getStepNumber(int n)  {
        if (n <= 2) {
            return n;
        }
        return getStepNumber(n - 1) + getStepNumber(n - 2);
    }

52张扑克牌,去掉大小王,问我三次摸到同一花色的概率。

	第1次抽到某一花色的概率为13/52
	第2次再抽到该花色的概率为12/51
	第3次再抽到该花色的概率为11/50
	第4次再抽到该花色的概率为10/49
	然后有4种花色
	13/52 × 12/51 × 11/50 × 10/49 × 4 = (13 * 12 * 11 * 10 * 4) / (52 * 51 * 50 * 49) = 68640/6497400 !==! 0;  

对于一个抢红包的需求,要求每个用户每分钟最多不能超过5次,问你怎么解决这个问题?

滑动窗口算法实现:
	如果是分布式:采用redis的zset实现 key,score(时间),value
	不是分布式:map<key,<map<time,value>>> map ;

三面

跳跃表的思想时怎样的?哪里有用到跳跃表?

==有序列表+关键节点加索引的结构++++ -==》 ++++比如每10个提取出来建立节点,读取的时候直接通过节点更快的定位到数据范围,然后在精细查找到。

redis,zset底层采用条约表。

服务容灾是如何做的?

解决方案就是冗余,多备份(主备,多数据中心,完全分布式部署),负载均衡,负载拦截

作为调用方和被调用放如何对避免服务雪崩?

雪崩是在同一时间大量的缓存失效:
服务端:
	缓存失效时间增加随机数,防止集中失效,对于热点数据,采用不失效处理;
	降级:超时降级
	隔离:限制调用分布式服务的资源使用
	熔断:当失败率(如因网络故障或超时 造成的失败率高)达到阈值自动触发降级,熔断器触发的快速失败会进行快速恢复;
客户度:
	服务雪崩后客户端能感知到怼就是服务变慢,服务不可用等,对于这类,客户端可以告警,可以采用休息间隔访问,循环请求等方式。

rpc接口的超时时间时如何设置得?

在服物段配置timeout时间,

工作中采用的微服务是如何部署的?

todo

平时出现问题是怎样排查的?

七层模型
物理层 数据链路层 网络层 传输层 表示层 应用层 会话层

jstat -gc pid 查询gc情况

快速排查问题:
首先top或者ps命令查询出占用资源较大的java进成,一般就是这个进程出了问题,拿到pid
使用命令 将线程执行状态下载下来, jstack pid -> dunm.txt
分析运行中的running状态的,定位代码,发现问题。

http和rpc的区别:

http本质上也是一个rpc,只是一种标准的应用层协议,但是慢,文本传输,需要序列化反序列化,浪费时间,
rpc能定制,可以建立在http协议的基础上,通过http协议进行网关搬运,然后在进行rpc调用。

rpc是远端过程调用,其调用协议通常包含传输协议和序列化协议。

传输协议包含: 如著名的 [gRPC](grpc / grpc.io) 使用的 http2 协议,也有如dubbo一类的自定义报文的tcp协议。

序列化协议包含: 如基于文本编码的 xml json,也有二进制编码的 protobuf hessian等。

只要是远程调用都可以叫RPC,和是不是通过http没什么关系。

rpc也有不通过http的,可以直接走socket

http是一种建立在tcp之上的应用曾协议。

RPC(即Remote Procedure Call,远程过程调用)和HTTP(HyperText Transfer Protocol,超文本传输协议)他们最本质的区别
,就是RPC主要工作在TCP协议之上,
而HTTP服务主要是工作在HTTP协议之上,我们都知道HTTP协议是在传输层协议TCP之上的,所以效率来看的话,RPC当然是要更胜一筹。