Java 面试八股文(全网最全20w字)

news2026/3/26 18:42:39
一、Java 基础知识1、Object 类相关方法getClass 获取当前运行时对象的 Class 对象。hashCode 返回对象的 hash 码。clone 拷贝当前对象 必须实现 Cloneable 接口。浅拷贝对基本类型进行值拷贝对引用类型拷贝引用深拷贝对基本类型进行值拷贝对引用类型对象不但拷贝对象的引用还拷贝对象的相关属性和方法。两者不同在于深拷贝创建了一个新的对象。equals 通过内存地址比较两个对象是否相等String 类重写了这个方法使用值来比较是否相等。toString 返回类名哈希码的 16 进制。notify 唤醒当前对象监视器的任一个线程。notifyAll 唤醒当前对象监视器上的所有线程。wait 1、暂停线程的执行2、三个不同参数方法等待多少毫秒额外等待多少毫秒一直等待3、与Thread.sleep(long time)相比sleep 使当前线程休眠一段时间并没有释放该对象的锁wait 释放了锁。finalize 对象被垃圾回收器回收时执行的方法。2、基本数据类型整型byte(8)、short(16)、int(32)、long(64)浮点型float(32)、double(64)布尔型boolean(8)字符型char(16)3、序列化Java 对象实现序列化要实现 Serializable 接口。反序列化并不会调用构造方法。反序列的对象是由 JVM 自己生成的对象不通过构造方法生成。序列化对象的引用类型成员变量也必须是可序列化的否则会报错。如果想让某个变量不被序列化使用 transient 修饰。单例类序列化需要重写 readResolve() 方法。4、String、StringBuffer、StringBuilderString 由 char[] 数组构成使用了 final 修饰是不可变对象可以理解为常量线程安全对 String 进行改变时每次都会新生成一个 String 对象然后把指针指向新的引用对象。StringBuffer 线程安全StringBuiler 线程不安全。操作少量字符数据用 String单线程操作大量数据用 StringBuilder多线程操作大量数据用 StringBuffer。5、重载与重写重载 发生在同一个类中方法名相同参数的类型、个数、顺序不同方法的返回值和修饰符可以不同。重写 发生在父子类中方法名和参数相同返回值范围小于等于父类抛出的异常范围小于等于父类访问修饰符范围大于等于父类如果父类方法访问修饰符为 private 或者 final 则子类就不能重写该方法。6、final修饰基本类型变量一经出初始化后就不能够对其进行修改。修饰引用类型变量不能够指向另一个引用。修饰类或方法不能被继承或重写。7、反射在运行时动态的获取类的完整信息增加程序的灵活性JDK 动态代理使用了反射8、JDK 动态代理使用步骤创建接口及实现类实现代理处理器实现 InvokationHandler 实现 invokeProxy proxyMethod methodObject[] args 方法通过 Proxy.newProxyInstance(ClassLoaderloader, Class[] interfaces, InvocationHandler h) 获得代理类通过代理类调用方法。9、Java IO普通 IO 面向流同步阻塞线程。NIO面向缓冲区同步非阻塞。二、Java 集合框架1、List线性结构ArrayList Object[] 数组实现默认大小为 10 支持随机访问连续内存空间插入末尾时间复杂度 o(1)插入第 i 个位置时间复杂度 o(n - i)。扩容大小变为1.5倍Arrays.copyOf底层 System.ArrayCopy复制到新数组指针指向新数组。Vector 类似 ArrayList线程安全扩容默认增长为原来的2倍还可以指定增长空间长度。LinkedList 基于链表实现1.7 为双向链表1.6 为双向循环链表取消循环更能分清头尾。2、MapKV 对HashMap底层数据结构JDK 1.8 是数组 链表 红黑树JDK 1.7 无红黑树。链表长度大于 8 时转化为红黑树优化查询效率。初始容量为16通过 tableSizeFor 保证容量为 2 的幂次方。寻址方式高位异或(n-1)h取模优化速度。扩容机制当元素数量大于容量 x 负载因子 0.75 时容量扩大为原来的 2 倍新建一个数组然后转移到新数组。基于 Map 实现。线程不安全。HashMap (1.7) 多线程循环链表问题在多线程环境下进行扩容时1.7 下的 HashMap 会形成循环链表。怎么形成循环链表 假设有一 HashMap 容量为 2 在数组下标 1 位置以 A - B 链表形式存储。有一线程对该 map 做 put 操作由于触发扩容条件需要进行扩容。这时另一个线程也 put 操作同样需要扩容并完成了扩容操作由于复制到新数组是头部插入所以 1 位置变为 B - A 。这时第一个线程继续做扩容操作首先复制 A 然后复制 B 再判断 B.next 是否为空时由于第二个线程做了扩容操作导致 B.next A所以在将 A 放到 B 前A.next 又等于 B 导致循环链表出现。HashTable线程安全方法基本全用 Synchronized 修饰。初始容量为 11 扩容为 2n 1 。继承Dictionary类。ConcurrentHashMap线程安全的 HashMap。1.7 采用分段锁的形式加锁1.8 使用 Synchronized 和 CAS 实现同步若数组的 Node 为空则通过 CAS 的方式设置值不为空则加在链表的第一个节点。获取第一个元素是否为空使用 Unsafe 类提供的 getObjectVolatile 保证可见性。对于读操作数组由 volatile 修饰同时数组的元素为 NodeNode 的 K 使用 final 修饰V 使用 volatile 修饰下一个节点也用 volatile 修饰保证多线程的可见性。LinkedHashMap LinkedHashMap 继承自 HashMap所以它的底层仍然是基于拉链式散列结构即由数组和链表或红黑树组成。另外LinkedHashMap 在上面结构的基础上增加了一条双向链表使得上面的结构可以保持键值对的插入顺序。TreeMap 有序的 Map红黑树结构可以自定义比较器来进行排序。Collections.synchronizedMap 如何实现 Map 线程安全 基于 Synchronized 实际上就是锁住了当前传入的 Map 对象。3、Set唯一值HashSet 基于 HashMap 实现使用了 HashMap 的 K 作为元素存储V 为 new Object() 在 add() 方法中如果两个元素的 Hash 值相同则通过 equals 方法比较是否相等。LinkedHashSet LinkedHashSet 继承于 HashSet并且其内部是通过 LinkedHashMap 来实现的。TreeSet 红黑树实现有序唯一。三、Java 多线程1、synchronized修饰代码块 底层实现通过 monitorenter monitorexit 标志代码块为同步代码块。修饰方法 底层实现通过 ACC_SYNCHRONIZED 标志方法是同步方法。修饰类 class 对象时实际锁在类的实例上面。单例模式public class Singleton {private static volatile Singleton instance null;private Singleton(){}public static Singleton getInstance(){if (null instance) {synchronized (Singleton.class) {if (null instance) {instance new Singleton();}}}return instance;}}运行项目并下载源码偏向锁自旋锁轻量级锁重量级锁通过 synchronized 加锁第一个线程获取的锁为偏向锁这时有其他线程参与锁竞争升级为轻量级锁其他线程通过循环的方式尝试获得锁称自旋锁。若果自旋的次数达到一定的阈值则升级为重量级锁。需要注意的是在第二个线程获取锁时会先判断第一个线程是否仍然存活如果不存活不会升级为轻量级锁。2、LockReentrantLock基于 AQS AbstractQueuedSynchronizer实现主要有 state (资源) FIFO (线程等待队列) 组成。公平锁与非公平锁区别在于在获取锁时公平锁会判断当前队列是否有正在等待的线程如果有则进行排队。使用 lock() 和 unLock() 方法来加锁解锁。ReentrantReadWriteLock同样基于 AQS 实现内部采用内部类的形式实现了读锁共享锁和写锁 排它锁。非公平锁吞吐量高 在获取锁的阶段来分析当某一线程要获取锁时非公平锁可以直接尝试获取锁而不是判断当前队列中是否有线程在等待。一定情况下可以避免线程频繁的上下文切换这样活跃的线程有可能获得锁而在队列中的锁还要进行唤醒才能继续尝试获取锁而且线程的执行顺序一般来说不影响程序的运行。3、volatileJava 内存模型在多线程环境下保证变量的可见性。使用了 volatile 修饰变量后在变量修改后会立即同步到主存中每次用这个变量前会从主存刷新。禁止 JVM 指令重排序。单例模式双重校验锁变量为什么使用 volatile 修饰 禁止 JVM 指令重排序new Object()分为三个步骤申请内存空间将内存空间引用赋值给变量变量初始化。如果不禁止重排序有可能得到一个未经初始化的变量。4、线程的五种状态1). New一个新的线程被创建还没开始运行。2). Runnable一个线程准备就绪随时可以运行的时候就进入了 Runnable 状态。Runnable 状态可以是实际正在运行的线程也可以是随时可以运行的线程。多线程环境下每个线程都会被分配一个固定长度的 CPU 计算时间每个线程运行一会儿就会停止让其他线程运行这样才能让每个线程公平的运行。这些等待 CPU 和正在运行的线程就处于 Runnable 状态。3). Blocked例如一个线程在等待 I/O 资源或者它要访问的被保护代码已经被其他线程锁住了那么它就在阻塞 Blocked 状态这个线程所需的资源到位后就转入 Runnable 状态。4). Waiting无限期等待如果一个线程在等待其他线程的唤醒那么它就处于 Waiting 状态。以下方法会让线程进入等待状态Object.wait()Thread.join()LockSupport.park()5). Timed Waiting有期限等待无需等待被其他线程显示唤醒在一定时间后有系统自动唤醒。以下方法会让线程进入有限等待状态Thread.sleep(sleeptime)Object.wait(timeout)Thread.join(timeout)LockSupport.parkNanos(timeout)LockSupport.parkUntil(timeout)6). Terminated一个线程正常执行完毕或者意外失败那么就结束了。5、 wait() 与 sleep()调用后线程进入 waiting 状态。wait() 释放锁sleep() 没有释放锁。调用 wait() 后需要调用 notify() 或 notifyAll() 方法唤醒线程。wait() 方法声明在 Object 中sleep() 方法声明在 Thread 中。6、 yield()调用后线程进入 runnable 状态。让出 CPU 时间片之后有可能其他线程获得执行权也有可能这个线程继续执行。7、 join()在线程 B 中调用了线程 A 的 Join()方法直到线程 A 执行完毕后才会继续执行线程 B。可以保证线程的顺序执行。join() 方法必须在 线程启动后调用才有意义。使用 wait() 方法实现。9、线程使用方式继承 Tread 类实现 Runnable 接口实现 Callable 接口带有返回值10、Runnable 和 Callable 比较方法签名不同void Runnable.run(),V Callable.call() throws Exception是否允许有返回值Callable允许有返回值是否允许抛出异常Callable允许抛出异常。提交任务方式Callable使用FutureT submit(CallableT task)返回 Future 对象调用其 get() 方法可以获得返回值Runnable使用void execute(Runnable command)。11、hapens-before如果一个操作 happens-before 另一个操作那么第一个操作的执行结果将对第二个操作可见而且第一个操作的执行顺序排在第二个操作之前。12、ThreadLocal场景 主要用途是为了保持线程自身对象和避免参数传递主要适用场景是按线程多实例每个线程对应一个实例的对象的访问并且这个对象很多地方都要用到。原理 为每个线程创建变量副本不同线程之间不可见保证线程安全。使用 ThreadLocalMap 存储变量副本以 ThreadLocal 为 K这样一个线程可以拥有多个 ThreadLocal 对象。实际 使用多数据源时需要根据数据源的名字切换数据源假设一个线程设置了一个数据源这个时候就有可能有另一个线程去修改数据源可以使用 ThreadLocal 维护这个数据源名字使每个线程持有数据源名字的副本避免线程安全问题。8、线程池1)、分类FixThreadPool 固定数量的线程池适用于对线程管理高负载的系统SingleThreadPool 只有一个线程的线程池适用于保证任务顺序执行CacheThreadPool 创建一个不限制线程数量的线程池适用于执行短期异步任务的小程序低负载系统ScheduledThreadPool 定时任务使用的线程池适用于定时任务2)、线程池的几个重要参数int corePoolSize, 核心线程数int maximumPoolSize, 最大线程数long keepAliveTime, TimeUnit unit, 超过 corePoolSize 的线程的存活时长超过这个时间多余的线程会被回收。BlockingQueue workQueue, 任务的排队队列ThreadFactory threadFactory, 新线程的产生方式RejectedExecutionHandler handler) 拒绝策略3)、线程池线程工作过程corePoolSize - 任务队列 - maximumPoolSize - 拒绝策略核心线程在线程池中一直存活当有任务需要执行时直接使用核心线程执行任务。当任务数量大于核心线程数时加入等待队列。当任务队列数量达到队列最大长度时继续创建线程最多达到最大线程数。当设置回收时间时核心线程以外的空闲线程会被回收。如果达到了最大线程数还不能够满足任务执行需求则根据拒绝策略做拒绝处理。4)、线程池拒绝策略默认抛出异常|:---|:---| | AbortPolicy | 抛出 RejectedExecutionException | | DiscardPolicy | 什么也不做直接忽略 | | DiscardOldestPolicy | 丢弃执行队列中最老的任务尝试为当前提交的任务腾出位置 | | CallerRunsPolicy | 直接由提交任务者执行这个任务 |5)、如何根据 CPU 核心数设计线程池线程数量IO 密集型 2nCPU计算密集型 nCPU1其中 n 为 CPU 核心数量可通过Runtime.getRuntime().availableProcessors()获得核心数。为什么加 1即使当计算密集型的线程偶尔由于缺失故障或者其他原因而暂停时这个额外的线程也能确保 CPU 的时钟周期不会被浪费。四、Java 虚拟机1、Java 内存结构堆 由线程共享存放 new 出来的对象是垃圾回收器的主要工作区域。栈 线程私有分为 Java 虚拟机栈和本地方法栈存放局部变量表、操作栈、动态链接、方法出口等信息方法的执行对应着入栈到出栈的过程。方法区 线程共享存放已被加载的类信息、常量、静态变量、即时编译器编译后的代码等信息JDK 1.8 中方法区被元空间取代使用直接内存。2、Java 类加载机制加载 加载字节码文件。链接验证 验证字节码文件的正确性。准备 为静态变量分配内存。解析 将符号引用如类的全限定名解析为直接引用类在实际内存中的地址。初始化 为静态变量赋初值。双亲委派模式当一个类需要加载时判断当前类是否被加载过。已经被加载的类会直接返回否则才会尝试加载。加载的时候首先会把该请求委派该父类加载器的loadClass()处理因此所有的请求最终都应该传送到顶层的启动类加载器BootstrapClassLoader中。当父类加载器无法处理时才由自己来处理。当父类加载器为 null 时会使用启动类加载器BootstrapClassLoader作为父类加载器。3、垃圾回收算法Mark-Sweep标记-清除算法 标记需要回收的对象然后清除会造成许多内存碎片。Copying复制算法 将内存分为两块只使用一块进行垃圾回收时先将存活的对象复制到另一块区域然后清空之前的区域。Mark-Compact标记-整理算法压缩法 与标记清除算法类似但是在标记之后将存活对象向一端移动然后清除边界外的垃圾对象。Generational Collection分代收集算法 分为年轻代和老年代年轻代时比较活跃的对象使用复制算法做垃圾回收。老年代每次回收只回收少量对象使用标记整理法。4、典型垃圾回收器CMS简介 以获取最短回收停顿时间为目标的收集器它是一种并发收集器采用的是 Mark-Sweep 算法。场景 如果你的应用需要更快的响应不希望有长时间的停顿同时你的 CPU 资源也比较丰富就适合适用 CMS 收集器。垃圾回收步骤初始标记 (Stop the World 事件 CPU 停顿 很短) 初始标记仅标记一下 GC Roots 能直接关联到的对象速度很快并发标记 (收集垃圾跟用户线程一起执行) 并发标记过程就是进行 GC Roots 查找的过程重新标记 (Stop the World 事件 CPU 停顿比初始标记稍微长远比并发标记短) 修正由于并发标记时应用运行产生变化的标记。并发清理标记清除算法缺点并发标记时和应用程序同时进行占用一部分线程所以吞吐量有所下降。并发清除时和应用程序同时进行这段时间产生的垃圾就要等下一次 GC 再清除。采用的标记清除算法产生内存碎片如果要新建大对象会提前触发 Full GC 。G1简介 是一款面向服务端应用的收集器它能充分利用多 CPU、多核环境。因此它是一款并行与并发收集器并且它能建立可预测的停顿时间模型即可以设置 STW 的时间。垃圾回收步骤 1、初始标记(stop the world 事件 CPU 停顿只处理垃圾) 2、并发标记(与用户线程并发执行) 3、最终标记(stop the world 事件 ,CPU 停顿处理垃圾) 4、筛选回收(stop the world 事件 根据用户期望的 GC 停顿时间回收)特点并发与并行 充分利用多核 CPU 使用多核来缩短 STW 时间部分需要停顿应用线程的操作仍然可以通过并发保证应用程序的执行。分代回收 新生代幸存带老年代空间整合 总体看是采用标记整理算法回收每个 Region 大小相等通过复制来回收。可预测的停顿时间 使用 -XX:MaxGCPauseMillis200 设置最长目标暂停值。在 Java 语言中可作为 GC Roots 的对象包括 4 种情况a) 虚拟机栈中引用的对象栈帧中的本地变量表 b) 方法区中类静态属性引用的对象 c) 方法区中常量引用的对象 d) 本地方法栈中 Native 方法引用的对象。五、MySQL Inno DB1、聚簇索引与非聚簇索引都使用 B 树作为数据结构聚簇索引中数据存在主键索引的叶子结点中得到 key 即得到 data 非聚簇索引的数据存在单独的空间。聚簇索引中辅助索引的叶子结点存的是主键非聚簇索引中叶子结点存的是数据的地址聚簇索引的优势是找到主键就找到数据只需一次磁盘 IO 当 B 树的结点发生变化时地址也会发生变化这时非聚簇索引需要更新所有的地址增加开销。2、为何使用 B 树做索引而不是红黑树索引很大通常作为文件存储在磁盘上面每次检索索引都需要把索引文件加载进内存所以磁盘 IO 的次数是衡量索引数据结构好坏的重要指标。应用程序在从磁盘读取数据时不只是读取需要的数据还会连同其他数据以页的形式做预读来减少磁盘 IO 的次数。数据库的设计者将每个节点的大小设置为一页的大小同时每次新建节点时都重新申请一个页这样检索一个节点只需要一次 IO根据索引定位到数据只需要 h- 1h 为 B 树高度根节点常驻内存 次 IO而 d (度可以理解为宽度)与 h 称反比即 d 越大高度就越小所以树越扁磁盘 IO 次数越少即渐进复杂度为 logdN 这也是为什么不选择红黑树做索引的原因。前面可以得出结论d 越大索引的性能越好。节点由 key 和 data 组成页的大小一定key 和 data 越小d 越大。B 树去掉了节点内的 data 域所以有更大的 d , 性能更好。3、最左前缀原则在 MySQL 中可以指定多个列为索引即联合索引。比如 index(nameage) 最左前缀原则是指查询时精确匹配到从最左边开始的一列或几列namenameage就可以命中索引。如果所有列都用到了顺序不同查询引擎会自动优化为匹配联合索引的顺序这样是能够命中索引的。4、什么情况下可以用到 B 树索引(1) 定义有主键的列一定要建立索引。因为主键可以加速定位到表中的某行(2) 定义有外键的列一定要建立索引。外键列通常用于表与表之间的连接在其上创建索引可以加快表间的连接(3) 对于经常查询的数据列最好建立索引。① 对于需要在指定范围内快速或频繁查询的数据列因为索引已经排序其指定的范围是连续的查询可以利用索引的排序加快查询的时间② 经常用在where子句中的数据列将索引建立在where子句的集合过程中对于需要加速或频繁检索的数据列可以让这些经常参与查询的数据列按照索引的排序进行查询加快查询的时间。5、事务隔离级别Read uncommitted读未提交可能出现脏读不可重复读幻读。Read committed读提交可能出现不可重复读幻读。Repeatable read可重复读可能出现脏读。Serializable可串行化同一数据读写都加锁避免脏读性能不忍直视。Inno DB 默认隔离级别为可重复读级别分为快照度和当前读并且通过行锁和间隙锁解决了幻读问题。6、MVCC 多版本并发控制实现细节每行数据都存在一个版本每次数据更新时都更新该版本。修改时 Copy 出当前版本随意修改各个事务之间互不干扰。保存时比较版本号如果成功commit则覆盖原记录失败则放弃 copyrollback。Inno DB 实现在 InnoDB 中为每行增加两个隐藏的字段分别是该行数据创建时的版本号和删除时的版本号这里的版本号是系统版本号可以简单理解为事务的 ID每开始一个新的事务系统版本号就自动递增作为事务的 ID 。通常这两个版本号分别叫做创建时间和删除时间。六、Spring 相关1、Bean 的作用域|:---|:---| | 类别 | 说明 | |singleton| 默认在 Spring 容器中仅存在一个实例 | |prototype| 每次调用 getBean() 都重新生成一个实例 | |request| 为每个 HTTP 请求生成一个实例 | |session| 同一个 HTTP session 使用一个实例不同 session 使用不同实例 |2、Bean 生命周期简单来说四步实例化 Instantiation属性赋值 Populate初始化 Initialization销毁 Destruction在这四步的基础上面Spring 提供了一些拓展点Bean 自身的方法: 这个包括了 Bean 本身调用的方法和通过配置文件中 %3Cbean %3E 的 init-method 和 destroy-method 指定的方法Bean 级生命周期接口方法: 这个包括了 BeanNameAware、BeanFactoryAware、InitializingBean 和 DiposableBean 这些接口的方法容器级生命周期接口方法这个包括了 InstantiationAwareBeanPostProcessor 和 BeanPostProcessor 这两个接口实现一般称它们的实现类为“后处理器”。工厂后处理器接口方法: 这个包括了 AspectJWeavingEnabler, ConfigurationClassPostProcessor, CustomAutowireConfigurer 等等非常有用的工厂后处理器接口的方法。工厂后处理器也是容器级的。在应用上下文装配配置文件之后立即调用。3、Spring AOP实现方式两种JDK 动态代理带有接口的对象在运行期实现CGlib 静态代理在编译期实现。4、Spring 事务传播行为默认PROPAGATION_REQUIRED如果存在一个事务则支持当前事务。如果没有事务则开启一个新的事务。5、Spring IoC6、Spring MVC 工作流程七、计算机网络1、TCP/IP 五层模型2、浏览器输入地址后做了什么3、三次握手与四次挥手三次握手四次挥手4、TIME_WAIT 与 CLOSE_WAIT5、TCP 滑动窗口TCP 流量控制主要使用滑动窗口协议滑动窗口是接受数据端使用的窗口大小用来告诉发送端接收端的缓存大小以此可以控制发送端发送数据的大小从而达到流量控制的目的。这个窗口大小就是我们一次传输几个数据。对所有数据帧按顺序赋予编号发送方在发送过程中始终保持着一个发送窗口只有落在发送窗口内的帧才允许被发送同时接收方也维持着一个接收窗口只有落在接收窗口内的帧才允许接收。6、TCP 粘包和拆包现象产生原因 1、要发送的数据大于 TCP 发送缓冲区剩余空间大小将会发生拆包。 2、待发送数据大于 MSS最大报文长度TCP 在传输前将进行拆包。 3、要发送的数据小于 TCP 发送缓冲区的大小TCP 将多次写入缓冲区的数据一次发送出去将会发生粘包。 4、接收数据端的应用层没有及时读取接收缓冲区中的数据将发生粘包。解决方式 1、发送端给每个数据包添加包首部首部中应该至少包含数据包的长度这样接收端在接收到数据后通过读取包首部的长度字段便知道每一个数据包的实际长度了。 2、发送端将每个数据包封装为固定长度不够的可以通过补 0 填充这样接收端每次从接收缓冲区中读取固定长度的数据就自然而然的把每个数据包拆分开来。 3、可以在数据包之间设置边界如添加特殊符号这样接收端通过这个边界就可以将不同的数据包拆分开。八、MQ 消息队列1、场景作用削峰填谷异步解耦。2、如何保证消息不被重复消费呢这个问题可以换个思路保证消息重复消费其实是保证程序的幂等性。无论消息如何重复程序运行的结果是一致的。比如消费消息后做数据库插入操作为了防止消息重复消费可以在插入前先查询一下有没有对应的数据。3、怎么保证从消息队列里拿到的数据按顺序执行消费端在接收到消息后放入内存队列然后对队列中的消息进行有序消费。4、如何解决消息队列的延时以及过期失效问题消息队列满了以后该怎么处理有几百万消息持续积压几小时说说怎么解决消息过期失效问题如果消息一段时间不消费导致过期失效了消息就丢失了只能重新查出丢失的消息重新发送。 再来说消息积压的问题思路是快速消费掉积压的消息首先排查消费端问题恢复消费端正常消费速度。然后着手处理队列中的积压消息。停掉现有的 consumer。新建一个 topic 设置之前 10 倍的 partation之前 10 倍的队列。写一个分发程序将积压的消息均匀的轮询写入这些队列。然后临时用 10 倍的机器部署 consumer每一批 consumer 消费 1 个临时的队列。消费完毕后恢复原有架构。消息队列满了只能边接收边丢弃然后重新补回丢失的消息再做消费。4、如何保证消息的可靠性传输如何处理消息丢失的问题kafka 为例消费者丢了数据 每次消息消费后由自动提交 offset 改为手动提交 offset 。kafka 丢了消息 比较常见的一个场景就是 kafka 某个 broker 宕机然后重新选举 partition 的 leader 时。要是此时其他的 follower 刚好还有些数据没有同步结果此时 leader 挂了然后大家选举某个 follower 成为 leader 之后不就少了一些数据。给 topic 设置replication.factor参数这个值必须大于 1要求每个 partition 必须有至少两个副本。在 kafka 服务端设置min.insync.replicas参数这个值必须大于 1这个是要求一个 leader 至少感知到有至少一个 follower 还跟自己保持联系没掉队这样才能确保 leader 挂了还有一个 follower。在 producer 端设置acksall这个是要求每条数据必须是写入所有 replica 之后才能认为是写成功了。在 producer 端设置retriesMAX很大很大很大的一个值无限次重试的意思这个是要求一旦写入失败就无限重试卡在这里。生产者丢了消息 如果按照上述的思路设置了 ackall一定不会丢要求是你的 leader 接收到消息所有的 follower 都同步到了消息之后才认为本次写成功了。如果没满足这个条件生产者会自动不断的重试重试无限次。九、Redis1、数据类型String常用命令 set,get,decr,incr,mget 等。Hash常用命令 hget,hset,hgetall 等List常用命令 lpush,rpush,lpop,rpop,lrange 等可以通过 lrange 命令就是从某个元素开始读取多少个元素可以基于 list 实现分页查询。Set常用命令 sadd,spop,smembers,sunion 等Sort Set常用命令 zadd,zrange,zrem,zcard 等2、Redis 如何实现 key 的过期删除定期删除和惰性删除的形式。定期删除 Redis 每隔一段时间从设置过期时间的 key 集合中随机抽取一些 key 检查是否过期如果已经过期做删除处理。惰性删除 Redis 在 key 被访问的时候检查 key 是否过期如果过期则删除。3、Redis 的持久化机制数据快照RDB 修改数据语句文件AOF4、如何解决 Redis 缓存雪崩和缓存穿透缓存雪崩 缓存同一时间大面积的失效所以后面的请求都会落到数据库上造成数据库短时间内承受大量请求而崩掉。解决方式事前保证 Redis 集群的稳定性发现机器宕机尽快补上设置合适的内存淘汰策略。事中本地缓存 限流降级避免大量请求落在数据库上。事后利用 Redis 持久化机制尽快恢复缓存。缓存穿透 一般是黑客故意去请求缓存中不存在的数据导致所有的请求都落到数据库上造成数据库短时间内承受大量请求而崩掉。解决方式 将不存在的数据列举到一个足够大的 map 上这样遭到攻击时直接拦截 map 中的请求请求到数据库上面。或是把不存在的也做缓存值为 null 设置过期时间。5、如何使用 Redis 实现消息队列Redis 实现消息队列依赖于 Redis 集群的稳定性通常不建议使用。Redis 自带发布订阅功能基于 publish 和 subscribe 命令。使用 List 存储消息lpushrpop 分别发送接收消息。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2451835.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…

UE5 学习系列(二)用户操作界面及介绍

这篇博客是 UE5 学习系列博客的第二篇,在第一篇的基础上展开这篇内容。博客参考的 B 站视频资料和第一篇的链接如下: 【Note】:如果你已经完成安装等操作,可以只执行第一篇博客中 2. 新建一个空白游戏项目 章节操作,重…

IDEA运行Tomcat出现乱码问题解决汇总

最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…

利用最小二乘法找圆心和半径

#include <iostream> #include <vector> #include <cmath> #include <Eigen/Dense> // 需安装Eigen库用于矩阵运算 // 定义点结构 struct Point { double x, y; Point(double x_, double y_) : x(x_), y(y_) {} }; // 最小二乘法求圆心和半径 …

使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式

一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明&#xff1a;假设每台服务器已…

XML Group端口详解

在XML数据映射过程中&#xff0c;经常需要对数据进行分组聚合操作。例如&#xff0c;当处理包含多个物料明细的XML文件时&#xff0c;可能需要将相同物料号的明细归为一组&#xff0c;或对相同物料号的数量进行求和计算。传统实现方式通常需要编写脚本代码&#xff0c;增加了开…

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器的上位机配置操作说明

LBE-LEX系列工业语音播放器|预警播报器|喇叭蜂鸣器专为工业环境精心打造&#xff0c;完美适配AGV和无人叉车。同时&#xff0c;集成以太网与语音合成技术&#xff0c;为各类高级系统&#xff08;如MES、调度系统、库位管理、立库等&#xff09;提供高效便捷的语音交互体验。 L…

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…

【大模型RAG】拍照搜题技术架构速览:三层管道、两级检索、兜底大模型

摘要 拍照搜题系统采用“三层管道&#xff08;多模态 OCR → 语义检索 → 答案渲染&#xff09;、两级检索&#xff08;倒排 BM25 向量 HNSW&#xff09;并以大语言模型兜底”的整体框架&#xff1a; 多模态 OCR 层 将题目图片经过超分、去噪、倾斜校正后&#xff0c;分别用…

【Axure高保真原型】引导弹窗

今天和大家中分享引导弹窗的原型模板&#xff0c;载入页面后&#xff0c;会显示引导弹窗&#xff0c;适用于引导用户使用页面&#xff0c;点击完成后&#xff0c;会显示下一个引导弹窗&#xff0c;直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…

龙虎榜——20250610

上证指数放量收阴线&#xff0c;个股多数下跌&#xff0c;盘中受消息影响大幅波动。 深证指数放量收阴线形成顶分型&#xff0c;指数短线有调整的需求&#xff0c;大概需要一两天。 2025年6月10日龙虎榜行业方向分析 1. 金融科技 代表标的&#xff1a;御银股份、雄帝科技 驱动…

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具&#xff0c;该工具基于TUN接口实现其功能&#xff0c;利用反向TCP/TLS连接建立一条隐蔽的通信信道&#xff0c;支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式&#xff0c;适应复杂网…

铭豹扩展坞 USB转网口 突然无法识别解决方法

当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…

未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?

编辑&#xff1a;陈萍萍的公主一点人工一点智能 未来机器人的大脑&#xff1a;如何用神经网络模拟器实现更智能的决策&#xff1f;RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战&#xff0c;在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…

深度学习在微纳光子学中的应用

深度学习在微纳光子学中的主要应用方向 深度学习与微纳光子学的结合主要集中在以下几个方向&#xff1a; 逆向设计 通过神经网络快速预测微纳结构的光学响应&#xff0c;替代传统耗时的数值模拟方法。例如设计超表面、光子晶体等结构。 特征提取与优化 从复杂的光学数据中自…