Java开发框架和中间件面试题(10)

目录

104.怎么保证缓存和数据库数据的一致性?

105.什么是缓存穿透,什么是缓存雪崩?怎么解决?

106.如何对数据库进行优化?

107.使用索引时有哪些原则?

108.存储过程如何进行优化?

109.说说如何对Tomcat进行优化?

110.BIO、NIO和AIO的区别?

111.Netty的特点?

112.Netty的线程模型?

113.如何进行JVM性能调优?

115.GC调优策略有哪些?

116.介绍下单点登录?

117.RabbitMQ的使用场景有哪些?

118.RabbitMQ有哪些重要的角色?有哪些重要的组件?

119.RabbitMQ中vhost的作用是什么?

120.介绍下RabbitMQ的架构?

121.RabbitMQ中的交换机类型有哪些?

122.除了ReetrantLock,你还接触过JUC并发包中的哪些并发API?

123.你了解哪些负载均衡算法、策略?

124.如何设计符合幂等性的高质量Restful   API ?

125.如何理解Restful API 的幂等性?

126.jsp和servlet有什么区别?

127.forward和redirect的区别?

128.jsp有哪几个作用域?

129.session和cookie有什么区别?

130.如果客户端禁止cookie能实现session还能用吗?


104.怎么保证缓存和数据库数据的一致性?

1.淘汰缓存在;如果是较为复杂的数据时,进行缓存的更新操作就会变得异常复杂,因此一般推荐选择淘汰缓存,而不是更新缓存。

2.选择先淘汰缓存,再更新数据库,加入先更新数据库在淘汰缓存,如果淘汰缓存失败,那么后面的请求就会得到脏数据,直至缓存过期。加入先淘汰缓存再更新数据库,如果更新数据库失败,只会产生一次缓存穿透,相比较而言,后者对业务则没有本质上的影响。

3.延时双删除策略,如下场景:同时有一个请求A进行更新操作,另一个请求B进行查询操作。我们按照如下步骤执行:

  (1)请求A进行写操作,删除缓存

    (2)请求B查询发现缓存不存在

  (3)请求B去数据库查询得到旧值

  (4)请求B将旧值写入缓存

  (5)请求A将新值写入数据库,次数便出现了数据不一致问题,此时我们可以采用延时双删策略的已解决。

     

public  void  write(String key,Object data){redisUtils.del(key);db.update(data);Thread.Sleep(100);redisUtils.del(key);
}

这么做,可以将1秒内所造成的缓存脏数据,再次删除。这个时间设定可以根据业务场景进行一个调节。

4.数据库读写分离的场景

假如有如下场景:两个请求,一个请求A进行更新操作,另一个请求B进行查询操作。我们按照如下步骤执行:

1.请求A进行写操作,删除缓存

2.请求A将数据写入数据库了

3.请求B查询缓存发现,缓存没有值

4.请求B去从库查询,这时,还没有完成主从同步,因此查询到的是旧值。

5.请求B将旧值写入缓存

6.数据库完成主从同步,从库变为新值,依旧采用延时双删策略解决此问题。

105.什么是缓存穿透,什么是缓存雪崩?怎么解决?

1.缓存穿透:一般的缓存系统,都是按照key去缓存查询,如果不存在对用的value,就应该去后端系统去查找(比如DB数据库)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

2.怎么解决?

对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert之后清理缓存。对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的bitmap中,查询时通过该bitmap过滤。

3.缓存雪崩:当缓存服务器重启或者大量缓存集中在某一时间段失效,这样在失效的时候,会给后端系统带来大量的压力,导致系统崩溃。

4.如何解决?在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待;做二级缓存;不同的key,设置不同的过期时间,让缓存失效的时间尽量均匀。

106.如何对数据库进行优化?

1.选取适合的字段属性

  为了获取更好的性能,可以将表中字段的宽度设的尽可能小。

  尽量把字段设置成not null

  执行查询的时候,数据库不用去比较null值

  对某些省份或者性别字段,将他们定义为enum类型

  enum类型被当做数值型数据来处理,而数值型数据被处理起来的速度要比文本类型快很多。

2.使用join链接代替子查询

3.使用联合union来代替手动创建的临时表union用法中,两个select语句的字段类型要匹配,而且字段个数要相同。

5.锁定表:尽管事务时维护数据库完整性的一个非常好的方法,但却因为他的独占性,有时候会影响数据库的性能,尤其是在大应用中。由于在事务执行的过程中,数据库会被锁定,因此其他用户只能暂时等待直到数据库结束。有的时候可以用锁定表的方法获得更好的性能。

共享锁:

    其他用户只能看,不能修改lock table person in share mode;对于通过lock table命令主动添加的锁来说,如果要释放他们,只需发出rollback命令即可。

6.使用外键:锁定表的方法可以维护数据的完整性,但是他却不能保证数据的关联性,这个时候可以使用外键。

7.使用索引:索引时提高数据库查询速度的常用方法,尤其是查询语句中包含max(),min(),order by这些命令的时候,性能提高更为显著。一般来说索引应该建在常用于join,where,order by的字段上。尽量不要对数据库中含有大量重复的值得字段建立索引。

8.优化的查询语句:在索引的字段上尽量不要使用函数进行操作。尽量不要使用like关键字和通配符,这样做法很简单,但却是以牺牲性能为代价的。避免在查询中进行自动类型转换,因为类型转换也会使索引失效。

107.使用索引时有哪些原则?

 常见的索引原则有:

   1.选择唯一性索引

唯一性索引的值是唯一的,可以更快速的通过该索引来确定某条记录。

2.为经常需要排序,分组和联合操作的字段建立索引;

3.为常作为查询条件的字段建立索引。

4.限制索引的数据:越多的索引,会使更新表变得很浪费时间。

5.尽量使用数据量少的索引。

6.如果索引的值很长,那么查询的速度会受到影响。

7.尽量使用前缀来索引。

8.如果索引字段的值很长,最好使用值的前缀来索引。

9.删除不再使用或者很少使用的索引。

10.最左前缀匹配原则,非常重要的原则。

11.尽量选择区分度高的列作为索引。

12.索引列不能参与计算,保持列干净:但函数的查询不参与索引。

13.尽量的扩展索引,不要新建索引。

108.存储过程如何进行优化?

存储过程是一组为了完成特定功能的SQL语句集,存储在数据库中,经过一次编译后再次调用不需要再次编译,用户通过指定存储过程的名字并给出参数(如果该存储过程带有参数)来执行他。存储过程是数据库中的一个重要对象。

存储过程优化思路:

1.尽量利用一些SQL语句来替代一些小循环,例如聚合函数,求平均函数等。

2.中间结果存放于临时表,加索引。

3.少使用游标。SQL是个集合语言,对于集合运算具有较高性能。而cursors是过程运算。比如一个100万行的数据进行查询。游标需要读取100万次,而不使用游标只需要少量几次读取。

4.事务越短越好。SqlServer支持并发操作。如果事务过多过长,或者隔离级别过高,都会造成并发操作的阻塞,死锁。导致查询极慢,CPU占用率极低。

5.使用try  catch处理错误异常

6.查找语句尽量不要放在循环内。

109.说说如何对Tomcat进行优化?

Tomcat作为Web服务器,他的处理性能直接关系到用户体验,下面是几种常见的优化措施。

1.去掉对web.xml的监视,把jsp提前编辑成Servlet。有抚育物理内存的情况,加大Tomcat使用的JVM的内存。

2.服务器资源

服务器所能提供CPU,内存,硬盘的性能对处理能力有决定性影响。

2.1对于高并发情况下会有大量的运算,那么CPU的速度会直接影响到处理速度。


2.3硬盘主要问题就是读写性能,当大量文件进行读写时,硬盘极容易称为性能瓶颈。最好的办法还是利用下面提到的缓存。

3.利用缓存和压缩

    对于静态页面最好是能够缓存起来,这样就不必每次从磁盘上读。这里我们采用了Nginx作为缓存服务器,将图片,css,js文件都进行了缓存,有效的减少了后端Tomcat的访问。

     另外,为了能加快网络传输速度,开启gzip压缩也是必不可少的。但考虑带Tomcat已经需要处理很多东西了,所以把这个压缩的工作就交给前端的Nginx来完成。

     除了文本可以用gzip压缩,其实很多图片也可以用图像处理工具预先进项压缩,找到一个平衡点可以让画质损失很小而文件可以减小很多。曾静我就见过一个图片从300多kb压缩到几十kb,自己几乎看不出来区别。

4.采用集群

单个服务器性能总是有限的,最好的办法自然是实现横向扩展,那么组建Tomcat集群是有效提升性能的手段。我们还是采用了Nginx来作为请求分流的服务器,后端多个Tomcat共享session来协同工作。

5.优化Tomcat参数

这里以Tomcat7的参数配置为例,需要修改conf/server.xml文件,主要是优化连接配置,关闭客户端dnd查询。

110.BIO、NIO和AIO的区别?

1.基本概念

   BIO:一个连接一个线程,客户端有连接请求时服务器端就需要启动一个线程进行处理。线程开销大。

   伪异步IO:将请求连接放入线程池,一对多,但线程还是很宝贵的资源。

   NIO:一个请求一个线程,但客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求时才启动一个线程处理。

   AIO:一个有效请求一个线程,客户端的I/O请求都是由OS先完成了再通知服务器应用去启动线程进行处理。

2.常规区别

   BIO是面向流的,NIO是面向缓冲区的;

BIO的各种流是阻塞的。

而NIO是非阻塞的。

BIO的Stream是单向的,而NIO的channel是双向的。NIO特点:事件驱动模型,单线程处理多任务,非阻塞I/O,I/O读写不再阻塞,而是返回0,基于block的传输比基于流的传输更高效,更高级的IO函数zero  copy,IO多路复用大大提高了Java网络应用的可伸缩性和实用性。

基于Reactor线程模型。在Reactor模式中,事件分发器等待某个事件或者可应用或者某个操作的状态发生,时间分发器就把这个事件事先注册的事件处理函数或者回调函数,由后者来做实际的读写操作。

如在Reactor中实现读:注册读就绪事件和相应的事件处理器,事件分发器等待事件,事件到来,激活分发器,分发器调用事件对应的处理器,事件处理器完成实际的读操作,处理读到的数据,注册新的事件,然后返还控制权。

111.Netty的特点?

  一个高性能,异步事件驱动的NIO框架,他提供了对TCP,UDP和文件传输的支持使用更高效的socket底层,对epoll空轮询引起的CPU占用飙升在内部进行了处理,避免了直接使用NIO的陷阱,简化了NIO的处理方式。

采用多种decoder/encoder支持,对TCP粘包/分包进行自动化处理,可使用接受/处理线程池,提高连接效率,对重连,心跳检测的简单支持。

可以配置IO线程数,TCP参数,TCP接收和发送缓冲区使用直接内存代替堆内存,通过内存池的方式循环利用ByteBuf通过引用计数器及时申请释放不再引用对象,降低了GC频率使用单线程串行化的方式,高效的Reactor线程模型大量使用了volitale,使用了CAS和原子类,线程安全类的使用,读写锁的使用。

112.Netty的线程模型?

    Netty通过Reacor模型基于多路复用器接收并处理用户请求,内部实现了了两个线程池,boss线程池和work线程池。其中boss线程池的线程负责处理请求的accept,当接收到accept事件的请求时,把对应的socket封装到一个NIOSocketChannel中,并交给work线程池,其中work线程池负责请求的read和write事件,由对应的Handler处理。

  单线程模型:所有I/O操作都有一个线程完成,即多路复用,事件分发和处理都是在一个Reactor线程上完成的。既要接受客户端的连接请求,向服务器端发起连接,又要发送/读取请求或者应答/响应消息。

一个NIO线程同时处理成百上千的链路,性能上无法支撑,速度慢,若线程进入死循环,整个程序不可用,对于高负载,大并发的应用场景不合适。

多线程模型:有一个NIO线程(Acceptor只负责监听服务器,接受客户端的TCP连接请求,NIO线程池负责网络IO的操作,即消息的读取,解码,编码和发送。

1个NIO线程可以同时处理N条链路,但是一个链路只对应1个NIO线程,这是为了防止发生并发操作问题。但在并发百万客户端连接或者需要安全认证时,一个Acceptor线程可能会存在性能不足问题。

主从多线程模型:Acceptor线程用于绑定监听端口,接收客户端连接,将SocketChannel从主线程池的Reactor线程的多路复用器上移除,用于处理I/O的读写等操作,从而保证mainReactor只负责接入认证,握手等操作。

113.如何进行JVM性能调优?

1.监控GC的状态,使用各种JVM工具,查看当前日志,分析当前JVM参数设置,并且分析当前堆内存快照和gc日志,根据实际的各区域内存划分GC执行时间,觉得是否进行优化。

举一个例子:系统崩溃前的一些现象:

  每次垃圾回收的时间越来越长,由之前的10ms延长到50ms左右,FullGC的时间也有之前的0.5s延长到4,5s

  FullGC的次数越来越多,最频繁时隔不到1分钟就进行一次FullGC

  年老代的内存越来越大并且每次FullGC后年老代没有内存被释放之后系统就会无法响应新的请求,逐渐到达OutOfMemoryError的临界值,这个时候就需要分析JVM内存快照dump。

2.生成堆的dump文件。

通过JMX的MBean生成当前的Heap信息,大小为一个3G(整个堆的大小)的hprof文件,如果没有启动JMX可以通过Java的jmap命令来生成该文件。

3.分析dump文件打开这个3g的堆信息文件,显然一般的Window系统没有那么大内存,必须借助高配置的Linux,几种工具打开该文件:

  Visual VM   

   IBM  HeapAnalyzer

   JDK自带的Hprof工具

   Mat(Eclipse专门的静态内存分析工具)推荐使用

备注:文件太大,建议使用Eclipse专门的静态内存分析工具Mat打开分析。

4.分析结果,判断是需要优化,如果各项参数设置合理,系统没有超时日志出现,GC频率不高,GC耗时不高,那么没有必要进行GC优化,如果GC事件超过1到3秒,或者频繁GC,则必须优化。

注:如果满足下面的指标,则一般不需要进行GC:

  Minor  GC执行时间不到50毫秒;

  Minor  GC执行不频繁,约10秒一次;

  FullGC执行时间不到1秒;

  FullGC执行频率不算频繁,不低于10分钟一次;

5.调整GC类型和内存分配,如果内存分配过大或者过下,或者采用的GC收集器比较慢,则应该优先调整这些参数,并且先找一台或者几台机器进行beat,然后比较优化过的机器和没有优化的机器性能对比,并有针对性的做出最后选择。

6.不读拿的分析和调整,通过不断地试验和试错,分析并找到最合适的参数,如果找到了最合适的参数,则将这些参数应用到所有的服务器。

114.JVM调优参数有哪些?

115.GC调优策略有哪些?

116.介绍下单点登录?

117.RabbitMQ的使用场景有哪些?

1.解决一步问题,例如用户注册,发送邮件和短信反馈注册成功,可以使用RabbitMQ消息队列,用户无需等待反馈。

2.服务间解耦,订单系统和库存系统,中间加入RabbitMQ消息队列,当库存系统出现问题时,订单系统依旧能正常使用,降低服务间耦合度。

3.秒杀系统,利用RabbitMQ的最大值,实现秒杀系统。

118.RabbitMQ有哪些重要的角色?有哪些重要的组件?

1.RabbitMQ有哪些重要角色?客户端,RabbitMQ服务端。

2.有哪些重要组件?

 2.1connectionFactory(连接管理器)应用程序与RabbitMQ之间建立连接的管理器。

 2.2Channel(信道)消息推送使用的信道。

 2.3RoutingKey(路由键)用于把生产者的数据分配到交换机上。

 2.4Exchange(绑定键)用于把交换机的消息绑定到队列上

 2.6Queue(队列)用于存储生产者消息。

119.RabbitMQ中vhost的作用是什么?

   vhost可以理解为mini版的RabbitMQ,其内容均含有独立的交换机,绑定,队列,最重要的是拥有独立的权限系统,可以做到vhost范围内的用户控制。

用RabbitMQ全局考虑,不同的应用可以跑在不同的vhost上,作为不同权限隔离的手段。

120.介绍下RabbitMQ的架构?

121.RabbitMQ中的交换机类型有哪些?

122.除了ReetrantLock,你还接触过JUC并发包中的哪些并发API?

123.你了解哪些负载均衡算法、策略?

124.如何设计符合幂等性的高质量Restful   API ?

125.如何理解Restful API 的幂等性?

126.jsp和servlet有什么区别?

127.forward和redirect的区别?

128.jsp有哪几个作用域?

129.session和cookie有什么区别?

130.如果客户端禁止cookie能实现session还能用吗?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/311354.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

HTML使用JavaScript的三种方式

要使用 JavaScript&#xff0c;你可以在 HTML 文件中的 <script> 标签中编写代码&#xff0c;或者将代码保存到一个单独的 .js 文件中并在 HTML 文件中引入。以下是一些常用的 JavaScript 使用方式&#xff1a; 内联 JavaScript&#xff1a;在 HTML 文件的 <script&g…

Hive实战:统计总分与平均分

文章目录 一、实战概述二、提出任务三、完成任务&#xff08;一&#xff09;准备数据文件1、在虚拟机上创建文本文件2、将文本文件上传到HDFS指定目录 &#xff08;二&#xff09;实现步骤1、启动Hive Metastore服务2、启动Hive客户端3、创建Hive表&#xff0c;加载HDFS数据文件…

劫持最新版 QQNT / QQ / TIM 客户端 ClientKeys

针对 TX官网 最新发布的 QQNT 9.9.6 与 QQ 9.7.21 新版本客户端全面更新截取代码 大伙应该都知道自从 QQ 9.7.20 版本起就已经不能通过模拟网页快捷登录来截取 Uin 跟 Clientkey 数据&#xff0c;而此次 TX官网 最新发布的 QQNT 9.9.6 与 QQ 9.7.21 可谓是采用了全新的技术、全…

Python列表的介绍与操作 增改查,连接,赋值,复制,清空

列表 在日常中我们通过给变量赋值来存储数据,比如 a "hello" b "world" c "你好啊" d "....."由于变量一次只能存储一个数据,但我们如果想一次存储多个数据,的话这样存储会很复杂,所以,我们可以通过列表 列表(List)是Python中的…

详解Vue3中的鼠标事件click和dblclick

本文主要介绍Vue3中的常见鼠标事件。 目录 一、click——单击事件二、dblclick——双击事件三、在使用click和dbclick需要注意的地方 下面是Vue 3中常用的鼠标事件&#xff1a; 一、click——单击事件 click事件是一种常见的事件类型&#xff0c;用于在用户点击某个元素时触发…

单片机原理及应用:数码管的动态扫描显示、余晖效应与消影

动态显示 动态显示是一种一位一位地轮流点亮各位数码管的显示方式。 当数码管显示位数较多时&#xff0c;静态显示所占的I/O口多 &#xff0c;这时常采用动态显示。为节省I/O口&#xff0c;通常将所有显示器段码线相应段并联在一起&#xff0c;由一个8位I/O口控制&#xff0c;…

45、激活函数 - 为什么非线性这么重要

这一节开始讲一讲神经网络中的激活函数,在讲激活函数之前,先讲一下非线性。 看一个基础知识:线性函数的叠加,我们初中学过的知识点。 假设有一个线性函数,y = kx + b, 这个函数画出来是下面的样子,这里显示 y 和 x 是线性关系。 而如果这个时候又有一个线性关系 z = hy…

C#-CSC编译环境搭建

一.Microsoft .NET Framework 确保系统中安装Microsoft .NET Framework相关版本下载 .NET Framework 4.7 | 免费官方下载 (microsoft.com)https://dotnet.microsoft.com/zh-cn/download/dotnet-framework/net47 二.编译环境搭建 已经集成编译工具csc.exe,归档至gitcode,实现us…

trino-435: 理论基础

一、trino介绍 Trino是⼀种⽀持使⽤ SQL 访问任意数据源的 开源的分布式SQL 查询引擎&#xff0c;其能够提供更加灵活与⾼效的查询服务。为不同的异构数据源提供统⼀的sql访问&#xff0c;并⽀持联邦查询和并⾏查询。 应⽤场景 Trino是定位在数据仓库和数据分析业务的分布式S…

20231228在Firefly的AIO-3399J开发板的Android11的Firefly的AIO-3399J开发板的DTS配置单前置摄像头ov13850

20231228在Firefly的AIO-3399J开发板的Android11的Firefly的AIO-3399J开发板的DTS配置单前置摄像头ov13850 2023/12/28 12:30 开发板&#xff1a;Firefly的AIO-3399J【RK3399】 SDK&#xff1a;rk3399-android-11-r20211216.tar.xz【Android11】 Android11.0.tar.bz2.aa【ToyBr…

从0到1入门C++编程——01 C++基础知识

文章目录 一、工具安装二、新建项目三、设置字体、注释、行号四、C基础知识1.数据类型2.输入输出3.运算符4.选择、循环结构5.跳转语句6.数组7.函数8.指针9.结构体 一、工具安装 学习C使用到的工具是Visual Studio&#xff0c;Visual Studio 2010旗舰版下载链接&#xff1a;点此…

【实用工具】Gradio快速部署深度学习应用1:图像分类

前言 在AI快速发展的今天&#xff0c;我们作为算法开发人员&#xff0c;也应该有一些趁手的工具帮助我们快速开发并验证自己的想法&#xff0c;Gradio可以实现快速搭建和共享的功能&#xff0c;能够展示出一个前端界面&#xff0c;把我们的算法包裹起来&#xff0c;快速验证算…