0
点赞
收藏
分享

微信扫一扫

38-面经整理

阿里+字节

说一下红黑树?

红黑树是一种自平衡的二叉查找树,除了BST的基本特性之外有以下特性:

  1. 节点是红色或者黑色,根节点是黑色,叶子节点是黑色的空节点
  2. 每个红色节点的两个子节点都是黑色(从每个叶子到根的所有路径不能有两个连续的红色节点)
  3. 从任一节点到每个叶子节点的所有路径都包含相同数目的黑色节点
  4. 为了保证以上特性红黑树可以进行变色和旋转来控制新增的节点

为什么要使用微服务?

解决了复杂性问题,把一个巨大的应用分成了一组服务,在功能没有改变的同时,应用程序被分解成立可管理的模块

利于开发,每个服务可以由每个团队独立开发,扩展和部署,服务如果挂了也不会影响到其他的服务

微服务之间的调用流程详细说一下?

方法消费方:在springBoot主类上开启@EnableFeignClient注解,使用@FeignClient注解放在在接口上,指明这是一个远程调用的接口,注解内容写上在注册中心注册的服务名称,方法上标明路径映射的全路径

Dubbo框架:容器启动提供者,提供者向注册中心注册自己,消费者订阅注册中心,注册中心通知消费者提供者的元信息,消费者拿着元信息直接对提供者的方法进行调用,消费者和提供者都被监控中心所监控,记录调用次数和调用时间

注册中心挂掉了会发生什么?

要看注册中心什么时候挂掉,最开始初始化的时候,消费者会将提供者的地址等信息拉取到本地缓存,所以注册中心挂了依然可以继续通信,但是如果还没有进行缓存就挂了,那就不能通信了

有哪些负载均衡的方式?

轮询策略:按照次序一个一个访问

随机策略:随机访问

最大可用策略:过滤掉故障的服务器,选择一个当前并发数最小的

加权轮询:可以对服务器性能的不同,进行加权处理,权数更多的服务器更容易被访问到

可用过滤:过滤出故障的服务器,以线性轮询的方式从过滤后的清单选择一个

微服务负载均衡发生在消费者还是提供者?为什么?

负载均衡根据发生位置不同分为服务端负载均衡和客户端负载均衡

  • 发生在服务端负载均衡的就是发生在提供者一方,比如nginx负载均衡,
  • 客户端负载均衡发生在消费者一方,在微服务调用中一般会选择客户端负载均衡,也就是在服务调用一方决定服务由哪个提供者执行

我的理解是消费者在提供者的上层,只有上层可以决定要往哪边走,就像二叉树根节点才能决定往左走还是往右走一样

线程有哪些状态,java怎么从运行状态切换到等待状态?wait和sleep的区别?

线程状态:

创建,就绪(Java中把就绪和运行统称为运行),运行,阻塞,等待,超时等待,终止

Thread.sleep:当前线程调用此方法,进入等待状态,不释放对象的锁,指定时间后苏醒进入就绪状态,作用是给其他线程执行机会的最佳方式

yield:当前线程调用此方法,由运行态变成就绪态,该线程有可能还会被再次选中,与sleep类似,但是不能指定暂停多长时间

t.join:当前线程里调用其他线程的join方法,使得当前线程进入等待状态,当前线程不会释放已经持有的对象锁,等到线程t执行完成之后,当前线程进入就绪状态

obj.wait:当前线程调用对象的wait方法,当前线程释放对象锁,进入等待队列,依靠notify/notifyall唤醒或者wait(time)时间后自动被唤醒

obj.notify:唤醒在此对象监视器上等待的单个线程,选择任意,notifyall是唤醒等待池中的所有线程,线程从等待池中出来,需要重新获取对象的锁,因此会进入阻塞状态

创建线程的方式?线程池的优点

  • 继承Thread类,重写run方法创建线程
  • 实现Runnable接口,重写run方法,然后把接口作为对象传入Thread构造器中,创建线程
  • Callable接口和Futrue创建线程,可以有返回值,实现Callable接口,重写call方法,将实现callable接口的对象丢到FutureTask的构造器中,Thread构造器中再丢入FutureTask对象,使用future对象的get方法获取返回值
  • 使用线程池,newFixedThreadPool,newCachedThreadPool一般都不用,在生产中自定义线程池使用ThreadPoolExecutor创建

线程是稀缺资源,使用线程池可以减少创建和销毁线程的次数,使得线程复用

根据系统的承受能力,可以调整线程池中工作的线程数量,防止因为消耗过多导致的服务器崩溃

项目中,缓存击穿如果是对于很多个无效id该如何处理?

布隆过滤器,他可以判断数据是否一定不存在,而无法判断数据是否一定存在

数据结构:位图,有序数组只有0和1两个值,0代表不存在,1代表存在

算法:需要知道某个元素在数组的哪个位置上,然后去看这个位置是0还是1,所以要是有hash函数,比如MD5就是常用的hash算法:解决哈希冲突:扩大数组长度,或者多经过几次hash计算

  • 从容器的角度来说:如果布隆过滤器判断元素在集合中,不一定存在,如果布隆过滤器判断不存在,就一定不存在
  • 从元素的角度说:如果元素实际存在,布隆过滤器一定判断存在,如果元素实际不存在,布隆过滤器可能判断存在

十亿个手机号查找一个手机号是否存在?

存储结构:可以使用字典树(也叫前缀树);

商品如何上架到ES中,说一下ES倒排索引的原理

  • 给ES建立一个商品的索引,需要在es中,先建立商品的保存模型,其中spuid,skusprice,brandName这些设置为keyword表示参与检索但是不分词,商品的描述skuTitle等设置为text参与分词
  • 在ES中保存商品的spu信息,建立专门的vo进行数据传输
  • 每次保存最好是批量进行保存,使用bulkRequest添加每个IndexRequest请求
  • 在索引内构建保存的请求,使用FastJson对vo进行序列化操作,添加到索引的文档,构建完请求后,使用bulk批量保存请求,通过bulk的返回值判断是否保存成功

倒排索引:文档的内容被表示为一系列关键词的集合(会取出一些无用的词比如的),在查询的时候,通过关键词出现的时候对应的文档id,返回文档内容

购物车为什么要放在Redis中

在对购物车访问量比较大的时候,高速的读写数据库会对数据库产生巨大的压力;

临时用户的数据不应该被记录在数据库中

具体逻辑:将临时购物车的信息放在redis中,使用redis生成一个唯一的key,保存在Cookie中,每次添加商品带上这个Cookie,这样就可以保证每次加入的都是同一个购物车,业务中具体的用户信息可以使用ThreadLocal来存储

说一下Redis的一致性Hash

一致性hash算法主要应用于分布式存储系统中,可以有效地解决分布式存储结构下普通余数Hash算法带来的伸缩性差的问题,可以保证在动态增加和删除节点的情况下尽量有多的请求命中原来的机器节点

JDK1.8新特性

lambda表达式

接口添加了默认方法(可以有实现的方法,且不需要实现类去现)

stream(filter,foreach,collect,peek,map,sort)

Optional类:可以为null的容器对象

时间API:LocalDateTime,LocalDate,LocalTime

ConcurrentHashMap获得size的过程?

1.7以前连续做两遍统计,如果两次统计的结果一样就直接返回,如果不一致就全部segment加锁来获取size

1.8以后:有两个重要遍历一个是Countercell对象,一个是volatile修饰的baseCount遍历,在put和remove操作的时候会同步更新baseCount变量,在并发情况对baseCount进行修改的时候,有的线程可能会修改失败,那么就创建这个CounterCell数组对象并且将1这个值插入到数组里,当数组不为null的时候,开始遍历数组,累加操作,得到size

数据库的三大范式?

列不可分(确保列的原子性),属性完全依赖于主键(每行数据只和其中一列相关),每个属性都与主键有唯一关系而不是间接关系

无限创建空线程的影响?

会量的占用cpu资源,大量的线程会被闲置,空闲的线程占用许多内存,给垃圾回收器带来压力(有可能会引发outofmemory异常),且大量线程在竞争cpu资源会产生其他的性能开销

线程池怎么设置的?

这个核心数是模拟出来的,真正的核心数应该是这个值除以2

public static void main(String[] args) {
        System.out.println("cpu核心数:"+Runtime.getRuntime().availableProcessors());//12
    }

最大线程数:性能最高线程数

阻塞队列大小设置:10000,预估最大流量从而设置

核心线程数:cpu密集型:cpu核心数/1-阻塞系数,IO密集型(2*CPU核心数)

 nginx的负载均衡策略

随机

轮询:注意访问

加权轮询:访问率和wieght相关

ip_hash:按访问ip的哈希结果分配,可以使得每个访客固定访问一个后端服务器,解决session的问题

最少连接:活动连接最少的请求发送到服务器,再次考虑服务器权重

一致性hash:根据用户定义的hash键值,请求在所有上游服务器平均分配,如果有服务器被添加或者移除,只有少数几个键会被重新映射,从而尽最大可能减少缓存未命中的情况

最短时间:选择具有最低平常延迟和最低活动连接数的服务器

HTTP和HTTPS的区别?

后者需要申请ca证书,并且有一定费用

http是超文本协议,明文传输,https是具有安全性的ssl加密传输协议

两者使用不同的连接方式,用的端口也不一样,前者为80,后者为443

http的连接是无状态的,https的协议是由SSL+HTTP协议构建的可进行加密传输,身份认证的网络协议,比http安全

Http2.0对于1.1的改进

  • 新的二进制格式:与之前基于文本的解析不同
  • 多路复用:每个request都是用作连接共享机制的,一个连接上可以有多个request
  • header压缩,头部压缩,减小了传输大小
  • 服务端推送(server push)同SPDY一样,HTTP2.0也具有server push功能

docker和虚拟机的区别

docker可以很方便的管理和创建镜像,或者说正在运行的容器

  • docker可以做到秒级启动,虚拟机通常要几分钟去启动
  • docker需要的资源更少,更加轻量级,但是相比于虚拟机docker隔离性更弱
  • docker具有高可用和高恢复性,快速删除,创建都是分钟级别的

Java中synchronized锁升级的过程,是否可逆?

  • 偏向锁->偏向于第一个访问锁的线程,如果接下里没有其他线程访问,则持有偏向锁的线程将永远不需要触发同步
  • 自旋锁(轻量级锁)->:线程持有锁时间不长的时候,不使线程进入阻塞状态,让他自旋等待锁的释放
  • 重量级锁

锁的转换过程不可逆,无法降级

HashMap多线程操作下的问题?

并发情况下的rehash操作可能会带来循环链表,导致死循环使得线程挂掉

URL输入到服务端处理的全过程?

输入网址->DNS解析->建立TCP连接->浏览器向服务器发送HTTP请求->服务端处理请求并且响应->浏览器展示HTML->浏览器发送请求获取其他HTML的资源

MySQL主从复制原理?

是一个异步复制的过程,主库发送更新事件到从库,从库读取更新记录,并且执行更新记录

binlog:binary log,主库中保存所有更新事件日志的二进制文件,在主库中只要有更新事件出现,就会被依次的写入到binlog中

binlog输出线程:每当从库连接到主库的时候,主库都会创建一个线程发送binlog内容到从库

在从库中,复制开始的时候,从库就会创建I/O线程和从库的SQL线程进行复制处理

redolog和binlog区别和联系

redo log 是 存储引擎层(innodb)生成的日志,主要为了保证数据的可靠性,是Innodb独有的

bin log 是 MySQL server层面上生成的日志,主要用于 point in time 恢复和主从复制

数据库宕机后以哪个log为标准?

binlog是逻辑日志没有保存脏页数据,对于操作成功,但是缓存数据还没有刷新到硬盘上的情况,需要使用redolog重做,大情况还是以binlog为准

举报

相关推荐

0 条评论