面试必看-目录

mysql

事务的四大特性及数据库隔离级别
补充:A、I、D是手段、C是目的,弄到一块去完全是为了拼凑个单词缩写,奇葩!
Mysql中事务ACID的原理
不可重复读和幻读的区别在那里呢?
不可重复读是修改或者删除,幻读是插入。(sql92标准明确规定的)

优化的大方向
其他
补充:sql与索引–》表、存储引擎–》架构–》数据库配置(连接数、缓存区大小等)–》os和硬件,越往后成本越高,性能提升越慢
执行计划查看
执行计划extra的取值
mysql join 算法
小表驱动大表
索引的分类
MySQL有哪些索引?为什么用B+树?B+树高度如何计算?
聚簇索引和非聚簇索引的区别

聚簇索引的意思为我们的数据和索引是在一起的,非聚簇索引的意思为索引和数据不在一起。在一起的好处在于我们可以通过找到索引就能找到数据,缺点是索引表非常的大。在innodb引擎中,主键就为聚簇索引,其他的索引为非聚簇索引。在myasim引擎中索引为非聚簇索引。非聚簇索引保存的是索引和该数据在物理储存中的位置。找到索引后还需要去物理储存中再次读取数据。所以非聚簇索引在索引建立时需要更小的空间,但是查找还需要多一次读取。

(mysql会将字符串转化为数字,不会把数字转化为字符串)
索引失效的几种情况
请添加图片描述
联合索引的数据结构
mvcc

分库分表
基因注入法
锁,死锁以及mysql死锁的处理
行锁什么时候升级表锁
innodb和myisam的区别
innodb的内存结构
内存淘汰算法:lru,区别于传统的lru,新访问的页放在末尾37%的位置,防止全表扫描污染
mysql更新语句的执行流程
其他
B树和B+树的区别
(B-树不是B减树,就是B树,因为B树的英文B-tree翻译过来B-树,翻译的误解,其实就是B树)
补充:B+树数据冗余,重复的数据可能出现在几个节点上,叶子节点有指针,范围查询更方便,叶子节点包含数据和索引,且叶子节点包含所有的数据,查询更稳定,而非叶子节点只有索引
gupao课程的第一课

redis

数据库和缓存数据不一致处理

redis为什么这么快?

纯内存操作。
核心是基于非阻塞的 IO 多路复用机制。
C 语言实现,一般来说,C 语言实现的程序“距离”操作系统更近,执行速度相对会更快。
单线程反而避免了多线程的频繁上下文切换问题,预防了多线程可能产生的竞争问题。

持久化
rdb和aop
集群
smart客户端
数据结构
redis内存淘汰策略

补充:
   redis默认是no-envicition策略

redis键过期策略
击穿、雪崩、穿透的解决

spring

ioc和aop
其他1
@Tractional失效的原因
事务传播特性


@Service
public class AA {
    @Autowired
    private CommonMapper1 commonMapper;
    @Autowired
    private BB bb;
    @Transactional(propagation = Propagation.REQUIRED)
    public void mu(){
        commonMapper.updateMaById();
        try {
            bb.bb();
        } catch (Exception e) {
            e.printStackTrace();
        }
//        int i = 1/0;

    }
    }


@Service
public class BB {
    @Autowired
    private CommonMapper1 commonMapper;
    @Transactional(propagation = Propagation.NESTED)
    public void bb(){
        commonMapper.updateMbById();
        int i = 1/0;
    }
}
补充:a代表外部,b代表内部
两个都是REQUIRED,外部异常都回滚
两个都是REQUIRED,内部异常都回滚,即使外部捕获了也都回滚,捕获后外部的事务提交报错org.springframework.transaction.UnexpectedRollbackException: Transaction rolled back because it has been marked as rollback-only

外部REQUIRED,内部REQUIRED_NEW,内部报错没有被外部捕获都会回滚,如果被外部捕获,外部不回滚,内部回滚
外部REQUIRED,内部REQUIRED_NEW,外部报错,内部不回滚,外部回滚

外部REQUIRED,内部NESTED,外部异常都回滚
外部REQUIRED,内部NESTED,内部异常,外部不捕获,都会回滚,如果外部捕获,外部不回滚,内部回滚

循环依赖的解决
bean的生命周期
文字描述
请添加图片描述
请添加图片描述
请添加图片描述
在这里插入图片描述

@PostConstruct注解详解
BeanFactory和FactoryNean的区别
请添加图片描述
spring事务的注解配置

mybatis

执行流程
一级和二级缓存
mybatis如何匹配接口方法和xml的sql语句
补充:
在这里插入图片描述
在这里插入图片描述
最终mappedStatements.get(id)拿到对应的mappedStatement(这个对象有需要的sql),这里的id即是statementId

mybatis中的#{}和${}的区别

springmvc

源码解析
如何通过url找到method
补充:

 urlMap:key是String(所有url路径,类和方法拼好的,不含有*和?的路径),value是List<RequestMappingInfo>,这个可以理解为url一样的,但是params之类不一样的,所以用集合
 handlerMethods:key是RequestMappingInfo(所有的扫描到的路径,也是由类和方法拼好的),value是HandlerMethod(方法的封装)
 

执行流程

设计模式

常见的设计模式
单例模式
dcl单例模式
其他

数据结构与算法

排序算法

分布式

分布式锁
redis分布式锁
分布式事务和CAP
分布式事务atomikos实现
补充:atomikos是2PC(刚性事务)的实现,目前很少用
一致性算法解析

源码

list–Arraylist和linkedlist
hashmap
hashmap的put方法的过程
ConcurrentHashMap
ConcurrentHashMap扩容
threadlocal
其他
其他2
sync和lock
其他
synchronized原理
String的intern方法

多线程

线程池的七大参数
线程池时如何确定线程数目
书上的答案
线程池的运行流程
线程顺序执行

jvm

new Object()到底占几个字节
线上环境 FGC 频繁,如何解决?
oom分析
详细
垃圾收集器的选择
类加载过程
jvm命令
运行时内存区域
常量池
其他
垃圾收集算法
java的四种引用
破坏双亲委派机制
详细

基础知识

Java面试宝典Beta5.0
String、StringBuffer和StringBuilder的区别
深拷贝和浅拷贝
深拷贝和浅拷贝的实现
基础数据类型和包装数据类型的区别
String.intern方法
jdk7和jdk8的区别

补充:concurrentHashmap存在疑问,另,新增了时间的api

输入一个url后发生什么
三次握手和四次挥手
502状态码的意思
tomcat线程池用完了发生什么

异常的分类

java.lang.Throwable
Error错误:JVM内部的严重问题。无法恢复。程序人员不用处理。

Exception异常:普通的问题。通过合理的处理,程序还可以回到正常执行流程。要求编程人员要进行处理。

RuntimeException:也叫非受检异常(unchecked exception).这类异常是编程人员的逻辑问题。应该承担责任。Java编译器不进行强制要求处理。也就是说,这类异常再程序中,可以进行处理,也可以不处理。

非RuntimeException:也叫受检异常(checked exception).这类异常是由一些外部的偶然因素所引起的。Java编译器强制要求处理。也就是说,程序必须进行对这类异常进行处理。

常见异常

错误:
NoClassDefFoundError:找不到 class 定义异常
StackOverflowError:深递归导致栈被耗尽而抛出的异常
OutOfMemoryError:内存溢出异常
1)非受检的:
NullPointerException,ClassCastException,ArrayIndexsOutOfBoundsException,ArithmeticException(算术异常,除0溢出)

2)受检:
Exception,FileNotFoundException,IOException,SQLException.

项目

被调用方如何保证api接口的数据安全
项目的问题及解决方案
1.mybatis的bug
2.热部署类型转换异常
3.jenkins打包缺失文件
微服务统一认证及授权
接口幂等性
需求改了表怎么办

linux

常见的排查日志的命令

git

团队协作流程
git版本回退命令

 假如我们有下面这一串 commit 的历史,我们希望从 a5 回退到 a3。

a1 -> a2 -> a3 -> a4 -> a5  
首先在 a5 我们输入 git log 查看 a3 对应的 commit id,是一段很长的字母数字序列,假设前 4 位是 ab42,并且在所有的 commit id 里面是唯一的(方便我们做简写)。

接着执行:

git reset --hard ab42 # commit id 不用写全,写明能够标识该 commit id 的前几位即可  
我们还有更方便的方法,可以不用知道 commit id :

git reset --hard HEAD^^  
其中 HEAD^^ 标识我们切换会上上一个版本。如果指向切换为上一个版本,也就是 a4,那可以:

git reset --hard HEAD^  

reset 的三种模式 
--hard:stage区和工作目录里的内容会被完全重置为和指定 HEAD 位置相同的内容。

--soft:保留工作目录和暂存区中未提交的内容,并把重置 HEAD 所带来的新的差异(回滚掉的commit较回滚后最新commit的修改)放进暂存区。

--mixed(默认):工作区、暂存区未提交的内容以及由 reset 所导致的新差异,都会被放进工作区。

springboot

springboot自动装配原理
spring-boot-start.jar的作用

zookeeper

集群节点数量
zab协议

MQ

RabbitMQ五种工作模式
消息的可靠性投递

补充:
1.生产者发送到RabbitMQ(这里所指的 “RabbitMQ” 仅仅是到 Exchange):一般不采用事务机制,而采用Confirm机制
代码如下:(队列和交换机一般在消费端,遵循谁使用谁管理)
@Configuration
public class TemplateConfig {
    @Bean
    public ConnectionFactory connectionFactory() throws Exception {
        CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
        cachingConnectionFactory.setUri(ResourceUtil.getKey("rabbitmq.uri"));
        return cachingConnectionFactory;
    }
    //管理队列、交换机和绑定
    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory) {
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        //Mandatory为true和ReturnCallback一起保证消息被交换机路由但没有匹配不到队列,会调用ReturnCallback
        rabbitTemplate.setMandatory(true);
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback(){
            public void returnedMessage(Message message,
                                        int replyCode,
                                        String replyText,
                                        String exchange,
                                        String routingKey){
                System.out.println("回发的消息:");
                System.out.println("replyCode: "+replyCode);
                System.out.println("replyText: "+replyText);
                System.out.println("exchange: "+exchange);
                System.out.println("routingKey: "+routingKey);
            }
        });

        //事务消息,一般不用,也是确保生产者到MQ这条路正常
        rabbitTemplate.setChannelTransacted(true);
       //confirm机制,生产者发送消息后,MQ会回调,确保生产者到MQ这条路正常
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                if (!ack) {
                    System.out.println("发送消息失败:" + cause);
                    throw new RuntimeException("发送异常:" + cause);
                }
            }
        });



        return rabbitTemplate;
    }
}
2.Exchange 没有匹配到队列的话,消息依然会丢失:
1)mandatory和ReturnCallback 代码如上
2)备份交换机:交换机的arguments参数alternate-exchange填写创建好的备份交换机(15672管理界面创建交换机)
3.交换机、队列、消息的持久化;
代码如下:
@Configuration
public class ConsumerConfig {
    @Bean
    public ConnectionFactory connectionFactory() throws Exception{
        CachingConnectionFactory cachingConnectionFactory = new CachingConnectionFactory();
        cachingConnectionFactory.setUri(ResourceUtil.getKey("rabbitmq.uri"));
        return cachingConnectionFactory;
    }

    @Bean
    public RabbitAdmin rabbitAdmin(ConnectionFactory connectionFactory) {
        return new RabbitAdmin(connectionFactory);
    }
  //第二个参数为是否持久化
    @Bean("reliableQueue")
    public Queue queue() {
        return new Queue("GP_RELIABLE_SEND_QUEUE", true, false, false, new HashMap<>());
    }
//第二个参数为是否持久化
    @Bean("directExchange")
    public DirectExchange exchange() {
        return new DirectExchange("GP_RELIABLE_SEND_EXCHANGE", true, false, new HashMap<>());
    }

    @Bean
    public Binding binding(@Qualifier("reliableQueue") Queue queue,@Qualifier("directExchange") DirectExchange exchange) {
        return BindingBuilder.bind(queue).to(exchange).with("gupao.tech");
    }

    @Bean
    public MessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory) {
        SimpleMessageListenerContainer messageListenerContainer = new SimpleMessageListenerContainer();
        messageListenerContainer.setConnectionFactory(connectionFactory);
        messageListenerContainer.setQueueNames("GP_RELIABLE_SEND_QUEUE");
        // 消费者并发数
        messageListenerContainer.setConcurrentConsumers(5);
        // 最大消费者并发
        messageListenerContainer.setMaxConcurrentConsumers(10);

        Map<String, Object> argumentMap = new HashMap();
        messageListenerContainer.setConsumerArguments(argumentMap);

        messageListenerContainer.setConsumerTagStrategy(new ConsumerTagStrategy() {
            @Override
            public String createConsumerTag(String s) {
                return "添加消费者";
            }
        });

        messageListenerContainer.setMessageListener(new MessageListener() {
            @Override
            public void onMessage(Message message) {
                try {
                    System.out.println(new String(message.getBody(), "UTF-8"));
                    System.out.println(message.getMessageProperties());
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
        return messageListenerContainer;
    }
}

public static void main(String[] args) {
        AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(ProducerApp.class);

        RabbitAdmin rabbitAdmin = context.getBean(RabbitAdmin.class);
        RabbitTemplate rabbitTemplate = context.getBean(RabbitTemplate.class);

        rabbitAdmin.declareExchange(new DirectExchange("GP_RELIABLE_SEND_EXCHANGE", true, false, new HashMap<>()));

        MessageProperties messageProperties = new MessageProperties();
        // 消息持久化
        messageProperties.setDeliveryMode(MessageDeliveryMode.PERSISTENT);
        messageProperties.setContentType("UTF-8");
        Message message = new Message("各部门注意,今天8点发车".getBytes(), messageProperties);

        rabbitTemplate.convertAndSend("GP_RELIABLE_SEND_EXCHANGE", "gupao.tech", message, new CorrelationData("201906180001"));
        rabbitTemplate.send("GP_RELIABLE_SEND_EXCHANGE", "gupao.tech", message, new CorrelationData("201906180001"));
        rabbitTemplate.send("GP_RELIABLE_SEND_EXCHANGE", "gupao.tech.wrong", message, new CorrelationData("201906180002"));
    }
4.采用镜像模式的集群
5.MQ到消费者,开启手动确认(单独设置某个队列)
代码:
//springboot中消费者被封装为SimpleMessageListenerContainer,可以在这个类上设置
@Bean
public SimpleMessageListenerContainer messageListenerContainer(ConnectionFactory connectionFactory){
    SimpleMessageListenerContainer container = new SimpleMessageListenerContainer();
    container.setConnectionFactory(connectionFactory);
    container.setQueueNames("consumer_queue");              // 监听的队列
    container.setAcknowledgeMode(AcknowledgeMode.MANUAL);        // 手动确认
    container.setMessageListener((ChannelAwareMessageListener) (message, channel) -> {      //消息处理
        System.out.println("====接收到消息=====");
        System.out.println(new String(message.getBody()));
        if(message.getMessageProperties().getHeaders().get("error") == null){
        //第二个参数为消息是否重新入队,多消费者的时候可以设置为true
        channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            System.out.println("消息已经确认");
        }else {
            //channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,false);
            channel.basicReject(message.getMessageProperties().getDeliveryTag(),false);
            System.out.println("消息拒绝");
        }

    });
    return container;
}
或者在消费消息的代码上加上:
@RabbitHandler
public void processMessage2(String message,Channel channel,@Header(AmqpHeaders.DELIVERY_TAG) long tag) {
    System.out.println(message);
    try {
    //第二个参数为消息是否重新入队,多消费者的时候可以考虑设置为true
        channel.basicAck(tag,false);            // 确认消息
    } catch (IOException e) {
        e.printStackTrace();
    }
}

6.消息落库,对消息进行状态标记

分布式源码

dubbo的spi机制
Feign+Ribbon+Hystrix的原理

总结:@EnableFeignClients里有@Import(FeignClientsRegistrar.class),FeignClientsRegistrar实现了ImportBeanDefinitionRegistrar,导入了批量的bean,
registerBeanDefinitions--》registerFeignClients--》registerFeignClient,由此引入FeignClientFactoryBean,他是FactoryBean,注入的时候会调用getObject方法
getObject--》getTarget--》targeter.target--》不管哪个实现都会进入feign.target(target)
--》newInstance(target)--》factory.create(target, methodToHandler)--》匿名内部类的new InvocationHandlerFactory() 的create方法返回HystrixInvocationHandler,所以注入的对象最终会调用HystrixInvocationHandler的invoke方法,此方法组成HystrixCommand的run和
getFallback,其中run从Map<Method, MethodHandler> dispatch中根据method取到MethodHandler,其实现为SynchronousMethodHandler,并调用他的invoke方法

springboot应用启动扫描导入批量bean的流程
SpringApplication的run、refreshContext、refresh---》AbstractApplicationContext的refresh--》AbstractApplicationContext的invokeBeanFactoryPostProcessors(beanFactory)--》ConfigurationClassParser的processConfigurationClass---》ConfigurationClassParser的doProcessConfigurationClass--》ConfigurationClassParser的processImports

FeignClientsRegistrar深入分析
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
getObject方法深入分析
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

feign集成hystrix原理
集成ribbon原理
补充:从SynchronousMethodHandler的invoke方法看起
nacos实现原理

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值