当前位置: 首页 > article >正文

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

一、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 分别发送接收消息。

相关文章:

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

一、Java 基础知识 1、Object 类相关方法 getClass 获取当前运行时对象的 Class 对象。hashCode 返回对象的 hash 码。clone 拷贝当前对象, 必须实现 Cloneable 接口。浅拷贝对基本类型进行值拷贝,对引用类型拷贝引用;深拷贝对基本类型进行…...

热门 PyPI 包 LiteLLM 遭投毒,窃取凭据和认证令牌

聚焦源代码安全,网罗国内外最新资讯! 编译:代码卫士专栏供应链安全数字化时代,软件无处不在。软件如同社会中的“虚拟人”,已经成为支撑社会正常运转的最基本元素之一,软件的安全性问题也正在成为当今社会的…...

神经高利贷:预支未来技能导致认知崩溃

在软件测试领域,从业者常面临一个隐形威胁:过度追求新技能而忽视认知极限,最终引发崩溃。这种现象被称为“神经高利贷”,即通过预支未来学习能力来应对当前挑战,结果导致认知资源枯竭、错误率飙升,甚至职业…...

脑皮层房地产:公司在我的神经突触建数据中心

在数字时代的浪潮中,一个颠覆性的概念正在兴起:企业将数据中心直接构建于人类神经突触之上,仿佛一场“脑皮层房地产”的革命。这并非科幻小说的臆想,而是对现代分布式系统和人工智能架构的深刻隐喻。对于软件测试从业者而言&#…...

情感GDP报告:测试员负面情绪成经济指标的行业变革

一、导言:情感GDP的崛起与测试行业新坐标 2025年全球情感计算市场规模突破596亿元(数据来源:2024年情感计算行业报告),"情感GDP"作为衡量情绪价值的经济指标,正重塑职业评价体系。软件测试领域首…...

【OpenClaw 全面解析:从零到精通】第 025 篇:OpenClaw v2026.3.22+v2026.3.23 安全与架构全面升级:从版本迭代看 AI Agent 工程化实践

系列说明:本系列全面介绍 OpenClaw 开源 AI 智能体框架,从历史背景到核心原理,从安装部署到应用生态。本文为系列第 025 篇,结合 2026 年 3 月 22-24 日最新发布的双版本合并更新,系统解析 OpenClaw 从功能驱动到安全驱…...

嵌入式开发调试与问题诊断实战指南

嵌入式工程师常见问题诊断与调试经验分享1. 典型开发场景分析1.1 开发环境差异问题"在我的开发环境运行正常"是嵌入式工程师最常遇到的困境之一。这种现象通常源于:编译器版本差异(GCC/Keil/IAR版本不一致)硬件平台差异&#xff08…...

别再傻傻线性扫描了!用Python+Scikit-learn手把手实现IVFFlat图像相似度搜索

用PythonScikit-learn实现IVFFlat图像搜索引擎:从原理到实战 当你面对十万张未分类的图片库,如何快速找到与目标图片最相似的十张?传统线性扫描需要计算所有图片特征的距离,耗时呈线性增长。本文将手把手教你用IVFFlat算法构建高效…...

网络协议与文件系统,小车亮灯实验

网络协议与文件系统 一、项目背景二、项目核心目标与环境二者协同工作流程 四、Linux文件系统与设备操作实战五、完整Python代码实现配置项(根据自身硬件调整)安全退出函数:捕获CtrlC,关闭LED后退出注册CtrlC信号,绑定…...

中国空间智能,梦想照进现实

2026年初,AI教母李飞飞的AI公司World Labs再次获得一笔10亿美元的投资,投资名单除了传统投资机构外,还不乏英伟达、Autodesk等行业巨头,这清晰地传递出市场信号:继AI大语言模型之后,空间智能已成为AI的下一…...

AI时代程序员创业指南:从超级个体到一人企业

AI时代程序员创业指南:从超级个体到一人企业 AI给了每个人杠杆,但不是每个人都能用好。认知、决策能力,甚至运气,同样重要。 引子:那些"超级个体"的真实故事 最近读到一篇AIX财经的报道,采访了6…...

AS3935闪电传感器Arduino驱动库深度解析与工业级应用

1. 项目概述AS3935 是一款由 AMS(现为 ams OSRAM)推出的专用闪电检测传感器芯片,集成 RF 前端、数字信号处理器(DSP)、闪电算法引擎及 IC/SPI 接口,可实现对 40 km 范围内云地闪(CG)…...

会议纪要助手:OpenClaw+GLM-4.7-Flash实时转录与摘要

会议纪要助手:OpenClawGLM-4.7-Flash实时转录与摘要 1. 为什么需要自动化会议纪要 每次开完会最头疼的就是整理会议纪要。上周三的部门周会结束后,我花了40分钟反复听录音、手敲重点,结果还是漏掉了两个关键决议事项。这种低效重复劳动让我…...

pyNastran:破解工程仿真困境的Python技术革新者

pyNastran:破解工程仿真困境的Python技术革新者 【免费下载链接】pyNastran A Python-based interface tool for Nastrans file formats 项目地址: https://gitcode.com/gh_mirrors/py/pyNastran 揭示行业痛点:有限元分析的三大核心挑战 现代工程…...

汽车智能制造时代,哪些服务商助力智慧供应链?

一辆汽车的诞生,背后是一场精密到分钟的大合唱。当生产线以每小时数十台的速度流转时,任何一个零部件的迟到,都可能导致整条线停摆。一个汽车工厂里,单一产线同时生产多种车型,涉及数以万计的SKU零部件。这些物料必须从…...

YOLOv8改进:MixUp with Consistency——基于混合增强与一致性正则化的鲁棒性目标检测算法

1. 引言目标检测作为计算机视觉领域的核心任务之一,在实际应用中面临着诸多挑战,如光照变化、遮挡、图像噪声以及数据分布偏移等问题。YOLOv8作为当前最先进的目标检测器之一,凭借其高效的网络结构和优秀的性能表现,已在工业界和学…...

告别用人“开盲盒”|江湖背调定义全生命周期风控范式

企业用人别踩坑!传统单次背调只有入口安检,无法应对员工在职动态风险,漏洞百出江湖背调以“雇前可信、在职可控”,正式定义全生命周期用工风控范式,筑牢从招聘到离职全链路安全屏障!传统背调vs全生命周期风…...

国际大牌入门之选

这些品牌是轻奢饰品界的常青树,设计经典,辨识度高,是很多人的入门首选。卡地亚 27%人推荐猎豹为图腾,工艺精湛,是轻奢界的经典与传奇。宝格丽 24%人推荐跃马徽记是其标志,珠宝设计性感矜贵,灵蛇…...

Steam致命错误failed to load steamui.dll?小白必看的6种实用修复方案

软件获取地址 https://pan.quark.cn/s/4cc6a4c0e881 打开Steam时突然弹出“failed to load steamui.dll”提示,无法进入平台甚至启动Y戏?这是Steam最常见的致命错误之一,在failed to load类问题中占比超4成,很多小白不清楚dll文件…...

避坑指南:三自由度机械臂DH参数建模与逆解求解的那些‘坑’(从理论到Matlab/Python验证)

三自由度机械臂运动学建模实战:从DH参数陷阱到逆解验证 机械臂运动学建模是机器人学中最基础却最容易踩坑的领域之一。很多工程师和学生在理论学习阶段看似掌握了DH参数法和正逆运动学推导,但一旦动手实践,总会遇到各种"诡异"的问题…...

OpenClaw飞书机器人配置指南:百川2-13B-4bits量化模型对话触发

OpenClaw飞书机器人配置指南:百川2-13B-4bits量化模型对话触发 1. 为什么选择OpenClaw飞书百川2的组合? 去年我接手了一个小团队的日报自动化项目,需要每天收集5个成员的进度更新并生成汇总报告。最初尝试用Python脚本钉钉机器人&#xff0…...

三层交换机vlan间互通配置

SW1(三层交换机)配置# 1. 创建VLAN sysname LSW1 vlan batch 100 200 300# 2. 配置接口并加入VLAN interface GigabitEthernet 0/0/4port link-type accessport default vlan 100stp disable # 关闭生成树 interface GigabitEthernet 0/0/5port link-ty…...

告别Linux卡顿!用RK3562的M0核跑RT-Thread,实现实时控制与Linux并行运行

RK3562多核异构开发实战:用M0核实现Linux与RT-Thread的完美协同 在智能家居控制器项目中,我们遇到了一个典型难题——当Linux系统处理图形界面和网络通信时,电机的实时控制会出现明显延迟。传统解决方案需要两套独立硬件,直到我们…...

Linux内核观测与跟踪的利器BPF环境测试

内核观测工具BPF实例BPF介绍BPF实例使用 BCC 工具集(最简单)使用 libbpf BPF 骨架(更接近生产环境)使用 bpftool 直接加载(适合调试)总结BPF介绍 BPF 最初诞生于 1992 年,是一种用于网络数据包…...

大三大学生挖洞收入十万背后:网安圈的“天才少年”,普通人能复制吗?

大三学生挖洞收入十万背后:网安圈的 “天才少年” ,普通人能复制吗? SRC首期学员战绩疯传:大四小白45天回本6K?大三在读2个月挖洞收获六位数? 当朋友圈被"零基础挖洞暴富"的捷报疯狂刷屏时&…...

MySQL 8.0迁移后表名报错?别急着改my.cnf,先搞懂lower_case_table_names这个坑

MySQL 8.0表名大小写陷阱:从踩坑到系统化解决方案 当数据库管理员小李将公司核心业务系统从MySQL 5.7迁移到8.0版本后,系统突然开始频繁报错"表不存在",而实际上这些表明明就在数据库中。这个看似简单的表象背后,隐藏着…...

Claude Code 速查表

其中的:键盘快捷键常规控制Ctrl C:取消输入 / 生成Ctrl D:退出会话Ctrl L:清屏Ctrl O:切换详细输出Ctrl R:反向搜索历史Ctrl G:在编辑器中打开提示Ctrl B:后台运行任务Ctrl …...

BilibiliDown:B站音视频资源管理的全场景解决方案

BilibiliDown:B站音视频资源管理的全场景解决方案 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bi…...

程序员视角:五笔输入法98版为何更适合代码编写?

程序员视角:五笔输入法98版为何更适合代码编写? 在程序员的世界里,效率就是生命。从IDE的选择到快捷键的配置,每一个细节都可能影响编码的速度和质量。而作为中文开发者,输入法的选择往往被忽视——直到你发现自己在输…...

browser-use爆火:AI Agent接管浏览器,测试自动化正在被重构

导读 最近在实际项目和工具演进中,可以明显看到一个变化: AI 不再只是写代码,而是开始“直接干活”。 这款 browser-use开源工具非常厉害。它能让AI Agent🚀直接操控浏览器。实现网页任务自动化简单高效 (๑•̀ㅂ•́)و✧。该…...