java开发核心面试题
说一下项目中那些场景使用了redis缓存穿透击穿雪崩缓存击穿添加一个分布式锁只能有一个线程拿到锁和钱相关必须强一致选互斥锁逻辑过期重要是高可用不保证数据的一致性双写一致Mysql的数据如何与redis进行同步双写一致两种方案要根据项目来选第一种延时双删先删除缓存还没有更新数据库20这个时候有另外一个数据进来查询缓存没有查到就去数据库里查到之前的数据10先操作数据线程2还没有更新数据库20这个时候线程1查询数据10写入缓存10线程2更新数据20导致数据不一致出现脏数据两种 情况都会导致脏数据所以数据修改之后再删除一次缓存为什么要延时数据库可能是主从节点需要延时一会让数据从主节点复制到从节点延时双删的时间不好控制还是可能会导致脏数据第二种方案 使用读写锁读的时候使用共享锁可以读不能写写的时候使用排他锁会阻塞其他线程读和写的操作相比分布式锁性能高一点可以保证强一致但是性能低异步通知保证数据的最终一致性redis的持久化第一种方式 RDB推荐使用子进程这样不会影响其他命令在linux中所有的主进程都无法直接操作物理内存由操作系统给每个主进程分配一个虚拟内存操作系统会维护一下虚拟内存和物理内存中间的映射关系表页表主进程通过页表对物理内存进行读操作fork是克隆fork子进程就是把主进程的页面复制过去这样就和主进程有了相同的映射关系这样就实现了主进程和子进程内存空间的共享这样就无需拷贝内存中的数据了直接实现内存共享这样子进程就可以写新的RDB文件。怎么避免在写文件的时候有新的写操作导致数据不一致fork采用copy-on-write技术有写操作就把数据拷贝把数据写进去读的数据对应的映射也会改变第二种 AOF会把无效的命令重写最大的节省命令行数reids的过期策略reids数据淘汰策略redis内存使用完之后会报错out of memory,中止服务读操作可以写操作不行分布式锁给锁续期一开始给锁设置了过期时间然后再开另外一个线程来看业务到底执行了多久如果执行时间长就增加持有锁的时长这种就需要使用到redisson使用redisson,watchdog会续期抢不到锁的线程会尝试等待加锁和设置过期时间等操作都是基于lua脚本的lua脚本可以调用linux命令来保证多条命令执行的原子性当设置了过期时间30之后watchdog就没有了redisson认为你可以自己控制时间就不给你续期了10是while循环的时间redis实现的分布式锁不能重入redisson实现的分布式锁可重入同一个线程内不同线程就是互斥了没有使用红锁的话当一个服务挂了之后同一个锁可能就被不同的线程拿到了Redis是单线程为什么还这么快IO多路复用就是用来监听多个客户端的连接Mysqlsql优化sql优化Mysql中如何定位慢查询表数据量大可以添加索引怎么看索引是否失效呢可以通过EXPLAINPRIMARY是主键如果Extra 是using index condition 表示索引还有优化的空间索引1.写sql创建sql范本create index 索引名称 on 表名(字段名);sql示例create index index_user_name on PROMULGATE_CERT(user_name);没有索引的时候查找age是45的人sql执行会从第一行一个一个找找到最后一行B树特点非叶子节点不存储数据只存储指针这些指针是为了方便找到数据只在叶子节点保存数据主键索引是聚族索引1 是主键索引也是聚族索引可以从索引中一次查询出所有的数据索引创建的原则索引失效name status address 是有顺序的查询要从最左边开始key 和key_len 是null 索引已经失效了最下面的这个key_len是303跟只查询name时候的key_len是一样都是303表示只命中了name的索引查询的时候后面的address是跳过status的没有命中Sql的优化经验选择合适的数值可以减少存储的成本提高查询的效率Mysql 事务加钱和减钱的操作要么成功要么失败并发事务带来的问题串行话效率很低一般是不会用的主库负责写数据从库负责读数据主库写数据之后要把数据同步到从库Springspring 单例bean是线程安全的吗AOP事务就是使用的aop项目中使用AOP记录日志spring 中事务失效的场景非检查异常有IOException,SQLException,ClassnotFoundException检查异常运行时异常RuntimeException,NullpointerException,ArrayIndexOutofBoundExceptionspring 的bean的生命周期spring中的循环依赖SpringMVC的执行流程springboot自动配置原理spring中常见的注解mybatis执行流程Mybatis的一级二级缓存二级缓存默认是关的开启之后同一个线程内两个sqlSessionFactory查一个sql只会连接数据库查询一次Spring Cloud服务降级针对的是某个接口服务熔断针对的是整个服务微服务是怎么监控的一般shywalking来监控项目中怎么做限流的tomcat在单体项目中可以微服务就不行了公司压测之后业务的qps是1200CAP和BASE比如提交订单提交多次也只能有一个订单使用token和redids,在点击购买的时候去获取token,然后返回一个token,有了token之后请求业务接口提交订单的页面验证token存在之后删除token其他请求进来没有token就打不开提交订单的页面使用分布式锁保证只有一个线程可以拿到锁进行业务的操作项目中使用的分布式任务调度消息中间件生产者发生消息到交换机交换机把消息路由到队列然后消费者消费消息消息未到达交换机怎么解决消息未到达对列怎么解决消费者未收到消息RabbitMq消息重复消费的问题如何解决当消费者消费完消息这个时候消费挂了确认的消息还没有回给生产者因为有超时重试机制消费者会再次消费消息导致重复消费的问题。每个消息设置一个唯一id我们消费的时候去数据库看如果没有这个id就正常消费如果有了就不再消费这个消息了消息堆积怎么解决集合算法复杂度分析来评估代码的执行耗时的3n3 前一个三是系数第二个三是常量这两个三都不能反映变化趋势所以可以省略不管底数是2还是10复杂度都是lognList相关多线程线程的基础线程中并发安全加锁之后使用monitorenter上锁把这段代码锁住等解锁之后其他代码才能执行这段代码第二次解锁是怕出现异常之后也能解锁JMMAQSRentrantLock导致并发程序出现问题的根本原因原子性保证一段代码要么全部执行完成要么全部执行失败内存可见性可以使用三种方案解决但是volatile的方法效率高线程池的核心参数核心参数详解线程池的种类有哪些异步线程打印平台请求进来保存json请求报文使用异步线程常常用于限流ThreadLocalJVM什么是程序计数器JAVA堆元空间就是方法区程序计数器Program Counter Register当前线程所执行的字节码的行号指示器字节码解析器的工作是通过改变这个计数器的值来选取下一条需要执行的字节码指令分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器来完成Java 虚拟机栈Java Virtual Machine Stacks用于存储局部变量表、操作数栈、动态链接、方法出口等信息本地方法栈Native Method Stack与虚拟机栈的作用是一样的只不过虚拟机栈是服务 Java 方法的而本地方法栈是为虚拟机调用 Native 方法服务的Java 堆Java HeapJava 虚拟机中内存最大的一块是被所有线程共享的几乎所有的对象实例都在这里分配内存方法区Methed Area用于存储已被虚拟机加载的类信息、常量、静态变量、即时编译后的代码等数据。Java1.8把方法区和永久代放到了本地内存的元空间因为元空间中保存类信息和静态变量随着代码加载这些类信息不可控放在堆空间中容易内存溢出为了避免OOM所以优化之后放在了本地内存虚拟机栈方法区1.7以前是在堆中的永久代保存类的信息1.8以后移到了本地内存中的方法区元空间类加载器bootstrap classloader 启动类加载器string一直委派到启动类加载器启动类加载器可以加载这个类则由启动类加载器加载stutdent类 委派到启动类加载器也没有被加载那么应用类加载器就会加载这个类类装载的执行过程垃圾回收对象什么时候可以被垃圾回收器回收demo指向一个对象ref就是1表面被引用了一次如果 string demo null; 那么ref就是0表示可以被回收垃圾回收算法有哪些先标记存活的对象然后清除其他的对象jvm中的分代回收当新生代和老年代内存严重不足的时候才会产生FullGCJVM有哪些垃圾回收器GC root是可达性算法标记哪些对象是存活的软引用GC root先能找到softReference对象软引用对象user对象是一个软引用进行垃圾回收之后如果内存不足再次触发垃圾回收就会回收user对象JVM实践JVM调优的参数在哪里设置参数JVM调优的参数有哪些JVM 调优工具Java内存泄漏的排查思路一些大的对象一直存活垃圾回收器一直没有回收就会导致堆空间内存泄漏CPU飙高排查方案和思路设计模式冒号后面是方法的返回值这样实现耦合比较严重更换对象的时候new的对象也都要更换要实现开闭原则扩展开放对修改关闭简单工厂模式工厂方法模式简单工厂又产生了新的耦合后期如果有新的产品还是要修改simplecoffefactory类具体产品抽象工厂具体工厂抽象工厂模式策略模式登录案例 工厂加策略模式原来的登录方式不符合开闭原则使用工厂和策略模式让spring管理这些策略对象在工厂类中拿到配置文件中的值放到map中继承的applicationcontexAware接口就会实现setApplicationContext方法拿到applicationcontext对象拿到配置文件前面的account不能随便写要和前端写的type对应后面的accountGranter也不能随便写要根据这个在spring中找到对应spring管理的类责任链设计模式setNext是设置下一条执行的顺序在client中设置链条执行的顺序这是责任链中的最后一个方法不用调用下一个执行的方法复杂的流程审批会使用工作流来实现常见的技术场景单点登录权限认证上传数据的时候安全性怎么考虑项目中遇到的问题一开始写的代码没有使用设计模式后来需要经常更改代码很不方便后来我使用工厂模式和策略模式重构代码解决了这个问题线上bug,线下测试不方便复现项目上线一个月之后日志的采集怎么在linux中查看日志QPS是每秒查询率