
八股文
文章平均质量分 56
记录一些自己理解的白话八股文
apeiMark
这个作者很懒,什么都没留下…
展开
-
Kafka-Kafka 如何避免重复消费?
但是他与commitSync()不同的是,当他失败后会一直重试,假如发起了一个异步提交commitA,此时提交的偏移量为1000,随后又发起了一个异步提交commitB且偏移量为2000,如果commitA提交失败,但commit B提交成功,那么此时对commitA进行重试并成功的话,则会把实际上已经提交的偏移量从2000回滚到1000,导致重复消费。当有新的消费者进入或者消费者移除时,需要暂替当前消费者组中的所有消费者,并重新规划offset,这就称为再均衡。例如,在数据库操作时,可以使用。原创 2025-04-11 21:04:43 · 474 阅读 · 0 评论 -
JAVA并发-本地事务
用于设置不需要进行回滚的异常类名称数组,当方法中抛出指定异常名称数组中的异常时,不进行事务回滚。这意味着在事务的不同点上,如果其他事务修改了数据,你就会看到不同的数据。被外部调用的公共方法 A 声明事务 @Transactional,无论子方法 B 和 C 是不是本类的方法,无论子方法 B 和 C 是否声明事务,事务均由公共方法 A 控制。被外部调用的公共方法 A 声明事务 @Transactional,子方法运行异常,但运行异常被子方法自己 try-catch 处理了,则事务回滚是不会生效的!原创 2025-04-11 21:03:53 · 780 阅读 · 0 评论 -
消息队列基础面试题
确认模式【发布的所有消息分配唯一ID,消息投入指定队列成功,返回确认消息并包含唯一ID标识成功 - 异步】:普通确认模式【每一条消息调用waitForConfirms等待(穿行方式)】 = 》 简单时间长、批量确认模式【每发送一批调用waitForConfirms】 =》 考虑过多消息失败重传、异步确认模式【调用addConfirmListener注册回调】= 》维护尚未确认消息集合。镜像队列模式的话,就是在普通集群模式的基础上,将队列中的消息复制到多个节点,可以保证可靠性,但是增大网络开销和同步成本;原创 2025-04-11 21:02:26 · 822 阅读 · 0 评论 -
Java方法引用(::)深度解析
方法引用::是lambda表达式的一种简写形式,它不是调用方法,而是引用方法。编译器会根据上下文自动推断方法的调用方式。方法引用只是创建了一个方法指针,不会立即执行。:当lambda只是调用一个已有方法时,可以用。类名::new (构造方法)原创 2025-04-11 20:59:09 · 285 阅读 · 0 评论 -
深入理解 Java 中的 Function 接口
T:输入类型(参数类型)R:结果类型(返回类型)唯一抽象方法:R apply(T t)// 还包含两个默认方法(后面会讲解)super V,?super R,?T:输入参数类型核心方法:accept(T t) 执行操作特点:有输入无输出(与 Function 不同)// 核心抽象方法// 默认方法(组合操作)原创 2025-04-11 20:58:39 · 752 阅读 · 0 评论 -
Java Stream 手把手完整指南
想象你有一条传送带(Stream),上面放着各种物品(数据)。:使用原始类型流(IntStream, LongStream等)原料 → [筛选机] → [加工机] → [分拣机] → 成品。(中间操作) (中间操作) (中间操作) (终端操作):使用并行流 .parallelStream()操作是"懒加载"的(只有需要结果时才真正执行)筛选掉不需要的物品(filter)把物品装箱打包(collect)把物品加工成其他形态(map)统计物品数量(count)可以无限长(如无限序列):普通循环可能更高效。原创 2025-04-11 20:58:07 · 242 阅读 · 0 评论 -
一篇文章带你搞清楚23种设计模式(JAVA)
定义抽象类的接口,维护一个指向实现化角色的引用。原创 2025-04-11 20:57:23 · 1595 阅读 · 0 评论 -
JAVA并发-Callable
可以使用ExecutorService、Callable、Future实现有返回结果的线程,ExecutoreService提供了submit()方法,传递一个Callable,或Runnable,返回Future。Callable 接口类似于 Runnable,但是 Runnable 不会返回结果,并且无法抛出经过检查的异常,而 Callable 依赖 FutureTask 类获取返回结果。原创 2025-03-29 21:53:51 · 168 阅读 · 0 评论 -
Java并发-Runnable
Runnable接口是Java提供的一种用于实现多线程的接口,通常用来定义任务的具体逻辑。与Thread类不同,Runnable接口只提供一种抽象方法run(),没有任何与线程的生命周期、管理相关的功能。它的主要作用是与Thread类或线程池(如ExecutorService)配合,作为线程的任务载体,使任务与线程的执行分离,从而提高代码的灵活性和可维护性。Runnable接口直接继承自Object,没有复杂的继承关系。通过实现Runnable接口,可以将任务逻辑放入run()方法中,随后通过。原创 2025-03-29 21:53:20 · 316 阅读 · 0 评论 -
JAVA并发-Thread
正式因为没有内核的支持,所以通常来讲只会支持进程级别的资源分配,并且所有线程的生命周期需要用户程序自行处理,因此用户线程实现的程序也提高了复杂度和故障机率,Java中的线程曾经使用用户线程实现,最终由于其复杂度被放弃。所以当前应用程序内共有两个线程:主线程【普通线程】、Hook线程【普通线程】、子线程【守护线程】,所以当主线程结束后,应用程序内没有普通线程了,所以被设置为守护线程的子线程就停止执行了。在这段代码中,Hook线程的任务只是打印日志,当run()方法执行完毕(日志打印完成后),线程自然终止。原创 2025-03-29 21:52:40 · 1075 阅读 · 0 评论 -
JAVA并发-什么是指令重排?
指令重排是计算机编译器或处理器为了提高性能而对指令执行顺序进行的一种优化手段。在多核和多线程的计算机系统中,指令重排的目标是通过优化执行顺序来提高指令级别的并行度,充分发挥计算资源,加速程序的执行。原创 2025-03-29 21:49:07 · 251 阅读 · 0 评论 -
JAVA并发-ReentrantLock 与 synchronized的区别
可以实现多路选择通知(可以绑定多个 Condition),而 synchronized 只能通过 wait 和 notify/notifyAll 方法唤醒一个线程或者唤醒全部线程(单路通知);通常需要在 finally 块中调用 unlock 方法以确保锁被正确释放。在某些情况下,性能可能稍差一些,但随着 JDK 版本的升级,性能差距已经不大了。会自动释放锁,当同步块执行完毕时,由 JVM 自动释放,不需要手动操作。通常提供更好的性能,特别是在高竞争环境下。原创 2025-03-29 21:48:12 · 166 阅读 · 0 评论 -
场景-如何使用 JustAuth 集成第三方登录?
JustAuth插件网址:https://justauth.wiki组件的帮助文档:https://justauth.wiki组件的GitHub:GitHub - justauth/JustAuth: 🏆Gitee 最有价值开源项目 🚀:100: 小而全而美的第三方登录开源组件。目前已支持Github、Gitee、微博、钉钉、百度、Coding、腾讯云开发者平台、OSChina、支付宝、QQ、微信、淘宝、Google、Facebook、抖音、领英、小米、微软、今日头条、Teambition、StackO原创 2025-03-28 19:07:49 · 291 阅读 · 0 评论 -
Redis-解决缓存和数据库一致性问题
首先引入缓存就是为了提高客户端对数据的查询效率。最简单的方式就是全量数据刷到缓存中,一般是通过先将数据库的数据全量刷入缓存,不设置缓存失效时间。写请求只更新数据库,不更新缓存,启动一个定时任务定时将数据库的数据更新到缓存中。这样做有几个缺点:缓存利用率低:不经常访问的数据也存在缓存中,且不失效;数据不一致:因为是定时刷新,所以不一致的概率取决于定时时间。原创 2025-03-28 17:16:00 · 1544 阅读 · 0 评论 -
Java-Java修饰符
抽象类不能用来实例化对象,声明抽象类的唯一目的是为了将来对该类进行扩充。一个类不能同时被 abstract 和 final 修饰。如果一个类包含抽象方法,那么该类一定要声明为抽象类,否则将出现编译错误。原创 2025-03-27 17:13:12 · 926 阅读 · 0 评论 -
Java-浅拷贝与深拷贝
浅拷贝只拷贝目标对象,至于目标对象内部的引用类型指向的还是原对象;其中otherTeacher就是teacher的浅拷贝。深拷贝就是连带目标对象中的对象一起拷贝。原创 2025-03-27 17:11:21 · 193 阅读 · 0 评论 -
JVM-虚拟机类加载机制
以一组符号来描述所引用的目标;符号引用可以是任何形式的字面量,只要使用时能无歧义地定位到目标即可,符号引用和虚拟机无关;在编译的时候每个java类都会被编译成一个class文件,但。原创 2025-03-27 17:10:46 · 798 阅读 · 0 评论 -
Redis-如何基于Redis实现分布式锁?
基于redis实现分布式锁,可以通过SET NX命令,也就是当客户端需要申请锁的时候可以往redis尝试加入一个拥有唯一ID的锁变量,并通过EXPIRE设置过期时间,另外创建一个守护线程,定时检测锁的失效时间,如果锁快过期了,操作共享资源还没有完成,那么就自动对锁进行续期,重新设置过期时间;在完成对共享资源的操作后,通过编写Lua脚本判断是否为所属锁,并将其从redis删除以释放锁,释放操作具备原子性。【包括为什么要设置唯一ID等】原创 2025-03-26 11:23:12 · 112 阅读 · 0 评论 -
Redis-如果Redis分布式锁引用在redis集群应该怎么办?当出现主从切换时导致丢锁应该如何处理?
来解决,他的基本思路就是通过改用多个独立的redis服务器或者redis Cluster集群,在客户端获取锁时先计算当前时间,然后设置过期时间,并取其中比如几十毫秒用作获取锁的过期时间,在获取锁时会依次向独立服务器获取,如果过半数获取成功,并且获取时间小于设定的过期时间,那么获取成功,否则获取失败,无论成功与否最后会向所有redis服务器或者集群解除锁。另外redis普通分布式锁需要自己加唯一标识,在Redlock中则是通过。原创 2025-03-26 11:22:42 · 154 阅读 · 0 评论 -
场景-认证登录这块为什么用 JWT?
使用 Session 进行身份认证的话,实现单点登录,需要我们把用户的 Session 信息保存在一台电脑上,并且还会遇到常见的 Cookie 跨域的问题。但是,使用 JWT 进行认证的话, JWT自己包含了完整的认证授权信息,可以轻松实现跨域支持,并且这一点也使得再微服务架构中不需要可以维护会话状态的一致性,使得JWT也更加适应微服务架构。因此,即使你点击了非法链接发送了请求到服务端,这个非法请求也是不会携带 JWT 的,所以这个请求将是非法的。JWT还支持扩展和定制,可以灵活的完成其他业务功能。原创 2025-03-26 11:22:10 · 145 阅读 · 0 评论 -
场景-数据库直接保存的密码还是?
每次用给定的信息摘要查找字典,即可快速找到碰撞的结果。对于单机来说,暴力枚举法的时间成本很高(以14位字母和数字的组合密码为例,共有1.24×1025种可能,即使电脑每秒钟能进行10亿次运算,也需要4亿年才能破解),字典法的空间成本很高(仍以14位字母和数字的组合密码为例,生成的密码32位哈希串的对照表将占用5.7×1014 TB的存储空间)。因为不可逆MD5算法的hash算法是固定的,所以同一个字符串计算出来的hash串是固定的,可以采用暴力枚举法、字典法、彩虹表(rainbow)法等多种方式破解哈希。原创 2025-03-26 11:20:49 · 222 阅读 · 0 评论 -
场景-JWT无状态有什么问题考虑过吗?强制让用户下线怎么弄?
3.可以使用缓存创建一个Token黑名单,把客观上需要注销的token存入即可;2.注销时从客户端删除存储的token;1.合理的设置令牌过期时间;原创 2025-03-26 11:20:15 · 86 阅读 · 0 评论 -
JVM-GC
GC就是垃圾回收机制,其实像程序计数器、虚拟栈、本地方法栈等随线程而生,随线程而死,栈中的栈帧随着方法的进入和退出有条不紊的执行出栈和入栈的操作,每一个栈帧要分配多少内存也是在编译器就确定好了,尽管在运行期会有即时编译器进行一些优化,但基于概念模型我们还是可以认为他们在编译器就确定好了,但是Java堆和方法区不一样,一个接口的多个实现类的内存需求可能不一样,不同的条件分支所需的内存也可能不一样,所以只有在运行时我们才知道需要创建多少个对象。原创 2025-03-23 16:29:13 · 765 阅读 · 0 评论 -
JVM-JAVA内存区域与内存溢出异常
C/C++拥有着绝对的内存管理权限,但是也正因如此控制这些内存从无到有,再从有到无就异常繁琐。但是java不需要担心这些,他们把他全权交给了虚拟机去实现,也正因如此,如果你不了解java虚拟机,那么一旦出现了内存泄漏和溢出方面的问题,解决起来将会异常繁琐。原创 2025-03-22 11:08:57 · 1237 阅读 · 0 评论 -
专业名词-TPS和QPS
对于一次事务的访问对应一次‘T’,但是在事务中可能会进行其他访问服务器的请求,或多次对服务器的请求,所以可能对应多次QPS。每秒能够响应的查询次数,用于衡量特定的查询服务器在规定时间内所处理流量多少,主要针对专门用于查询的服务器的性能指标;一个事务是指客户端向服务器发送请求然后服务器做出反应的过程;每秒能返回N次以上结果,那么TPS就是N。原创 2025-03-20 17:23:17 · 196 阅读 · 0 评论 -
Redis-为什么考虑用redis做缓存
缓存的话一般可以采用本地缓存或者redis,其实按照查询效率来看,本地缓存直接基于本地其实要比redis这种缓存中间层效率要更高,但是存在一个问题是,既然是本地那么就只能存储在本地,而现在生产环境几乎都是集群式的,无法做到缓存的共享,如果一开始本地缓存最后又要改动成redis缓存所以何不一开始就交给专业的缓存层来处理。另外本地缓存没有redis的功能多样,redis有过期时间、淘汰机制、命中率统计等等,在处理复杂多变的业务场景时本地存储会使得业务代码更加臃肿。原创 2025-03-20 17:22:31 · 200 阅读 · 0 评论 -
源码接口-ApplicationContext
场景:当需要根据运行时条件动态获取特定Bean时(例如根据配置切换实现类)。场景:读取配置文件、国际化资源等。动态获取Bean实例。原创 2025-03-20 17:21:51 · 205 阅读 · 0 评论 -
源码接口-Serializable
另外实现该接口官方显式推荐用private声明一个serialversionUID变量,这个变量的作用是作为一个反序列化的标识,当该对象被序列化后,他的serialversionUID也会进入序列,当在进行JVM反序列化的时候会根据这个标识找到对应的类进行反序列化。当一个类实现于该接口后,其可以被ObjectOutputStream转化为字节流,同时也可以被ObjectInputStream重新转化成对象。该接口为一个空接口,主要用于为JVM提供标识,告知该类由JVM负责序列化和反序列化。原创 2025-03-20 17:21:13 · 196 阅读 · 0 评论 -
JAVA并发-分布式锁
分布式锁是一种在分布式环境下用于协调多个节点访问共享资源的机制。它可以保证在同一时刻,只有一个节点可以持有锁并访问共享资源,其他节点必须等待,直到锁被释放。一个有效的分布式锁应该具备以下特性:互斥性:在同一时刻,只能有一个节点持有锁。高可用性:锁服务本身必须是高可用的,否则会成为系统的单点故障。高性能:锁的获取和释放必须快速,否则会成为系统的性能瓶颈。可重入性:同一个节点多次获取同一个锁,不会产生死锁。原创 2025-03-20 14:04:20 · 734 阅读 · 0 评论 -
JAVA并发-悲观锁
悲观锁总是假设最坏的情况,认为共享资源每次被访问的时候就会出现问题,所以每次在获取资源操作的时候都会上锁,这样其他线程就会阻塞直至到锁悲伤一个持有者释放。在Java中synchronized和ReentrantLock等独占锁就是悲观锁的实现。原创 2025-03-20 14:04:03 · 222 阅读 · 0 评论 -
JAVA并发-乐观锁
乐观锁是一种并发控制策略,乐观锁总是假设最好的情况,认为共享资源每次被访问的时候不会出现问题,线程可以不停的执行,无需加锁也无需等待,只是在提交修改的时候需要去验证对应的资源是否被其他线程修改了(一般有两种方法:版本号机制或CAS算法)JAVA中通过CAS实现了乐观锁的原子变量类有两个(java.util.concurrent.atomic)下的AtomicInteger和LongAdder。原创 2025-03-20 13:33:21 · 588 阅读 · 0 评论 -
JAVA并发-唯一索引
就比如在高并发场景下,我们要注册一个用户,当出现比如前端反馈延迟或者其他情况,导致在注册用户的过程中出现了多次注册同一用户的行为,这可能导致数据库中存在重复的数据,这个时候可以采用唯一索引的方式,比如为每个注册的用户提供一个用户名的唯一索引,由于SQL的特性,唯一索引具有唯一性,所以无法插入唯一索引相同的数据,从而解决。原创 2025-03-20 13:32:50 · 207 阅读 · 0 评论 -
JAVA并发-什么是幂等性
幂等性(Idempotence):对同一个系统,使用同样的参数,不管执行多少次,都应该产生同样的结果。也就是说,一个幂等操作的效果和执行次数无关。举个简单的例子,假设我们有一个接口用于创建用户。如果这个接口是幂等的,那么无论调用多少次,只会创建一个用户。相反,如果这个接口不是幂等的,多次调用可能会创建多个重复的用户,导致数据不一致。原创 2025-03-20 13:31:39 · 288 阅读 · 0 评论 -
JAVA并发-Java线程池实现原理
线程池是一种基于池化思想的管理线程的工具,在多并发场景下,人为完成多线程什么时候创建销毁太过繁琐,所以有了线程池工具来帮助我们管理线程池,他最大的作用就是解开了任务和线程的耦合,使得使用者仅需要专注于任务的处理即可。本文描述的也就是JDK中提供的ThreadPoolExecutor类,该类就是专注于任务实现。原创 2025-03-20 13:29:55 · 926 阅读 · 0 评论 -
Kafka-ConsumerRecord
ConsumerRecord 是 Apache Kafka 消费者从主题中读取消息时的核心数据结构,每条消息都会被封装为一个 ConsumerRecord 对象。它包含了消息的元数据(如来源、位置)和实际内容,是消费者处理消息的基础单元。原创 2025-03-19 20:54:16 · 451 阅读 · 0 评论 -
Kafka-Q&A
同一topic下的不同分区包含的消息是不同的,有点类似于分库分表的意思,每一个分区partition会有<topic_name>-<partition_id>用以标识自己是哪一个分区。消息数量 3(1,2,3) 4(4,5,6,7) 3(8,9,10)这样做可以实现多个consumers可以同时消费一个topic。比如1,2,3,4,5,6,7,8,9,10是十条消息。其实可以理解为一个大管道中间由多个小管道。原创 2025-03-19 20:53:10 · 280 阅读 · 0 评论 -
Kakfa-为什么消息队列(Kafka)能够削峰
该技术是将读缓存区的文件描述符以及长度信息发送到Socket内核缓冲区,从而实现了CPU零拷贝,拷贝的过程就是DMA拷贝到读缓存区 -》 读缓存区将文件描述符和长度信息发送给Socket内核缓冲区 -》 DMA根据文件描述符和数据长度从读内核缓冲区把数据拷贝至网卡。该技术是读缓存区与用户空间进行映射,所以节省了由CPU将读缓存区拷贝到用户空间这一过程,所以是2次DMA和1次CPU拷贝。比如正常情况下我们在执行读文件时,需要DMA把磁盘的数据拷贝到读内核缓存区,CPU在把读内核缓存区拷贝到用户空间。原创 2025-03-19 20:52:40 · 288 阅读 · 0 评论 -
Kafka-Kafka的使用场景
比如举个例子,我现在有一个消息管理平台系统,对外提供接口给各个业务方调用。原创 2025-03-19 20:51:59 · 264 阅读 · 0 评论 -
JAVA并发-volatile底层原理
先来说可见性,java存在共享变量不可见性的原因就是,线程不可以直接操作主内存,他需要虚拟一个本地内存,正是因为这样,这两个内存就容易因为多线程的原因出现主内存和本地内存不一致的现象,而volatile就是解决了这点,具体就是通过一个Lock指令,这个指令使得当你在访问变量的时候需要判断你的内存地址是否有效,如果有效则更改并且会通知其他处理器缓存使得他们对于这个共享变量的内存地址都失效,如果发先内存地址实效,则需要重新从本地内存读取,从而实现了可见性。原创 2025-03-19 20:50:54 · 165 阅读 · 0 评论 -
JAVA并发-volatile、synchronized的区别
volatile无法保证原子性,且不会造成线程阻塞,但是synchronized会;volatile主要保证内存的可见性,synchronized则主要解决原子性;volatile作用变量,synchronized作用代码块和方法;原创 2025-03-19 20:50:24 · 114 阅读 · 0 评论