面试稿·Java

面试稿·Java

  • 一、Java基础
    • 1、Java数据结构
    • 2、Java网络编程
      • 2.1 TCP&UDP
      • 2.2 Netty
        • 2.2.1 Netty项目
          • 2.2.1.1 Push(推) & Pull(拉)
    • 3、Java多线程
      • 3.1 Java并发基础(锁)
        • 3.1.1 多线程活跃性问题
        • 3.1.2 并发级别
        • 3.1.3 同步控制
          • 3.1.3.1 可重入锁
        • 3.1.4 锁优化
          • 3.1.4.1 偏向锁
          • 3.1.4.2 自旋锁
          • 3.1.4.3 锁消除
      • 3.2 JDK并发包(J.U.C)
        • 3.2.1 线程复用:线程池
        • 3.2.2 自定义线程池
          • 3.2.2.1 合理的线程池大小
        • 3.2.3 并发容器
          • 3.2.3.1 BlockingQueue
      • 3.3 并行模式&算法
      • 3.4 Java8并发(CompletableFuture)
      • 3.5 使用建议
    • 4、Java虚拟机
      • 4.1 内存管理
      • 4.2 引用
      • 4.3 GC详解
      • 4.4 性能调优
    • 5、Java8新特性
      • 5.1 Java8接口新特性
      • 5.2 Java8注解新特性
      • 5.3 HashMap源码 JDK1.7 vs JDK1.8
      • 5.4 Java8其他新特性:函数式接口、方法引用
  • 二、Spring·前后端分离架构
    • 1、Spring
      • 1.1 Spring 编程模型
      • 1.2 Spring FrameWork 有哪些核心模块?
      • 1.3 Spring IOC
        • 1.3.1 什么是IOC
        • 1.3.2 BeanFactory 和 FactoryBean 有什么区别
        • 1.3.3 BeanFactory 和 ApplicationContext有什么区别
        • 1.3.4 @Autowired 与 @Resource有什么区别
        • 1.3.5 延迟加载的好处
        • 1.3.6 Spring IOC 生命周期
      • 1.4 Spring MVC
        • 1.4.1 Controller
          • 1.4.1.1 @RequestMapping
          • 1.4.1.2 JSR-303(Spring数据校验)
        • 1.4.2 RESTful
        • 1.4.3 View
      • 1.5 Spring AOP
        • 1.5.1 什么是AOP
        • 1.5.2 JDKDynamicAopProxy
        • 1.5.3 AOP 日志
    • 2、MyBatis
      • 2.1 MyBatis 类图
      • 2.2 MyBatis-Spring
        • 2.2.1 MyBatis 常用配置
      • 2.3 MyBatis-Plus
      • 2.4 CRUD 项目
        • 2.4.1 MyBatis注解方式(一般不介意使用)
        • 2.4.2 MyBatis代码生成器
        • 2.4.3 MyBatis二级缓存
          • 2.4.3.1 EhCache
      • 2.5 Spring 事务
        • 2.5.1 ACID
        • 2.5.2 隔离级别
        • 2.5.3 SpringBoot 统一配置
        • 2.5.4 传播行为
    • 3、Spring Data JPA
      • 3.1 JPA 类图
      • 3.2 CRUD 项目
    • 4、MyCat
    • 5、Redis(分布式缓存共享)
      • 5.1 高级功能
        • 5.1.1 持久化
        • 5.1.2 Redis的淘汰策略
      • 5.2 多级缓存项目(EhCache、Redis)
        • 5.2.1 SpringBoot 统一配置
        • 5.2.2 主从、哨兵、集群
        • 5.2.3 Redis缓存
    • 6、ElasticSearch
    • 7、消息中间件 MQ
      • 7.1 Rabbit MQ
        • 7.1.1 使用场景
        • 7.1.2 AMQP~Exchange
        • 7.1.3 高级功能
          • 7.1.3.1 发送方确认机制(confirm)
          • 7.1.3.2 如何避免消息重复投递或重复消费
          • 7.1.3.3 失败通知机制(return)
          • 7.1.3.3 消费者限流
          • 7.1.3.3 TTL & 死信队列(DLX)
          • 7.1.3.4 延迟队列
        • 7.1.4 RabbitMQ 项目(可靠性传输)
          • 7.1.4.1 SpringBoot 统一配置
      • 7.2 Kafka
        • 7.2.1 讲讲Kafka 维护消费状态跟踪的方法(Kafka分区)
    • 8、Vue
    • 9、Spring Security
      • 9.1 OAuth2
    • 10、Swagger
    • 11、Spring5 WebFlux

一、Java基础

1、Java数据结构

2、Java网络编程

2.1 TCP&UDP

面试稿·Java_第1张图片
面试稿·Java_第2张图片

2.2 Netty

2.2.1 Netty项目
2.2.1.1 Push(推) & Pull(拉)

Pull 模式的另外一个好处是 consumer 可以自主决定是否批量的从 broker 拉取数据。Push 模式必须在不知道下游 consumer 消费能力和消费策略的情况下决定是立即推送每条消息还是缓存之后批量推送。如果为了避免 consumer 崩溃而采用较低的推送速率, 将可能导致一次只推送较少的消息而造成浪费。Pull 模式下, consumer 就可以根据自己的消费能力去决定这些策略。

Pull 有个缺点是,如果 broker 没有可供消费的消息,将导致 consumer 不断在循环中轮询,直到新消息到 t 达。为了避免这点,Kafka 有个参数可以让 consumer 阻塞知道新消息到达(当然也可以阻塞知道消息的数量达到某个特定的量这样就可以批量发送)。

3、Java多线程

3.1 Java并发基础(锁)

3.1.1 多线程活跃性问题
  • 死锁(一个山上的景区,只有一天路,一辆车要上山去景区、一辆车逛完了要下山离开景区,两车互不相让)
  • 活锁(互相谦让)
  • 饥饿锁(低优先级线程一直拿不到资源,无法正常工作)
3.1.2 并发级别
  • 阻塞(synchronized和可重入锁)
  • 无饥饿(公平锁)
  • 无障碍(乐观锁)
  • 无锁(原子类、Disruptor)
  • 无等待()
3.1.3 同步控制
3.1.3.1 可重入锁

lock、unlock、tryLock(限时等待)

3.1.4 锁优化
3.1.4.1 偏向锁
-XX:+UseBiasedLocking
3.1.4.2 自旋锁
3.1.4.3 锁消除
-XX:+DoEscapeAnalysis
-XX:+EliminateLocks

3.2 JDK并发包(J.U.C)

3.2.1 线程复用:线程池
  • FixedThreadPool(固定数量线程池)
  • CachedThreadPool
  • ScheduledThreadPool
  • SingleThreadExecutor(只有一个线程的线程池)
  • SingleThreadScheduledExecutor(只有一个线程且周期性定时执行某任务的线程池)
3.2.2 自定义线程池
public ThreadPoolExecutor(
	int corePoolSize, //线程数量
	int maximumPoolSize, //最大线程数量
	long keepAliveTime, //空闲线程存活时间
	TimeUnit unit, //时间单位
	BlockingQueueRunnable> workQueue, //任务队列
	ThreadFactory threadFactory, //线程工厂
	RejectedExecutionHandler handler //拒绝策略)
3.2.2.1 合理的线程池大小
  • 合理的线程池大小:
  • I/O密集型:CPU核数 *(1+I/O耗时/CPU耗时)amp工具
  • CPU密集型:CPU核数 + 1
Runtime.getRuntime().availableProcessors()
3.2.3 并发容器
3.2.3.1 BlockingQueue

ArrayBlockingQueue、LinkedBlockingQueue、PriorityBlockingQueue

3.3 并行模式&算法

3.4 Java8并发(CompletableFuture)

面试稿·Java_第3张图片
在这里插入图片描述

3.5 使用建议

面试稿·Java_第4张图片

4、Java虚拟机

4.1 内存管理

面试稿·Java_第5张图片
面试稿·Java_第6张图片

  • 虚拟机的分代回收,又分为新生代(Eden、S0、S1)和老年代。对新生代的回收为Minor GC,对老年代的回收为Major GC。
  • Stop The World:清理时暂停其他工作线程。

4.2 引用

  • 强引用:大部分场景都是强引用
  • 软引用:缓存(内存不足即回收)
  • 弱引用:缓存(发现即回收)
  • 虚引用:对象的回收跟踪

4.3 GC详解

4.4 性能调优

  • CPU(线程上下文切换、频繁GC,解决方案:使用线程池、减少线程数量及线程间的切换)
  • 内存(合理设置各个代的大小、选择合适的GC策略)
  • I/O(异步代替同步、尽量批量写入、减少IO次数)
    面试稿·Java_第7张图片

5、Java8新特性

5.1 Java8接口新特性

在Java8中,可以为接口添加 静态方法 和 默认方法

  • 实现类不能调用接口中的 静态方法、只能通过接口调用
  • 实现类可以 调用和重写 接口中的 默认方法
  • 实现类同时继承了一个有与接口同名同参的 默认方法 的父类、根据类优先原则、在子类没有重写该方法时、默认调用父类的方法

5.2 Java8注解新特性

在Java8中,注解方面新增了 可重复注解 和 类型注解

5.3 HashMap源码 JDK1.7 vs JDK1.8

底层结构有变化、JDK1.8中HashMap的底层结构是:数组+链表+红黑树

5.4 Java8其他新特性:函数式接口、方法引用

Lambda表达式、Stream API

二、Spring·前后端分离架构

1、Spring

1.1 Spring 编程模型

Spring FrameWork 一共涉及到5种编程模型、面向对象的编程模型(接口、对象、设计模式)、面向切面的编程模型(动态代理、字节码提升)、注解驱动的编程模型、事件驱动的编程模型、模块驱动的编程模型

1.2 Spring FrameWork 有哪些核心模块?

spring-core(资源管理、泛型处理)、spring-beans(依赖注入)、spring-context(注解驱动、事件驱动、模块驱动)、spring-webmvc(Servlet)、spring-aop(动态代理、字节码提升)

1.3 Spring IOC

1.3.1 什么是IOC

Spring管理Bean的容器

1.3.2 BeanFactory 和 FactoryBean 有什么区别

BeanFactory是一种Spring IOC的容器
FactoryBean是创建Bean的一个工厂方法

1.3.3 BeanFactory 和 ApplicationContext有什么区别

ApplicationContext是BeanFactory的一个子接口,在BeanFactory上进行了很多扩展、比如扩展了消息国际化(MessageSource)、环境可配置(EnvironmentCapable)、应用事件发布(ApplicationEventPublisher)和资源模式解析(ResourcePatternResolver)等

1.3.4 @Autowired 与 @Resource有什么区别

IOC容器中允许按照名字或类型获取Bean
@Autowired根据类型进行注入、@Resource根据名字注入
@Primary 和 @Quelifier 消除歧义 配合@Autowired使用
@Primary(优先)、@Quelifier(限定)有参数的构造方法装配

1.3.5 延迟加载的好处

没有在SpringIoC容器初始化时就执行了Bean的实例化和依赖注入。

1.3.6 Spring IOC 生命周期

读取和解析配置元信息(通过BeanDefinition可以注册)、启动Spring上下文、实例化Bean、依赖注入(初始化Bean)、(Bean生存期)关闭Spring上下文(销毁Bean)
BeanNameAware , BeanFactoryAware, ApplicationContextAware, InitializingBean, DisposableBean

1.4 Spring MVC

  • ApplicationContext初始化时用Map保存所有URL和Controller类的对应关系。
  • 根据请求URL找到对应的Controller,并从Controller中找到处理请求的方法。
  • 将Request参数绑定到方法的形参上,执行方法处理请求,并返回结果视图。
  • 主要有DispatcherServlet、视图解析器(ViewResolver)和处理适配器(HandlerAdapter)
    面试稿·Java_第8张图片
  • DispatcherServlet是前端控制器,主要负责接收Request并将Request转发给对应的处理组件。
  • HandlerMapping主要完成URL到Controller映射的组件。
  • Controller主要处理Request,并返回ModelAndView对象。
  • ④、⑤、⑥是视图解析器解析ModelAndView对象并返回对应的视图给客户端的过程。
1.4.1 Controller

mv.setViewName("")
面试稿·Java_第9张图片

1.4.1.1 @RequestMapping

把请求的URL和控制器的方法相对应

1.4.1.2 JSR-303(Spring数据校验)

面试稿·Java_第10张图片

1.4.2 RESTful
1.4.3 View
spring.mvc.view.prefix=/WEB-INF/jsp/
spring.mvc.view.suffix=.jsp

1.5 Spring AOP

1.5.1 什么是AOP

面向切面编程(目标增强、约定大于配置)、主要用在日志、事务、安全等方面,底层原理是动态代理

1.5.2 JDKDynamicAopProxy
  • 创建目标对象、
  • 创建代理对象Proxy.newProxyInstance(),传三个参数,目标类加载器(.getClass().getClassLoader())、目标类接口数组(.getClass().getInterfaces())、处理器类(new InvocationHandler())
  • 创建一个匿名内部类,或者类实现InvocationHandler接口,重写invoke方法,对调用的目标方法进行增强(invoke方法有三个参数,Object proxy, Method method, Object[] args)
  • method指的是代理对象调用的方法、args是代理对象调用方法时传的参数
  • 通过代理对象调用方法
1.5.3 AOP 日志

2、MyBatis

Hibernate是全映射框架,在以管理系统为主的时代,它的模型化十分有利于公司业务的分析和理解,但是在近年兴起的移动互联网时代,这样的模式却走到了尽头。Hibernate的模式重模型和业务分析,移动互联网虽然业务相对简单,但却更关注大数据和大并发下的性能问题。全表映射规则下的Hibernate已无法满足SQL优化和互联网灵活多变的业务。

2.1 MyBatis 类图

面试稿·Java_第11张图片
StatementHandler(数据库会话器)、ParameterHandler(参数处理器)、ResultHandler(结果处理器)

2.2 MyBatis-Spring

2.2.1 MyBatis 常用配置
#定义Mapper的XML路径
mybatis.mapper-locations=

#定义别名扫描的包,需要与@Alias联合使用
mybatis.type-aliases-package=

#MyBatis配置文件,当你的配置比较复杂的时候,可以使用它
mybatis.config-location=

#配置MyBaits插件(拦截器)
mybatis.configuration.interceptors=

#具体类需要与@MappedJdbcTypes联合使用
mybatis.type-handlers-package=

#级联延迟加载属性配置
mybatis.configuration.aggressive-lazy-loading=

#执行器(Executor〕,可以配置SIMPLE、REUSE、BATCH,默认为SIMPLE
mybatis.executor-type=

2.3 MyBatis-Plus

2.4 CRUD 项目

2.4.1 MyBatis注解方式(一般不介意使用)
2.4.2 MyBatis代码生成器

<dependency>
    <groupId>org.mybatis.generatorgroupId>
    <artifactId>mybatis-generator-coreartifactId>
    <version>1.3.7version>
dependency>

generatorConfig.xml
面试稿·Java_第12张图片

2.4.3 MyBatis二级缓存

面试稿·Java_第13张图片
面试稿·Java_第14张图片

2.4.3.1 EhCache

ehcache.xml


<Cache  name="simpleCache"      缓存的名字
                maxElementsInMemory="10000"  内存中最大的对象数
                eternal="false"   对象是否永久存活
                timeToIdleSeconds="120"  当缓存闲置n秒后销毁
                timeToLiveSeconds="120"  当缓存存活n秒后销毁
                overflowToDisk="true"  当大小超过memory的大小时,可以缓存到本地硬盘
                maxElementsOnDisk="10000000"  硬盘上最大的对象数
                diskPersistent="false"      是否在硬盘上持久化保存
                diskExpiryThreadIntervalSeconds="120"  
                memoryStoreEvictionPolicy="LRU"  内存清除对象的方式
                />

面试稿·Java_第15张图片

2.5 Spring 事务

2.5.1 ACID
  • Atomic(原子性):事务中包含的操作被看作一个整体的业务单元,这个业务单元中的操作要么全部成功,要么全部失败,不会出现部分失败、部分成功的场景。
  • Consistency(一致性):事务在完成时,必须使所有的数据都保持一致状态,在数据库中所有的修改都基于事务,保证了数据的完整性。
  • Isolation(隔离性):多个线程同时访问同一数据,这样数据就会在各个不同的事务中被访问,会产生丢失更新。为了解决这个问题,数据库定义了隔离级别的概念。
  • Durability(持久性):事务结束后,所有的数据会固化到一个地方,如保存到磁盘当中,即使断电重启后也可以提供给应用程序访问。
2.5.2 隔离级别
  • Spring事务管理器里的隔离级别有:数据库默认的隔离级别、未提交读、读写提交、可重复读和串行化五种。
  • 其中,数据库默认的隔离级别,Oracle的默认级别是读写提交、MySql的默认级别是可重复读。
  • 未提交读(READ_UNCOMMITTED)是最低的隔离级别,它的意思是允许一个事务读取另外一个事务没有提交的数据。
  • 读写提交(READ_COMMITTED)隔离级别,是指一个事务只能读取另外一个事务已经提交的数据,不能读取未提交的数据。
  • 可重复读(REPEATABLE_READ)是克服读写提交中出现的不可重复读的现象,因为在读写提交的时候,可能出一些值的变化,影响当前事务的执行。
  • 串行化(SERIALIZABLE)按顺序执行、完全保证数据一致性。
    面试稿·Java_第16张图片
  • 脏读:一个事务对数据进行了增、删、改,但未提交,另一个事务可以读取到未提交的数据。如果第一个事务这时候回滚了,那么第二个事务就读到了脏数据。
  • 不可重复读:一个事务中发生了两次读操作,在第一次读操作和第二次读操作之间,另外一个事务对数据进行了修改,这时候两次读取的数据是不一致的。
  • 幻读:第一个事务对一定范围的数据进行了批量修改,第二个事务在这个范围内增加了一条数据,这时候第一个事务就会丢失对新增数据的修改。
2.5.3 SpringBoot 统一配置
  • 事务只能运用在那些低井发而又需要保证数据一致性的场景下。对于高井发下又要保证数据一致性的场景,则需要另行处理了。
# 隔离级别数字配置的含义
#-1 据库默认隔离级别
# 1 未提交读
# 2 读写提交
# 4 可重复读
# 8 串行化

# tomcat数据源默认隔离级别
spring.datasource.tomcat.default-transaction-isolation=2
2.5.4 传播行为

面试稿·Java_第17张图片

3、Spring Data JPA

JPA是一种规范,是JSR-220规范的一部分。

3.1 JPA 类图

3.2 CRUD 项目

4、MyCat

5、Redis(分布式缓存共享)

5.1 高级功能

5.1.1 持久化

Redis 提供两种持久化机制 RDB 和 AOF 机制

持久化机制 含义 优点 缺点
RDB(Redis DataBase) 把数据写入一个临时文件, 持久化结束后, 用这个临时文件替换上次持久化的文件, 达到数据恢复。 RDB模式 是让主进程继续处理命令,使用单独子进程来进行持久化,主进程不会进行任何 IO 操作,保证了 Redis 的高性能 RDB模式 是隔一段时间进行一次持久化,如果持久化之前 Redis 发生了故障, 会发生数据的丢失。所以这种方式更适合数据要求不严格的时候
AOF(Append-Only File) 把每次Redis命令追加写入日志文件中 跟 RDB模式 相比,当发生故障时,丢的少了 AOF 文件比 RDB 文件大, 且恢复速度慢。
5.1.2 Redis的淘汰策略
策略 含义
volatile-lru 从已设置过期时间的数据集中挑选最近最少使用的数据淘汰
volatile-ttl 从已设置过期时间的数据集中挑选将要过期的数据淘汰
volatile-random 从已设置过期时间的数据集中随机选择数据进行淘汰
allkeys-lru 从所有数据集中挑选最近最少使用的数据淘汰
allkeys-random 从所有数据集中随机选择数据进行淘汰
no-enviction 永不回收策略

使用策略规则:

1、如果数据呈现幂律分布,也就是一部分数据访问频率高,一部分数据访问频率低, 则使用 allkeys-lru

2、如果数据呈现平等分布, 也就是所有的数据访问频率都相同, 则使用allkeys-random

5.2 多级缓存项目(EhCache、Redis)

5.2.1 SpringBoot 统一配置
# 配置连接池属性
spring.redis.jedis.pool.min-idle=5
spring.redis.jedis.pool.max-active=10
spring.redis.jedis.pool.max-idle=10
spring.redis.jedis.pool.max-wait=2000

# 配置Redis服务器属性
spring.redis.port=6379
spring.redis.host=192.168.11.131
spring.redis.password=123456

# Redis连接超时时间,单位毫秒
spring.redis.timeout=1000

# 日志配置为DEBUG级别,这样日志最为详细
logging.level.root=DEBUG
logging.level.org.springframework=DEBUG
logging.level.org.org.mybatis=DEBUG

#缓存配置
spring.cache.type=REDIS
spring.cache.cache-names=redisCache
5.2.2 主从、哨兵、集群

Redis Sentinal 着眼于高可用, 在 Master 宕机时会自动将 Slave 提升为Master, 继续提供服务。

Redis Cluster 着眼于扩展性, 在单个 redis 内存不足时, 使用 Cluster 进行分片存储。

Redis 集群有16384 个哈希槽,每个 key 通过 CRC16 校验后对 16384 取模来决定放置哪个槽, 集群的每个节点负责一部分 hash 槽。

5.2.3 Redis缓存
@EnableCaching //启动类上添加开启缓存注解
@Cacheable //需要缓存的方法上添加
@CacheEvict //Delete时也清除缓存
# 禁用前缀
spring.cache.redis.use-key-prefix=false
# 允许保存空值
#spring.cache.redis.cache-null-values=true
# 自定义前缀
#spring.cache.redis.key-prefix=
# 定义超时时间,单位毫秒
spring.cache.redis.time-to-live=600000

面试稿·Java_第18张图片

6、ElasticSearch

7、消息中间件 MQ

7.1 Rabbit MQ

7.1.1 使用场景
  • 服务间异步通信(异步解耦)
  • 分布式事务(消息发送重试、消息消费重试、死信监听告警)
  • 定时任务(延时队列)
  • 请求削峰(业务高峰期缓冲)
7.1.2 AMQP~Exchange
  • Rabbit MQ从消息发布方到消息消费方,需要经过Exchange(分拨中心)和Queue(取件点)。
  • Exchange根据绑定关系(Binding)和路由键routingKey(快递地址)转发消息到相应队列。
    面试稿·Java_第19张图片
7.1.3 高级功能
7.1.3.1 发送方确认机制(confirm)

waitforconfirms

7.1.3.2 如何避免消息重复投递或重复消费

在消息生产时, MQ 内部针对每条生产者发送的消息生成一个 inner-msg-id, 作为去重的依据( 消息投递失败并重传), 避免重复的消息进入队列;

在消息消费时,要求消息体中必须要有一个 bizId( 对于同一业务全局唯一,如支付 ID、订单 ID、帖子 ID 等) 作为去重的依据, 避免同一条消息被重复消费。

7.1.3.3 失败通知机制(return)
  • RabbitTemplate.ReturnCallback重写returnedMessage方法
7.1.3.3 消费者限流
spring.rabbitmq.listener.simple.prefetch = 1
7.1.3.3 TTL & 死信队列(DLX)

信息成为死信的原因:

  • 消费者拒收,重写basicNack方法、并将消息不放回原队列
  • 消息设置了超时时间,然后超过了超时时间,就到了死信队列
  • 队列达到了最大长度
7.1.3.4 延迟队列
7.1.4 RabbitMQ 项目(可靠性传输)

面试稿·Java_第20张图片

7.1.4.1 SpringBoot 统一配置
  • 消息生产者:
# RabbitMQ服务器地址
spring.rabbitmq.host=localhost
# RabbitMQ端口
spring.rabbitmq.port=5672
# RabbitMQ用户
spring.rabbitmq.usernarne=admin
#RabbitMQ密码
spring.rabbitmq.password=l23456
#是否确认发送的消息已经被消费
spring.rabbitmq.publisher-confirms=true
# RabbitMQ的消息队列名称,由它发送字符串
rabbitmq.queue.msg=spring-boot-queue-msg
# RabbitMQ的消息队列名称,由它发送用户对象
rabbitmq.queue.user=spring-boot-queue-user
  • 消息消费者:
spring.rabbitmq.listener.direct.acknowledge-mode=manual
spring.rabbitmq.listener.direct.prefetch=100
	@RabbitListener(queues = 队列名)
	@RabbitHandler
    public void receiveDeadMsg(String msg, Channel channel, Message messages) throws Exception {
        try {
            业务代码...
            // 回发ack,第二个参数multiple,表示是否批量确认,具体请百度,不赘述
            channel.basicAck(messages.getMessageProperties().getDeliveryTag(), false);
        } catch (Exception e) {
            // 回发Nack,且重回队列为false,防死循环
            channel.basicNack(messages.getMessageProperties().getDeliveryTag(), false, false);
        }
    }
  • https://blog.csdn.net/weixin_44367006/article/details/105404218(RabbitTemplate封装类)
  • https://blog.csdn.net/qq_37892957/article/details/89296157(RabbitMQ延迟队列)

7.2 Kafka

7.2.1 讲讲Kafka 维护消费状态跟踪的方法(Kafka分区)

大部分消息系统在 broker 端的维护消息被消费的记录:也就是一个消息被分发到 consumer 后 broker 就马上进行标记或者等待 customer 的通知后进行标记。这样也可以在消息在消费后立马就删除以减少空间占用。

一条消息发送出去之后就立即被标记为消费过的, 一旦 consumer 处理消息时失败了( 比如程序崩溃) 消息就丢失了。

为了解决这个问题, 很多消息系统提供了另外一个个功能: 当消息被发送出去之后仅仅被标记为已发送状态, 当接到 consumer 已经消费成功的通知后才标记为已被消费的状态。

这虽然解决了消息丢失的问题,但产生了新问题,首先如果 consumer 处理消息成功了但是向 broker 发送响应时失败了,这条消息将被消费两次。第二个问题时, broker 必须维护每条消息的状态, 并且每次都要先锁住消息然后更改状态然后释放锁。这样麻烦又来了, 且不说要维护大量的状态数据, 比如如果消息发送出去但没有收到消费成功的通知, 这条消息将一直处于被锁定的状态,

Kafka 采用的策略就是分区。把 Topic 分成了若干分区,每个分区在同一时间只被一个 consumer 消费。即使用 offset 来标记每个分区消费状态。

8、Vue

9、Spring Security

spring.security.user.name=myuser
spring.security.user.password=l23456

9.1 OAuth2

10、Swagger

面试稿·Java_第21张图片

11、Spring5 WebFlux

面试稿·Java_第22张图片
面试稿·Java_第23张图片
在这里插入图片描述
面试稿·Java_第24张图片

你可能感兴趣的:(Java,2021)