Java面试题整理_P2

本文整理了Java分布式面试中的重点问题,包括SpringBoot的核心注解、配置文件解析、集成Mybatis,以及SpringBoot、Spring、SpringMVC的区别。还涉及Maven、Linux、JDK1.8、Dubbo、Redis、数据库连接池和数据一致性等知识点,旨在帮助开发者全面了解Java后端开发的关键技能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Java分布式模拟面试题库-V1.0

1、SpringBoot核心注解?(其中有包含哪些注解分别有什么作用?)

核心启动类上面的注解是@SpringBootApplication,它也是 Spring Boot 的核心注解,主要组合包含了以下 3 个注解:

@SpringBootConfiguration:组合了 @Configuration 注解,实现配置文件的功能。

@EnableAutoConfiguration:打开自动配置的功能,也可以关闭某个自动配置的选项,如关闭数据源自动配置功能: @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class })。

@ComponentScan:Spring组件扫描。

整理其它注解:

@Controller:用于定义控制器类,在spring项目中由控制器负责将用户发来的URL请求转发到对应的服务接口(service层),一般这个注解在类中,通常方法需要配合注解@RequestMapping。

@RestController:用于标注控制层组件(如struts中的action),@ResponseBody和@Controller的合集。

@ResponseBody:获取json数据,加上@Responsebody后,会直接返回json数据。该注解一般会配合@RequestMapping一起使用。注意要添加Jackson或者Gson的依赖。

@RequestMapping:提供路由信息,负责URL到Controller中的具体函数的映射。

@Configuration:相当于传统的xml配置文件,如果有些第三方库需要用到xml文件,建议仍然通过@Configuration类作为项目的配置主类——可以使用@ImportResource注解加载xml配置文件。

@Import:用来导入其他配置类。

@ImportResource:用来加载xml配置文件。

@Autowired:自动导入依赖的bean

@Service:一般用于修饰service层的组件

@Repository:使用@Repository注解可以确保DAO或者repositories提供异常转译,这个注解修饰的DAO或者repositories类会被ComponetScan发现并配置,同时也不需要为它们提供XML配置项。

@Component:普通组件,当组件不好归类的时候,我们可以使用这个注解进行标注。

@Bean:用@Bean标注方法等价于XML中配置的bean。放在方法的上面,而不是类,意思是产生一个bean,并交给spring管理,bean的id就是方法名。

@Value:注入application.properties配置的属性的值。

@Inject:等价于默认的@Autowired,只是没有required属性;

@AutoWired:自动导入依赖的bean。byType方式。把配置好的Bean拿来用,完成属性、方法的组装,它可以对类成员变量、方法及构造函数进行标注,完成自动装配的工作。当加上(required=false)时,就算找不到bean也不报错。

@Qualifier:当有多个同一类型的Bean时,可以用@Qualifier(“name”)来指定。与@Autowired配合使用。@Qualifier限定描述符除了能根据名字进行注入,但能进行更细粒度的控制如何选择候选者

@Resource没有括号内内容的话,默认byName。与@Autowired干类似的事。

等等。。。。

2、SpringBoot核心配置文件有几种格式,优先级是?

配置文件格式和同目录下优先级

SpringBoot使用一个以application命名的配置文件作为默认的全局配置文件。支持properties后缀结尾的配置文件或者以yml/yaml后缀结尾的YAML的文件配置。
properties配置优先级 > yml配置优先级
注意@PropertySource注解不支持加载yaml文件,支持properties文件。

配置文件目录

SpringBoot配置文件可以放置在多种路径下,不同路径下的配置优先级有所不同。
可放置目录(优先级从高到低)

file:./config/ (当前项目路径config目录下);
file:./ (当前项目路径下);
classpath:/config/ (类路径config目录下);
classpath:/ (类路径config下).
优先级由高到底,高优先级的配置会覆盖低优先级的配置;
SpringBoot会从这四个位置全部加载配置文件并互补配置;

3、SpringBoot配置文件application.properties,你都配置过哪些内容?

server.port=xxx
可以指定springboot内嵌容器启动的端口,默认使用tomcat容器时在8080端口

spring.profiles.active=xxxx
可以指明要使用的配置文件,一般应用于多环境配置分离,如生产环境(production),开发环境(development),测试环境(test)等,可以自定义,如开发环境配置文件为application-dev.properties,则spring.profiles.active=dev,在启动时会加载application-dev.properties配置文件。

集成Mybatis(引入maven:mybatis-spring-boot-starter )
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/edocdb
spring.datasource.username=root
spring.datasource.password=xxxx
spring数据源的配置,使用jdbcTemplate进行数据库操作(使用jdbcTempate,会自动提示导入spring-boot-starter-jdbc等依赖)\
适用xml映射文件配置
mybatis.config-location=classpath:mybatis/mybatis-config.xml
mybatis.mapper-locaitons=classpath:mybatis/mappings/*.xml

# mybatis
mybatis.configuration.map-underscore-to-camel-case=true

Redis配置(引入spring-boot-starter-data-redis自动集成)
#spring.redis.url=
#上面url形式等同下面
spring.redis.host=localhost
spring.redis.port=6379

Dubbo配置
# 提供服务名称
dubbo.application.name=xxx-provider
# 注册中心地址
dubbo.registry.address=127.0.0.1:2181
# 注册中心协议
dubbo.registry.protocol=zookeeper
# 通信端口,可以单独指定接口,一般都是20880,如果设置为-1,代表自动查找接口,从20880开始,依次递增
dubbo.protocol.port=-1
# 指定扫描包路径
dubbo.scan.base-packages=com.kgc

文件上传配置

#默认true
#spring.http.mutipart.enabled=true
#上传中转文件位置,
#spring.http.multipart.location=
#最大上传文件大小,默认1MB
spring.http.multipart.max-file-size=5MB
#最大请求大小,默认10MB
spring.http.multipart.max-request-size=20MB

等等,自主增加

4、SpringBoot从配置文件中获取自定义值的常用方式?区别是?

有两种方式,@CofigurationProperties是批量获取的,@Value是单个获取的

二者对比:

@ConfigurationProperties@Value
功能批量注入配置文件中的属性一个个指定
松散绑定(松散语法)支持不支持
SpEL(#{11*2})不支持支持
JSR303数据校验支持不支持
复杂类型封装(map)支持不支持
松散绑定语法:比如有个属性是lastName的驼峰命名,可以支持last-name或者last_name进行绑定

JSR303数据校验,注释掉@value注解,然后放开@ConfigurationProperties,给person实体增加注解@Validated,然后给name属性增加注解@Email,代表校验实体输入值,必须name为邮箱的格式

复杂类型封装,给person实体的maps属性使用@Value获取配置文件中的值,启动单元测试,发现报错,说明这个不支持

结论:

配置文件yml还是properties他们都能获取到值;

如果说,我们只是在某个业务逻辑中需要获取一下配置文件中的某项值,使用@Value;

如果说,我们专门编写了一个javaBean来和配置文件进行映射,我们就直接使用@ConfigurationProperties;

5、SpringBoot 中的 Starter如何理解?

Starters可以理解为启动器,它包含了一系列可以集成到应用里面的依赖包,你可以一站式集成 Spring 及其他技术

6、SpringBoot默认日志框架?

Slf4j+Logback,Slf4j是日志的抽象层,Logback是日志的实现
扩展:log4j和logback都是同一个人写的,logback是对log4j升级版:

开始写出来log4j还不错,后来出现性能问题了,要对log4j进行升级了,就写了logback框架, 为了适应更多的日志实现框架,他就写了日志门面slf4j日志门面,

所以log4j、logback、slf4j都是出自同一个人之手

7、SpringBoot如何整合mybatis,如何快速生成mybatis代码?

pom.xml中增加依赖:
		<!--springboot整合mybatis-->
        <!-- mybatis begin -->
        <dependency>
            <groupId>org.mybatis.spring.boot</groupId>
            <artifactId>mybatis-spring-boot-starter</artifactId>
            <version>1.3.2</version>
        </dependency>
        <!-- mybatis end -->
        
        <!-- mysql driver begin -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
        </dependency>
        <!-- mysql driver end -->
        
自动生成代码有两种方式:

	第一种方式,直接使用ideaidea中mybatis自动生成代码插件(better-mybatis-generator)
		1、idea链接数据库:View > Tool Windows > Database,输入ip、端口、用户名密码链接成功
		2、选择某个表,右键点击,选择mybatis-generate
		3、在弹出的配置页面进行填写,点击ok


	第二种方式,手动添加generatorConfig.xml文件,然后在pom.xml中增加generator插件
	<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <!--mybatis自动生成代码插件-->
            <plugin>
                <groupId>org.mybatis.generator</groupId>
                <artifactId>mybatis-generator-maven-plugin</artifactId>
                <version>1.3.6</version>
                <configuration>
                    <verbose>true</verbose>
                    <!-- 是否覆盖,true表示会替换生成的JAVA文件,false则不覆盖 -->
                    <overwrite>true</overwrite>
                    <configurationFile>src/main/resources/generatorConfig.xml</configurationFile>
                </configuration>
                <dependencies>
                    <!--使用插件需要mysql驱动包,连接数据库-->
                    <dependency>
                        <groupId>mysql</groupId>
                        <artifactId>mysql-connector-java</artifactId>
                        <version>5.1.45</version>
                    </dependency>
                </dependencies>
            </plugin>
        </plugins>
        <!--上面的**resource**标签意思是将src/main/java/下的文件夹及其子文件夹的xml文件在编译时包含在最终工程中。**这个配置可以解决mybatis的将mapper接口和mapper.xml放在同一个文件夹下找不到mapper的问题**。即都打包到项目包中-->
        <resources>
            <resource>
                <directory>src/main/java</directory>
                <includes>
                    <include>**/*.xml</include>
                </includes>
            </resource>
            <!-- 如果配置了resource,默认的resources就失效了,所以必须再将resources也加载进来,否则会出问题,也可以指定包含文件 -->
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
    </build>
    

8、简单介绍下SpringBoot ,并说一下你觉得好的优点

简介:
1.Spring boot是Spring家族中的一个全新的框架,它用来简化Spring应用程序的创建和开发过程,也可以说Spring boot能简化我们之前采用Spring MVC+Spring+MyBatis(ssm)框架进行开发的过程;
2.在以往我们采用Spring Mvc+Spring+MyBatis框架进行开发的时候,搭建和整合三大框架需要做很多的工作,比如配置Web.xml,配置Spring,配置MyBatis,并将他们整合在一块,而Spring boot框架对此开发过程进行了革命性的颠覆,抛弃了繁琐的xml配置过程,采用大量的默认配置简化我们的开发过程;
3.所以采用Spring boot可以非常容易和快速的创建基于Spring框架的应用程序,它让编码变简单了,配置变简单了,部署变简单了,监控变简单了;
4.正因为Spring boot它化繁为简,让开发变得极其简单和快速。

优点:
1.能够快速创建基于Spring的应用程序;方便微服务的项目开发;
2.能够内嵌的Tomcat,Jetty服务器运行Spring boot程序,不需要部署war包文件;
3.提供约定的starter POM来简化Maven配置,让Maven的配置变得简单;
4.根据项目的Maven依赖配置,Spring boot自动配置Spring,Spring mvc等;
5.基本可以完全不使用XML配置文件,采用注解配置。

缺点:
优点也就是它的缺点,集成度较高,使用快速,简单,但是开发过程中不太容易了解底层。

9、Maven的install和package的区别

package是把jar打到本项目的target下,而install是把target下的jar安装到本地仓库,供其他项目使用

10、简单介绍你工作中使用的linux常用各种操作指令

1)查看进程:
ps -ef | grep java,或者ps aux | grep java

2)杀进程:
kill -9 进程号

3)查看系统状态 top、free、df

  top命令用于实时显示 process 的动态。可以配合用来查询vm的一些问题!具体参数不做介绍。

  # 表示更新两次后终止更新显示
  top -n 2
  #表示更新周期为3秒
  top -d 3
  # 显示进程号为2586的进程信息,CPU、内存占用率等
  top -p 2586
  更新显示二次的结果输入到名称为 top.log 的档案里
  top -n 2 -b < top.log
  
  free命令用于显示内存状态。

  # 显示内存使用信息 , -h 选项为根据大小适当显示(人类可以读懂的方式)
  free -h
  # 每10s 执行一次命令
  free -hs 10
  
  
  df 以磁盘分区为单位查看文件系统,可以获取硬盘被占用了多少空间,目前还剩下多少空间等信息。

  # 查看磁盘信息, -h 选项为根据大小适当显示
  df -hl

  du会显示指定的目录或文件所占用的磁盘空间。用于查看当前目录的总大小。

  # 通过排序的方式显示前十条
  [root@localhost ~]# du -am  | sort -nr | head -n 10

4)查找文件
find / -name filename.txt
根据名称查找/目录下的filename.txt文件。

5).查看文件,包含隐藏文件
ls -al

6)当前工作目录
pwd

7)复制文件包括其子文件到自定目录
cp -r sourceFolder targetFolder

8)创建目录
mkdir newfolder

9)删除文件夹包括其子文件
rm -rf deleteFile

10)移动文件
mv /temp/movefile /targetFolder
或者重命名 mv oldNameFile newNameFile

11)切换root用户
sudo su -

12)修改文件权限
chmod 777 file.java
文件权限-rwx rwx rwx,r表示读、w表示写、x表示可执行

13)压缩文件
tar -zcvf test.tar.gz /test

14)解压文件
tar -zxvf test.tar.gz

15)查看日志文件
tail -f exmaple.log 这个命令会自动刷新新增内容,f代表循环读取。

16)启动vi编辑器
vi命令,i或者a进入编辑模式,esc退出编辑,:wq!强制保存退出,shift+g进入文件末尾,dd删除行等等

17)查看系统当前时间
date
命令会输出 周几 几月 几日 时间 和 时间显示格式 和年份
Sat Jan 20 04:39:49 CST 2018
date +"%Y-%m-%d"
显示如下:
2021-02-28
如果不确定 就help 即可;

18)解压zip 文件
unzip -oq

19)查询端口号80 是否开启:
firewall-cmd --query-port=80/tcp

#开启端口
firewall-cmd --zone=public --add-port=2181/tcp --permanent

#查看防火墙的状态
systemctl status firewalld 或者 firewall-cmd —state

#重启防火墙:
firewall-cmd --reload

#查询有哪些端口是开启的:
firewall-cmd --list-port

#停止firewall
systemctl stop firewalld

#禁止firewall开机启动
systemctl disable firewalld

20)下载ftp 服务器上的文件或者文件夹:
wget -P 指定文件保存位置 ftp://ip:端口/文件夹 --ftp-user=用户名 --ftp-password=密码

21)SCP命令(文件拷贝,基于ssh的登录):
scp命令用于Linux服务器之间复制文件和目录。scp是 secure copy的缩写, scp是linux系统下基于ssh登陆进行安全的远程文件拷贝命令。
scp /opt/xxx.dmp root@ip:/home/oracle/dmpdir/
(本地/opt下的一个名为xxx.dmp的文件拷贝到远程服务器ip上的/home/oracle/dmpdir。而且远程服务器的帐号名为root,会提示你输入密码。)
scp root@]ip:/home/xxx.dmp
(把文件从远程机器拷贝到本机当前目录。)

22)
查看端口占用netstat命令
netstat命令用于显示网络状态。利用netstat指令可让你得知整个Linux系统的网络情况。
# 查看端口1212的使用情况
netstat -tln | grep 1212
查看端口属于哪个程序
lsof -i :1212

11、JDK1.8后都有哪些变化

jdk1.8新特性知识点:
主要有:
  Lambda表达式
  方法引用
  函数式接口
  Stream API
  接口中的默认方法和静态方法

另:
  在jdk1.8中对hashMap等map集合的数据结构优化。hashMap数据结构的优化 
  原来的hashMap采用的数据结构是哈希表(数组+链表),hashMap默认大小是16,一个0-15索引的数组,如何往里面存储元素,首先调用元素的hashcode 
  方法,计算出哈希码值,经过哈希算法算成数组的索引值,如果对应的索引处没有元素,直接存放,如果有对象在,那么比较它们的equals方法比较内容 
  如果内容一样,后一个value会将前一个value的值覆盖,如果不一样,在1.7的时候,后加的放在前面,形成一个链表,形成了碰撞,在某些情况下如果链表 
  无限下去,那么效率极低,碰撞是避免不了的 
  加载因子:0.75,数组扩容,达到总容量的75%,就进行扩容,但是无法避免碰撞的情况发生 
  在1.8之后,在数组+链表+红黑树来实现hashmap,当碰撞的元素个数大于8时 & 总容量大于64,会有红黑树的引入 
  除了添加之后,效率都比链表高,1.8之后链表新进元素加到末尾 
  ConcurrentHashMap (锁分段机制),concurrentLevel,jdk1.8采用CAS算法(无锁算法,不再使用锁分段),数组+链表中也引入了红黑树的使用

https://blog.youkuaiyun.com/qq_29411737/article/details/80835658

12、开发中,线上出了问题,是如何定位问题的?

如果有日志数据库,可以通过线上日志数据库,按照关键字和时间检索查找,如果没有,那就只能通过线上服务器的日志定位
常用命令:
1)tail -f 日志文件名称 f 是循环读取
2)vi编辑日志文件,然后 / 输入日志关键字,可定位具体的日志位置,n键向下查找日志,shift+n向上查找
3)grep '关键字' 日志文件
4)日志文件很大,不能vi,如何快速定位到日志
	得到错误日志或者异常日志的行号	
	cat -n test.log |grep "error" 
	cat -n test.log |grep "exception"
	
	通过位置往前往后查看日志详细
	// 比如错误日志在339555行,那就可以查询语句在 339500 -339600行中 || 100代表在339500 往后看100行
	cat -n test.log |tail -n +339500 |head -n 100  

13、Dubbo框架下默认的负载均衡策略是什么?还有哪几种负载均衡策略?

常用的3种负载均衡分别是:
Random 基于权重的随机负载均衡机制(默认)
RoundRobin 基于权重的轮询负载均衡机制
LeastActive 最少活跃数(最少并发)负载均衡机制

14、Dubbo与Dubbox区别?

Dubbo是阿里巴巴的
dubbox是当当网改造dubbo采用rest协议 http协议的。

15、Dubbo与SpringCloud区别?

dubo使用zookeeper来做注册中心

dubbo支持多种协议,默认使用的Dubbo协议。里面有Http协议、redis协议、hession协议、RMI协议。

dubbo平台可以自己配置负载均衡。

dubbo的负载均衡配置,权重越高,优先执行。


SpringCloud里面使用eureka来做注册中心的。

SpringCloud只能支持http协议。

SpringCloud里面有zuul网关。

SpringCloud里面有分布式配置中心

所以SpringCLoud功能强大与dubbo

16、Memcache与Redis的区别都有哪些?

1)、存储方式 Memecache把数据全部存在内存之中,断电后会挂掉,数据不能超过内存大小。 Redis
有部份存在硬盘上,redis可以持久化其数据
2)、数据支持类型   memcached所有的值均是简单的字符串,redis作为其替代者,支持更为丰富的数据类型 ,提供list,set,zset,hash等数据结构的存储
3)、使用底层模型不同 它们之间底层实现方式 以及与客户端之间通信的应用协议不一样。  Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求。
4). value 值大小不同:Redis 最大可以达到 1gb;memcache 只有 1mb。5)redis的速度比memcached快很多
6)Redis支持数据的备份,即master-slave模式的数据备份,高可用。

17、Spring Boot、Spring MVC 和 Spring 有什么区别?

Spring 框架就像一个家族,有众多衍生产品例如 boot、security、jpa等等。但他们的基础都是Spring 的ioc和 aop,ioc 提供了依赖注入的容器, aop解决了面向横切面的编程,然后在此两者的基础上实现了其他延伸产品的高级功能。

Spring MVC提供了一种轻度耦合的方式来开发web应用。它是Spring的一个模块,是一个web框架。通过Dispatcher Servlet, ModelAndView 和 View Resolver,开发web应用变得很容易。解决的问题领域是网站应用程序或者服务开发——URL路由、Session、模板引擎、静态Web资源等等。

Spring Boot实现了自动配置,降低了项目搭建的复杂度。它主要是为了解决使用Spring框架需要进行大量的配置太麻烦的问题,所以它并不是用来替代Spring的解决方案,而是和Spring框架紧密结合用于提升Spring开发者体验的工具。同时它集成了大量常用的第三方库配置(例如Jackson, JDBC, Mongo, Redis, Mail等等),Spring Boot应用中这些第三方库几乎可以零配置的开箱即用(out-of-the-box)。

Spring Boot只是承载者,辅助你简化项目搭建过程的。如果承载的是WEB项目,使用Spring MVC作为MVC框架,那么工作流程和你上面描述的是完全一样的,因为这部分工作是Spring MVC做的而不是Spring Boot。

对使用者来说,换用Spring Boot以后,项目初始化方法变了,配置文件变了,另外就是不需要单独安装Tomcat这类容器服务器了,maven打出jar包直接跑起来就是个网站,但你最核心的业务逻辑实现与业务流程实现没有任何变化。

总结:Spring 最初利用“工厂模式”(DI)和“代理模式”(AOP)解耦应用组件。大家觉得挺好用,于是按照这种模式搞了一个 MVC框架(一些用Spring 解耦的组件),用开发 web 应用( SpringMVC )。然后发现每次开发都写很多样板代码,为了简化工作流程,于是开发出了一些“懒人整合包”(starter),这套就是 Spring Boot。

18、Redis的数据类型有几种,以及每种数据类型的使用场景

一共5种

1)String
这个其实没啥好说的,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计  数功能的缓存。
2)hash
这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。博主在做单点登录的时候,  就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟   出类似session的效果。
3)list
使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基    于redis的分页功能,性能极佳,用户体验好。本人还用一个场景,很合适—取行情信息。就也是个生产    者和消费者的场景。LIST可以很好的完成排队,先进先出的原则。
4)set
因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去  重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去   重,再起一个公共服务,太麻烦了。
另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。
5)sorted set
sorted set多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。

19、如何把一个对象保存到redis中?

使用阿里巴巴的fastJson把对象变为json字符串,使用toJSONString方法,如果需要把json字符串转换为对象可以使用parseObject方法

20、Redis的分布式锁命令是什么?这个命令产生的效果是什么?

setnx命令,有key不可以保存,无key才能保存,可以实现多台服务共享一个锁

21、Redis是单线程还是单进程的?

单进程单线程

22、消息中间件的作用和使用场景

因为消息中间件属于异步处理方式可以很好的对流量进行削峰,主要适用于应用解耦(大业务模块拆分),流量消峰(抢购)等

消息中间件例如,ActiveMQ,Kafka,RocketMQ和RabbitMQ等等,是业务开发中不可或者的组件。通常消息中间件包括3个角色组成,如下:

生成者(Producer),生产消息。
消息代理(message broker),存储生产者产生的消息。
消费者(Consumer),从消息代理获取并消费消息。

具体参照:https://blog.youkuaiyun.com/new_com/article/details/105441750

23、SpringCloud有哪些组件?

Eureka注册中心,Feign调用,Ribbon负载均衡,Zuul网关,Hystrix熔断

24、乐观锁悲观锁介绍下

何谓悲观锁与乐观锁

乐观锁对应于生活中乐观的人总是想着事情往好的方向发展,悲观锁对应于生活中悲观的人总是想着事情往坏的方向发展。这两种人各有优缺点,不能不以场景而定说一种人好于另外一种人。

悲观锁

总是假设最坏的情况,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会上锁,这样别人想拿这个数据就会阻塞直到它拿到锁(共享资源每次只给一个线程使用,其它线程阻塞,用完后再把资源转让给其它线程)。传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作之前先上锁。Java中synchronized和ReentrantLock等独占锁就是悲观锁思想的实现。


乐观锁

总是假设最好的情况,每次去拿数据的时候都认为别人不会修改,所以不会上锁,但是在更新的时候会判断一下在此期间别人有没有去更新这个数据,可以使用版本号机制和CAS算法实现。乐观锁适用于多读的应用类型,这样可以提高吞吐量,像数据库提供的类似于write_condition机制,其实都是提供的乐观锁。在Java中java.util.concurrent.atomic包下面的原子变量类就是使用了乐观锁的一种实现方式CAS实现的。

两种锁的使用场景

从上面对两种锁的介绍,我们知道两种锁各有优缺点,不可认为一种好于另一种,像乐观锁适用于写比较少的情况下(多读场景),即冲突真的很少发生的时候,这样可以省去了锁的开销,加大了系统的整个吞吐量。但如果是多写的情况,一般会经常产生冲突,这就会导致上层应用会不断的进行retry,这样反倒是降低了性能,所以一般多写的场景下用悲观锁就比较合适。


25、数据库连接池工作机制

什么是连接池

数据库连接池负责分配、管理和释放数据库连接,它允许应用程序重复使用一个现有的数据库连接,而不是再重新建立一个。

为什么要使用连接池

数据库连接是一种关键的有限的昂贵的资源,这一点在多用户的网页应用程序中体现得尤为突出。  一个数据库连接对象均对应一个物理数据库连接,每次操作都打开一个物理连接,使用完都关闭连接,这样造成系统的 性能低下。 数据库连接池的解决方案是在应用程序启动时建立足够的数据库连接,并讲这些连接组成一个连接池(简单说:在一个“池”里放了好多半成品的数据库联接对象),由应用程序动态地对池中的连接进行申请、使用和释放。对于多于连接池中连接数的并发请求,应该在请求队列中排队等待。并且应用程序可以根据池中连接的使用率,动态增加或减少池中的连接数。 连接池技术尽可能多地重用了消耗内存地资源,大大节省了内存,提高了服务器地服务效率,能够支持更多的客户服务。通过使用连接池,将大大提高程序运行效率,同时,我们可以通过其自身的管理机制来监视数据库连接的数量、使用情况等。 

传统的连接机制与数据库连接池的运行机制区别

不使用连接池流程

下面以访问MySQL为例,执行一个SQL命令,如果不使用连接池,需要经过哪些流程。


不使用数据库连接池的步骤:

TCP建立连接的三次握手
MySQL认证的三次握手
真正的SQL执行
MySQL的关闭
TCP的四次握手关闭
可以看到,为了执行一条SQL,却多了非常多我们不关心的网络交互。

优点:

实现简单

缺点:

网络IO较多
数据库的负载较高
响应时间较长及QPS较低
应用频繁的创建连接和关闭连接,导致临时对象较多,GC频繁
在关闭连接后,会出现大量TIME_WAIT 的TCP状态(在2个MSL之后关闭)

使用连接池流程
使用数据库连接池的步骤:

第一次访问的时候,需要建立连接。 但是之后的访问,均会复用之前创建的连接,直接执行SQL语句。

优点:

较少了网络开销
系统的性能会有一个实质的提升
没了麻烦的TIME_WAIT状态

数据库连接池的工作原理
连接池的工作原理主要由三部分组成,分别为

连接池的建立
连接池中连接的使用管理
连接池的关闭

        第一、连接池的建立。一般在系统初始化时,连接池会根据系统配置建立,并在池中创建了几个连接对象,以便使用时能从连接池中获取。连接池中的连接不能随意创建和关闭,这样避免了连接随意建立和关闭造成的系统开销。Java中提供了很多容器类可以方便的构建连接池,例如Vector、Stack等。

        第二、连接池的管理。连接池管理策略是连接池机制的核心,连接池内连接的分配和释放对系统的性能有很大的影响。其管理策略是:

        当客户请求数据库连接时,首先查看连接池中是否有空闲连接,如果存在空闲连接,则将连接分配给客户使用;如果没有空闲连接,则查看当前所开的连接数是否已经达到最大连接数,如果没达到就重新创建一个连接给请求的客户;如果达到就按设定的最大等待时间进行等待,如果超出最大等待时间,则抛出异常给客户。

        当客户释放数据库连接时,先判断该连接的引用次数是否超过了规定值,如果超过就从连接池中删除该连接,否则保留为其他客户服务。

        该策略保证了数据库连接的有效复用,避免频繁的建立、释放连接所带来的系统资源开销。

        第三、连接池的关闭。当应用程序退出时,关闭连接池中所有的连接,释放连接池相关的资源,该过程正好与创建相反。

原文参考:https://blog.youkuaiyun.com/CrankZ/article/details/82874158?utm_medium=distribute.pc_relevant.none-task-blog-OPENSEARCH-10.control&dist_request_id=59ef38f5-7818-47fd-8f38-770bb9ed4eae&depth_1-utm_source=distribute.pc_relevant.none-task-blog-OPENSEARCH-10.control

26、什么是幂等性

幂等性:就是用户对于同一操作发起的一次请求或者多次请求的结果是一致的,不会因为多次点击而产生了多个结果。

例如:   

1. 前端重复提交选中的数据,应该后台只产生对应这个数据的一个反应结果。 
2. 我们发起一笔付款请求,应该只扣用户账户一次钱,当遇到网络重发或系统bug重发,也应该只扣一次钱; 
3. 发送消息,也应该只发一次,同样的短信发给用户,用户会哭的; 
4. 创建业务订单,一次业务请求只能创建一个,创建多个就会出大问题。   

等等很多重要的情况,这些逻辑都需要幂等的特性来支持。   

在增删改查4个操作中,查询时天然的幂等性操作,但是尤为注意就是增加或者修改,查询对于结果是不会有改变的,删除只会进行一次,用户多次点击产生的结果一样,修改在大多场景下结果一样,增加在重复提交的场景下会出现。

27、为什么要用swagger,常用注解及作用

Swagger 是一个规范且完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。

Swagger 的目标是对 REST API 定义一个标准且和语言无关的接口,可以让人和计算机拥有无须访问源码、文档或网络流量监测就可以发现和理解服务的能力。当通过 Swagger 进行正确定义,用户可以理解远程服务并使用最少实现逻辑与远程服务进行交互。与为底层编程所实现的接口类似,Swagger 消除了调用服务时可能会有的猜测。

Swagger 的优势

支持 API 自动生成同步的在线文档:使用 Swagger 后可以直接通过代码生成文档,不再需要自己手动编写接口文档了,对程序员来说非常方便,可以节约写文档的时间去学习新技术。
提供 Web 页面在线测试 API:光有文档还不够,Swagger 生成的文档还支持在线测试。参数和格式都定好了,直接在界面上输入参数对应的值即可在线测试接口。

说白了,swagger就是为了方便系统生成API文档。方便联合开发。

常用注解
- @Api()用于类; 表示标识这个类是swagger的资源 
- @ApiOperation()用于方法; 表示一个http请求的操作 
- @ApiParam()用于方法,参数,字段说明; 表示对参数的添加元数据(说明或是否必填等) 
- @ApiModel()用于类 表示对类进行说明,用于参数用实体类接收 
- @ApiModelProperty()用于方法,字段 表示对model属性的说明或者数据操作更改 
- @ApiIgnore()用于类,方法,方法参数 表示这个方法或者类被忽略 
- @ApiImplicitParam() 用于方法 表示单独的请求参数 
- @ApiImplicitParams() 用于方法,包含多个 @ApiImplicitParam

28、如果一个项目中同时保存数据进Redis和MySql如何保证数据一致?

https://www.cnblogs.com/rjzheng/p/9041659.html?spm=a2c6h.12873639.0.0.2020fe8dbuaVRu#!comments

29、简单说一下什么是MySQL主从复制及优缺点

MySQL从3.23版本开始提供复制功能,复制主要是指将主服务器的DDL和DML操作,通过二进制日志(binLog日志),传到服务的服务器上,然后在从服务器上对这些日志从新执行,从而实现从服务器与主服务器的数据同步。MySQL支持一台主服务器同时向多台从服务器进行复制,从服务器同时也可以作为其他服务器的主服务器,实现链状的复制。

优点

如果主服务器出现问题,可以快速切换到从服务器提供服务。
可以在从服务器上执行查询,降低主服务器的压力。
可以在从服务器上执行备份,以避免备份期间影响主服务器的性能。

缺点

由于MySQL实现的是异步复制,所以主从服务器之间的数据存在一定差异,对实时性要求高的数据仍然需要从主服务器上获得。

30、简单介绍下Redis的哨兵机制,Redis集群

https://blog.youkuaiyun.com/ls1645/article/details/78931605

https://blog.youkuaiyun.com/a67474506/article/details/50435498?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control&dist_request_id=aa70a850-f8fc-49ed-9f81-06bd13318fd0&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.control

31、Nginx负载均衡,Session不一致怎么解决?

负载均衡规则设置为:ip_hash

这样虽然能解决问题,但是万一其中一台服务器挂了,这个用户就访问不了这个服务了,用ip_hash只提高了服务器的并发能力,没有提高容灾能力。

Tomcat配置同步session

会增加应用服务器压力,不推荐。


Cookie存Session

Cookie不安全,若客户端禁用Cookie也无法进行Session同步。


session外置,存缓存

存到Redis或Memcache中,Session外置集中管理,推荐。

原文参考:https://my.oschina.net/u/4804015/blog/4749321

32、消息队列常见问题和解决方案

原文参考:https://blog.youkuaiyun.com/qq_36236890/article/details/81174504?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.control&dist_request_id=f87dd723-2b03-4b5e-937a-5d1d2e65356f&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-5.control

33、分布式系统,如何保证数据一致性

https://blog.youkuaiyun.com/vcliy/article/details/85229062?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&spm=1001.2101.3001.4242

https://www.infoq.cn/article/solution-of-distributed-system-transaction-consistency

34、怎么查找线上执行慢的SQL语句

https://www.cnblogs.com/qmfsun/p/4844472.html
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值