Java面试题(二)

数据库:
1.谈谈你对数据库的了解?
2.mysql和Oracle的优缺点?
3.mysql的优化?
4.redis的底层实现原理是什么?
5.乐观锁与悲观锁机制理解
6.redis中的事务和mysql中的事务有什么区别?
7.oracle的存储过程和函数有什么区别?
8.如何优化SQL语句
9.并发的处理,分布式锁
10.redis如何应对缓存雪崩
11.redis的过期策略有哪些
12.redis的并发竞争问题如何解决

前端:
1、页面多次提交会导致什么问题,怎么防范页面多次提交.
2、怎么让2个div展示在同一行(float)
3、easyUI和jquery的版本是多少?在我们的系统中
4、AJAX是什么,在前端怎么执行?如果我有一个需求,a1返回的结果,依赖给a2,a2的结果依赖给a3,直到a5,如果遇到这种情况,我该怎么做?如何去设计?(我和他讲了ajax的底层执行流程,他又说不要讲这些,这个老头脑子坏掉了)
5、easyUI是什么?
一、设计模式的分类
二、设计模式的六大原则
Mybatis面试题:
什么是MyBatis的接口绑定,有什么好处
2.MyBatis实现一对一有几种方式?具体怎么操作的
3.MyBatis实现一对多有几种方式,怎么操作的
4.讲下MyBatis的缓存 MyBatis的缓存分为一级缓存和二级缓存
5.#{}和${}的区别是什么?
6.Xml映射文件中,除了常见的select|insert|updae|delete标签之外,还有哪些标签?
7.最佳实践中,通常一个Xml映射文件,都会写一个Dao接口与之对应,请问,这个Dao接口的工作原理是什么?Dao接口里的方法,参数不同时,方法能重载吗?
8.简述Mybatis的插件运行原理,以及如何编写一个插件。
9.Mybatis能执行一对一、一对多的关联查询吗?都有哪些实现方式,以及它们之间的区别。
10.Mybatis是否支持延迟加载?如果支持,它的实现原理是什么?
11.Mybatis中如何执行批处理?
12.Mybatis都有哪些Executor执行器?它们之间的区别是什么?
15.Mybatis中如何指定使用哪一种Executor执行器?

Spring:
1.谈谈你对spring的理解
2.Spring中用到的设计模式
3.Spring Bean的作用域之间有什么区别?
4.ssm请求执行流程

多线程:
1.多线程的几种通讯方式
2.异步获取多线程返回的数据
3.当一个同步方法已经执行,线程能够调用对象上的非同步实例方法吗?
4.用过哪些线程安全的集合?
5.乐观锁与悲观锁机制理解

maven的插件有哪些
Tomcat:
1.tomcat安全性方面你会怎么做?

Jdk1.8的新特性

MQ:
1.mq如何保证他的高可用?
镜像模式:把需要的队列做成镜像队列,存在于多个节点,属于RabbitMQ的高可用方案
高可用三种策略模式:
1)同步至所有的节点
2)同步最多N个机器
3)只同步至符合指定名称的节点

2.怎么防止mq消费重复的数据?
1.比如,你拿到这个消息做数据库的insert操作。那就容易了,给这个消息做一个唯一主键,那么就算出现重复消费的情况,就会导致主键冲突,避免数据库出现脏数据。
2.再比如,你拿到这个消息做redis的set的操作,那就容易了,不用解决,因为你无论set几次结果都是一样的,set操作本来就算幂等操作。
3.如果上面两种情况还不行,上大招。准备一个第三方介质,来做消费记录。以redis为例,给消息分配一个全局id,只要消费过该消息,将以K-V形式写入redis。那消费者开始消费前,先去redis中查询有没消费记录即可。

3.如何防止mq的消息丢失?
1、消息确认 2、消息的持久化

4.几百万条数据在消息队列中积压了怎么办?
一般这个时候,只能操作临时紧急扩容了,具体操作步骤和思路如下:
1)先修复consumer的问题,确保其恢复消费速度,然后将现有cnosumer都停掉;
2)新建一个topic,partition是原来的10倍,临时建立好原先10倍或者20倍的queue数量;
3)然后写一个临时的分发数据的consumer程序,这个程序部署上去消费积压的数据,消费之后不做耗时的处理,直接均匀轮询写入临时建立好的10倍数量的queue;
4)接着临时征用10倍的机器来部署consumer,每一批consumer消费一个临时queue的数据;
5)这种做法相当于是临时将queue资源和consumer资源扩大10倍,以正常的10倍速度来消费数据;
6)等快速消费完积压数据之后,得恢复原先部署架构,重新用原先的consumer机器来消费消息;

假设你用的是rabbitmq,rabbitmq是可以设置过期时间的,就是TTL,如果消息在queue中积压超过一定的时间就会被rabbitmq给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据会大量积压在mq里,而是大量的数据会直接搞丢。
这个情况下,就不是说要增加consumer消费积压的消息,因为实际上没啥积压,而是丢了大量的消息。我们可以采取一个方案,就是批量重导,这个我们之前线上也有类似的场景干过。就是大量积压的时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,比如大家一起喝咖啡熬夜到晚上12点以后,用户都睡觉了。
这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出来,然后重新灌入mq里面去,把白天丢的数据给他补回来。也只能是这样了。
假设1万个订单积压在mq里面,没有处理,其中1000个订单都丢了,你只能手动写程序把那1000个订单给查出来,手动发到mq里去再补一次。

5.如果让你来设计一款mq,你会怎么设计,讲讲你的思路?
比如说这个消息队列系统,我们从以下几个角度来考虑一下:
首先这个 mq 得支持可伸缩性吧,就是需要的时候快速扩容,就可以增加吞吐量和容量,那怎么搞?设计个分布式的系统呗,参照一下 kafka 的设计理念,broker -> topic -> partition,每个 partition 放一个机器,就存一部分数据。如果现在资源不够了,简单啊,给 topic 增加 partition,然后做数据迁移,增加机器,不就可以存放更多数据,提供更高的吞吐量了?
其次你得考虑一下这个 mq 的数据要不要落地磁盘吧?那肯定要了,落磁盘才能保证别进程挂了数据就丢了。那落磁盘的时候怎么落啊?顺序写,这样就没有磁盘随机读写的寻址开销,磁盘顺序读写的性能是很高的,这就是 kafka 的思路。
其次你考虑一下你的 mq 的可用性啊?这个事儿,具体参考之前可用性那个环节讲解的 kafka 的高可用保障机制。多副本 -> leader & follower -> broker 挂了重新选举 leader 即可对外服务。
能不能支持数据 0 丢失啊?可以的,参考我们之前说的那个 kafka 数据零丢失方案。

分布式搜索引擎:
1.分布式搜索引擎是怎么架构的?为啥是分布式的?
elasticsearch设计的理念就是分布式搜索引擎,底层其实还是基于lucene的。
核心思想就是在多台机器上启动多个es进程实例,组成了一个es集群。
es中存储数据的基本单位是索引,比如说你现在要在es中存储一些订单数据,你就应该在es中创建一个索引,order_idx,所有的订单数据就都写到这个索引里面去,一个索引差不多就是相当于是mysql里的一张表。index -> type -> mapping -> document -> field。

2.你们公司分布式引擎是怎么部署的?

3.分布式引擎在几十亿数据量的情况下怎么调优?
1.性能优化的杀手锏——filesystem cacheos cache,操作系统的缓存。2.数据预热3.冷热分离4.document模型设计 5.分页性能优化

DUBBO:
说白了,就是看你对dubbo熟悉不熟悉:
(1)dubbo工作原理:服务注册,注册中心,消费者,代理通信,负载均衡;
(2)网络通信、序列化:dubbo协议,长连接,NIO,hessian序列化协议;
(3)负载均衡策略,集群容错策略,动态代理策略:dubbo跑起来的时候一些功能是如何运转的,怎么做负载均衡?怎么做集群容错?怎么生成动态代理?
(4)dubbo SPI机制:你了解不了解dubbo的SPI机制?如何基于SPI机制对dubbo进行扩展?
原文链接:https://blog.csdn.net/A_BlackMoon/article/details/85609379
1.dubbo的工作原理是啥?
第一层:service 层,接口层,给服务提供者和消费者来实现的
第二层:config 层,配置层,主要是对 dubbo 进行各种配置的
第三层:proxy 层,服务代理层,无论是 consumer 还是 provider,dubbo 都会给你生成代理,代理 之间进行网络通信
第四层:registry 层,服务注册层,负责服务的注册与发现
第五层:cluster 层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务
第六层:monitor 层,监控层,对 rpc 接口的调用次数和调用时间进行监控
第七层:protocal 层,远程调用层,封装 rpc 调用
第八层:exchange 层,信息交换层,封装请求响应模式,同步转异步
第九层:transport 层,网络传输层,抽象 mina 和 netty 为统一接口
第十层:serialize 层,数据序列化层
2.为什么要把项目拆分成分布式的?为啥要用dubbo?
1)各种代码冲突和合并处理。
2)有改动,所有代码要重新测试
3)每次发布都是几十万行代码的发布,大家提心吊胆。
4)一个人升级框架版本会导致其他人代码报错。
3.Dubbo支持哪些通讯协议及序列化协议?
dubbo支持不同的通信协议:
1.dubbo协议 默认就是走dubbo协议的,单一长连接,NIO异步通信,基于hessian作为序列化协议
2.rmi协议
走java二进制序列化,多个短连接,适合消费者和提供者数量差不多,适用于文件的传输,一般较少用
3.hessian协议
走hessian序列化协议,多个短连接,适用于提供者数量比消费者数量还多,适用于文件的传输,一般较少用
4.http协议 走json序列化
5.webservice 走SOAP文本序列化
4.Dubbo支持哪些负载均衡,高可用以及动态代理的策略?

5.Dubbo如何做服务治理,服务降噪?
调用链路自动生成:
服务访问压力以及时长统计
服务降级: 比如说服务A调用服务B,结果服务B挂掉了,服务A重试几次调用服务B,还是不行,直接降级,走一个备用的逻辑,给用户返回响应
分布式:
1.分布式系统中接口的幂等性如何保证?
1.幂等性
所谓幂等性,就是说一个接口,多次发起同一个请求,你这个接口得保证结果是准确的,比如不能多扣款,不能多插入一条数据,不能将统计值多加了1。这就是幂等性。

2.如何保证幂等性
①对于每个请求必须有一个唯一的标志,比如订单支付请求,必须要包含订单的id,一个id只能支付一次。

②每次处理完请求之后,必须要有一个记录标识这个请求已经处理过了,比如最常见的是在mysql中记录一个状态,比如支付前先插入一条这个订单的支付流水,而且支付流水采用唯一约束,只有插入成功才进行支付。

③每次接受到请求之后需要先判断之前是否已经处理过,比如一条订单已经支付了,那么就一定会有支付流水,如果存在就表示已经支付过了。

在实际操作中,可以结合自己的业务,比如说用redis用orderId作为唯一键。只有成功插入这个支付流水,才可以执行实际的支付扣款。你就可以写一个标识到redis里面去,set order_id payed,下一次重复请求过来了,先查redis的order_id对应的value,如果是payed就说明已经支付过了,你就别重复支付了。
2.分布式系统中接口的调用如何保证顺序性?
把要保证顺序的同一个key的数据或请求都哈希分发到同一个机器上去处理。然后这个机器把这些请求发到同一个内存queue中,然后要用同一个线程消费。
3.分布式锁是啥?
分布式锁其实可以理解为:控制分布式系统有序的去对共享资源进行操作,通过互斥来保持一致性。 举个不太恰当的例子:假设共享的资源就是一个房子,里面有各种书,分布式系统就是要进屋看书的人,分布式锁就是保证这个房子只有一个门并且一次只有一个人可以进,而且门只有一把钥匙。然后许多人要去看书,可以,排队,第一个人拿着钥匙把门打开进屋看书并且把门锁上,然后第二个人没有钥匙,那就等着,等第一个出来,然后你在拿着钥匙进去,然后就是以此类推
实现原理
** 互斥性**
保证同一时间只有一个客户端可以拿到锁,也就是可以对共享资源进行操作
安全性
只有加锁的服务才能有解锁权限,也就是不能让a加的锁,bcd都可以解锁,如果都能解锁那分布式锁就没啥意义了
可能出现的情况就是a去查询发现持有锁,就在准备解锁,这时候忽然a持有的锁过期了,然后b去获得锁,因为a锁过期,b拿到锁,这时候a继续执行第二步进行解锁如果不加校验,就将b持有的锁就给删除了
避免死锁
出现死锁就会导致后续的任何服务都拿不到锁,不能再对共享资源进行任何操作了
保证加锁与解锁操作是原子性操作
这个其实属于是实现分布式锁的问题,假设a用redis实现分布式锁
假设加锁操作,操作步骤分为两步:
1,设置key set(key,value)2,给key设置过期时间
假设现在a刚实现set后,程序崩了就导致了没给key设置过期时间就导致key一直存在就发生了死锁
使用redis实现分布式锁
使用redis命令 set key value NX EX max-lock-time 实现加锁
使用redis命令 EVAL 实现解锁
https://img-blog.csdn.net/20180219144927282

4.分布式事物的方案你们是怎么做的?
两阶段提交方案/XA方案
TCC方案
本地消息表
可靠消息最终一致性方案
feseaca

数据库:
1.你们公司是怎么分库分表的?
2.你们是怎么在系统不停机的情况下把数据迁移到分库分表的?
(2)双写迁移方案

这个是我们常用的一种迁移方案,比较靠谱一些,不用停机,不用看北京凌晨4点的风景

简单来说,就是在线上系统里面,之前所有写库的地方,增删改操作,都除了对老库增删改,都加上对新库的增删改,这就是所谓双写,同时写俩库,老库和新库。

然后系统部署之后,新库数据差太远,用之前说的导数工具,跑起来读老库数据写新库,写的时候要根据gmt_modified这类字段判断这条数据最后修改的时间,除非是读出来的数据在新库里没有,或者是比新库的数据新才会写。

接着导万一轮之后,有可能数据还是存在不一致,那么就程序自动做一轮校验,比对新老库每个表的每条数据,接着如果有不一样的,就针对那些不一样的,从老库读数据再次写。反复循环,直到两个库每个表的数据都完全一致为止。

1、系统中修改写数据库的代码,同时写单库和新库;
2、数据迁移工具获取到老库的数据,在新库中进行比较,如果新库中不存在,那么把数据保存到新库中;如果新库中存在数据,那么比较更新时间,如果老库的更新时间大于新库,那么修改新库的数据;如果老库的更新时间小于新库的,那么保持不变。
3、迁移完之后需要比较数据是否完全一样,在凌晨的时候,数据肯定会变为一致,因为很少数据进来。
4、最后凌晨,系统把写老库的代码删掉,都写新库。
整个迁移的过程就结束了,这个过程只有在删除写老库代码的时候,会停下服务(你使用了集群,其实对用户来说是无感知的)。

注:如果想数据迁移快点,那么可以多部署一些数据迁移工具。

3.如何设计可以动态扩容的分库分表?

4.分库分表之后全局的id怎么生成?
数据库自增id
uuid:
获取系统当前时间:
snowflake(雪花)算法:

5.说说mysql读写分离的原理?主从同步延时怎么解决?
主库将变更写binlog日志,然后从库连接到主库之后,从库有一个IO线程,将主库的binlog日志拷贝到自己本地,写入一个中继日志中。接着从库中有一个SQL线程会从中继日志读取binlog,然后执行binlog日志中的内容,也就是在自己本地再次执行一遍SQL,这样就可以保证自己跟主库的数据是一样的。
这里有一个非常重要的一点,就是从库同步主库数据的过程是串行化的,也就是说主库上并行的操作,在从库上会串行执行。所以这就是一个非常重要的点了,由于从库从主库拷贝日志以及串行执行SQL的特点,在高并发场景下,从库的数据一定会比主库慢一些,是有延时的。所以经常出现,刚写入主库的数据可能是读不到的,要过几十毫秒,甚至几百毫秒才能读取到。

而且这里还有另外一个问题,就是如果主库突然宕机,然后恰好数据还没同步到从库,那么有些数据可能在从库上是没有的,有些数据可能就丢失了。

所以mysql实际上在这一块有两个机制,一个是半同步复制,用来解决主库数据丢失问题;一个是并行复制,用来解决主从同步延时问题。

这个所谓半同步复制,semi-sync复制,指的就是主库写入binlog日志之后,就会将强制此时立即将数据同步到从库,从库将日志写入自己本地的relay log之后,接着会返回一个ack给主库,主库接收到至少一个从库的ack之后才会认为写操作完成了。

所谓并行复制,指的是从库开启多个线程,并行读取relay log中不同库的日志,然后并行重放不同库的日志,这是库级别的并行。
1)主从复制的原理;
2)主从延迟问题产生的原因;
3)主从复制的数据丢失问题,以及半同步复制的原理;
4)并行复制的原理,多库并发重放relay日志,缓解主从延迟问题。

一般来说,如果主从延迟较为严重:
1、分库,将一个主库拆分为4个主库,每个主库的写并发就500/s,此时主从延迟可以忽略不计;
2、打开mysql支持的并行复制,多个库并行复制,如果说某个库的写入并发就是特别高,单库写并发达到了2000/s,并行复制还是没意义。28法则,很多时候比如说,就是少数的几个订单表,写入了2000/s,其他几十个表10/s;
3、重写代码,写代码的同学,要慎重,当时我们其实短期是让那个同学重写了一下代码,插入数据之后,直接就更新,不要查询;
4、如果确实是存在必须先插入,立马要求就查询到,然后立马就要反过来执行一些操作,对这个查询设置直连主库。不推荐这种方法,你这么搞导致读写分离的意义就丧失了。

高可用:
1.如何设计高可用的系统架构

你可能感兴趣的:(Java面试题(二))