Java后端面試常見問題

Java后端面試

經歷了兩個月的面試和準備,下面對常見的八股文進行總結。有些問題是網上看到的面經里提到的,有些是我真實面試過程遇到的。

異常
1、異常分為哪幾種?他們的父類是什么?

注意:所有異常對象的父類為Throwable

  • Error及其子類:
    • 一般指的是虛擬機的錯誤,是由java虛擬機生成并拋出,程序不能進行處理,所以也不加處理,例如OutOfMemoryError內存溢出。
  • RuntimeException及其子類(運行時異常):
    • 是由編程bug所致。如NullPointerException、ClassCastException、ArrayIndexOutOfBoundsException、ArithmeticException
  • Exception及其子類中除了RuntimeException及其子類之外的其它異常(受檢型異常):
    • 編譯器就能檢測的異常,JAVA 編譯器強制要求我們必需對出現的這些異常進行 try-catch或者throws,否則編譯不會通過。如IOException、ClassNotFoundException
2、受檢異常與非受檢異常的區別?

? 同上。

3、Error可以捕獲嗎?

可以。Throwable 的子類,都可以被 try-catch 語句捕獲,分為 Error 和 Exception。

4、棧溢出和堆溢出是什么?OOM可以捕獲嗎?什么情況可以捕獲?

棧溢出:棧幀堆積,超過設置的棧的大小。

OOM 作為一個 Error,在某些條件下是可以被 catch 的。僅針對我們可控的代碼,并且在 try 塊中,由于申請大段連續內存的情況下,觸發的 OOM,才是可以被 catch 的。當 catch 住 OOM 時,應該主動釋放一些可控的內存,做好內存管理,避免在后續的操作中,在其他操作中又觸發 OOM,導致崩潰。

img

集合
1、說說你對Java集合的理解

2、ArrayList和LinkedList的區別

底層實現不同,長度一個有限一個理論無限

ArrayList延遲初始化,第一次添加元素時才初始化容量,每次擴容1.5倍

3、它們都線程安全嗎?如何得到線程安全的List?

No。

  1. Vector
  2. Collections.synchronizedList()方法對非線程安全集合進行裝飾
  3. CopyOnWriteArrayList。讀寫分離,讀取時不加鎖,只是寫入、刪除、修改時加鎖。不能保證完全線程安全,適用于讀多寫少的場景。
4、CopyOnWriteArrayList用過嗎?優缺點?

能保證寫入線程安全,提高讀線程并發量。

缺點:讀寫線程數據一致性無法保證、寫時內存占用問題

5、Set是有序還是無序的?一定無序嗎?

Set接口有三個實現類:HashSet(無序)、LinkedHashSet(有 序)、TreeSet(有序)

6、TreeSet的底層實現

紅黑樹。

7、把你所知道的HashMap的所有知識都說一下?(包括底層實現、擴容機制、1.7與1.8的區別、長度為什么是2的n次冪)

1.7:數組 + 鏈表,元素大于 容量 * 0.75 時進行擴容

1.8:數組 + 鏈表 + 紅黑樹

8、保證線程安全的Map是什么?ConcurrentHashMap聊一下?(和HashMap答題類似,不過重點要回答的是為什么線程安全)

HashTable、ConcurrentHashMap

HashTable 加的鎖鎖住整張表、ConcurrentHashMap1.8后鎖住一個節點再CAS自旋

ConcurrentHashMap:

1.7:分段鎖segment

1.8:CAS、synchronized、volatile

9、ConcurrentHashMap每個Node節點中變量使用final和volatile修飾有什么用呢?

final:保證不可修改,讀取該變量不用考慮線程安全問題。

volatile:volatile來保證某個變量內存的改變對其他線程即時可見,在配合CAS可以實現不加鎖對并發操作的支持。get操作可以無鎖是由于Node的元素val和指針next是用volatile修飾的,在多線程環境下線程A修改結點的val或者新增節點的時候是對線程B可見的。

10、ConcurrentHashMap中synchronize和CAS是如何使用的

深入淺出ConcurrentHashMap詳解-CSDN博客

CAS:當hash定位的節點為空,則用CAS自旋寫入。

synchronize:當hash定位的節點非空,則用synchronize鎖住節點進行修改。

至于為什么修改不用CAS,我的理解是由于無法解決ABA問題。

反射
1、反射是什么?舉幾個例子?

Java基礎之反射_java反射-CSDN博客

2、通過反射可以拿到類中的變量信息嗎?
設計模式(一般與SpringAOP一同問)

多線程

1、線程實現的方式及其優缺點?

線程是調度的基本單位。

2、如何死鎖?(考察死鎖的條件)
3、如何加鎖?(Synchronize關鍵字和Reentrantlock)

ReentrantLock詳解-CSDN博客

Reentrantlock實現了Lock接口規范:

接口作用
void lock()獲取鎖,調用該方法當前線程會獲取鎖,當鎖獲得后,該方法返回。
void lockInterruptibly() throws InterruptedException可中斷的獲取鎖,和lock()方法不同之處在于該方法會響應中斷,即在鎖的獲取中可以中斷當前線程
boolean tryLock()嘗試非阻塞的獲取鎖,調用該方法后立即返回。如果能夠獲取到返回true,否則返回false。
boolean tryLock(long time, TimeUnit unit) throws InterruptedException超時獲取鎖,當前線程在以下三種情況下會被返回: 當前線程在超時時間內獲取了鎖 當前線程在超時時間內被中斷 超時時間結束,返回false。
Condition newCondition()獲取等待通知組件,該組件和當前的鎖綁定,當前線程只有獲取了鎖,才能調用該組件的await()方法,而調用后,當前線程將釋放鎖。

可重入鎖:

可重入鎖又名遞歸鎖,是指在同一個線程在外層方法獲取鎖的時候,再進入該線程的內層方法會自動獲取鎖(前提鎖對象得是同一個對象),不會因為之前已經獲取過還沒釋放而阻塞。Java中ReentrantLock和synchronized都是可重入鎖,可重入鎖的一個優點是可一定程度避免死鎖。在實際開發中,可重入鎖常常應用于遞歸操作、調用同一個類中的其他方法、鎖嵌套等場景中。

3.1、同步方法塊和同步方法的區別?(monitorenter、exit和ACC_SYNCHRONIZED)

同步方法塊:monitorenter 和 monitorexit兩個指令進行同步

同步方法:ACC_SYNCHRONIZED標志位進行同步

3.2、鎖升級過程?

關于 鎖的四種狀態與鎖升級過程 圖文詳解 - 牧小農 - 博客園 (cnblogs.com)

鎖有四種狀態:無鎖、偏向鎖、輕量鎖、重量鎖。

三種鎖的優缺點對比:

優點缺點適用場景
偏向鎖加鎖和解鎖不需要額外的消耗,和執行非同步方法相比僅存在納秒級的差距如果線程質檢存在鎖競爭,會帶來額外鎖撤銷的消耗適用于只有一個線程訪問同步塊的場景
輕量級鎖競爭的線程不會阻塞,提高了程序的響應速度如果始終得不到鎖競爭的線程,使用自旋會消耗CPU資源追求響應時間,同步塊執行速度非常快
重量級鎖線程競爭不使用自旋,不會消耗CPU資源線程阻塞,響應時間緩慢追求吞吐量,同步塊執行速度較長

鎖升級過程:

  • 初次執行到synchronized代碼塊的時候,鎖對象變成偏向鎖(通過CAS修改對象頭里的鎖標志位),字面意思是“偏向于第一個獲得它的線程”的鎖。
  • 輕量級鎖是指當鎖是偏向鎖的時候,卻被另外的線程所訪問,此時偏向鎖就會升級為輕量級鎖,其他線程會通過自旋(關于自旋的介紹見文末)的形式嘗試獲取鎖,線程不會阻塞,從而提高性能。
  • 輕量級鎖在長時間獲取不到鎖時會忙等,自旋超過10次(可修改)時,升級為重量級鎖。
3.3、ReentrantLock優缺點?
3.4、底層實現?(AQS、CAS)
3.5、CAS會存在什么問題?如何避免?

ABA問題。版本號

3.6、公平鎖和非公平鎖在AQS上是如何實現的?Synchronized是公平鎖還是非公平鎖?
3.7、synchronized原理

synchronized原理_synchronized可重入鎖原理-CSDN博客

原理:JVM提供的監視器monitor,synchronized對代碼塊加鎖需要依靠兩個指令 monitorenter 和 monitorexit,對方法加鎖依賴方法ACC_SYNCHRONIZED標志區。

synchronized鎖升級原理:

JDK1.6之前synchronize是標準的重量級鎖(悲觀鎖),JDK1.6之后進行了大幅度優化,支持鎖升級制度緩解加鎖和解鎖造成的性能浪費,鎖的狀態總共有四種,無鎖、偏向鎖、輕量級鎖和重量級鎖。隨著鎖的競爭,鎖可以從偏向鎖升級到輕量級鎖,再升級到重量級鎖,并且鎖只能升級不能降級

4、線程池的理解
4.1、線程池工廠創建的4中方法?

阿里巴巴開發手冊上明確寫了不要這樣做,因為通過這種方式創建的線程池阻塞隊列太長,容易造成OOM

  • newCachedThreadPool 創建可緩存的線程池
  • newFixedThreadPool 創建定長的線程池
  • newSingledThreadPool 創建單一線程池執行
  • newScheduedThreadPool 創建一個定長的周期執行的線程池
4.2、任務加入的線程池的流程?

img

4.3、線程池的7個參數?拒絕策略?
// 本質ThreadPoolExecutor()
// 線程池的七大參數
public ThreadPoolExecutor(int corePoolSize,                  // 核心線程池大小int maximumPoolSize,               // 最大核心線程池大小long keepAliveTime,	             // 非核心線程超時了沒有被使用就會釋放TimeUnit unit,	                 // 超時單位BlockingQueue<Runnable> workQueue, // 阻塞隊列ThreadFactory threadFactory,	     // 線程工程創建線程,一般不用動RejectedExecutionHandler handler	 // 拒絕策略) {if (corePoolSize < 0 ||maximumPoolSize <= 0 ||maximumPoolSize < corePoolSize ||keepAliveTime < 0)throw new IllegalArgumentException();if (workQueue == null || threadFactory == null || handler == null)throw new NullPointerException();this.acc = System.getSecurityManager() == null ?null :AccessController.getContext();this.corePoolSize = corePoolSize;this.maximumPoolSize = maximumPoolSize;this.workQueue = workQueue;this.keepAliveTime = unit.toNanos(keepAliveTime);this.threadFactory = threadFactory;this.handler = handler;
}

拒絕策略:

new ThreadPoolExecutor.AbortPolicy()          // 默認的拒絕策略,不處理,拋出異常
new ThreadPoolExecutor.CallerRunsPolicy()     // 拒絕策略,哪來的去哪里
new ThreadPoolExecutor.DiscardPolicy()        // 拒絕策略, 隊列滿了不會拋出異常
new ThreadPoolExecutor.DiscardOldestPolicy()  // 拒絕策略,隊列滿了,嘗試去和最早的競爭,不會拋出異常
4.4、線程池中如何拿到線程的執行結果?

Callable類型的線程。

直接用Future接收線程返回值,或者提交Futuretask類型的線程任務。

// Future 
Callable<String> callable = () -> {Thread.sleep(2000);return Thread.currentThread().getName();};Future<String> future = executor.submit(callable);System.out.println("-------------task1返回結果 : " + future.get());//FutureTaskFutureTask<String> futureTask = new FutureTask<String>(callable);executor.submit(futureTask);Future<String> future1 = executor.submit(callable);System.out.println("-------------futureTask返回結果 : " + futureTask.get());
4.6、線程池的大小該如何去設置?

IO密集型:2 * CPU核心數

CPU密集型:CPU核心數 + 1

4.5、核心工作線程是否會被回收?

線程池中有個allowCoreThreadTimeOut字段能夠描述是否回收核心工作線程,線程池默認是false表示不回收核心線程,我們可以使用allowCoreThreadTimeOut(true)方法來設置線程池回收核心線程。

4.6、線程池創建參數中keepAliveTime的作用

當線程池中的線程數量?于 corePoolSize 的時候,如果這時沒有新的任務 提交,核?線程外的線程不會?即銷毀,?是會等待,直到等待的時間超過了 keepAliveTime 才會被回收銷毀。

非核心線程空閑狀態下的存活時間。

5、你對ThreadLocal了解多少?

每個線程維持一份副本。增刪查改都是對副本操作。

關鍵就是Thread里的這倆變量

【高并發】一文帶你徹底搞懂ThreadLocal-云社區-華為云 (huaweicloud.com)

  /* ThreadLocal values pertaining to this thread. This map is maintained* by the ThreadLocal class. */ThreadLocal.ThreadLocalMap threadLocals = null;/** InheritableThreadLocal values pertaining to this thread. This map is* maintained by the InheritableThreadLocal class.*/ThreadLocal.ThreadLocalMap inheritableThreadLocals = null;

注意:線程池創建的 ThreadLocal要在finally中?動remove,不然會有內存泄漏的風險。

6、為什么我們調? start() ?法時會執? run() ?法,為什么我們不能直接調? run() ?法。

new ?個 Thread,線程進?了新建狀態。調? start() ?法,會啟動?個線程并使線程進?了就緒狀態,當分配到時間?后就可以開始運?了。 start() 會執?線程的相應準備?作,然后?動 執? run() ?法的內容,這是真正的多線程?作。 但是,直接執? run() ?法,會把 run() ?法當成?個 main 線程下的普通?法去執?,并不會在某個線程中執?它,所以這并不是多線程?作。

image-20240324135614004

7、Semophore介紹一下

synchronized 和 ReentrantLock 都是?次只允許?個線程訪問某個資源, Semaphore (信號量)可以指定多個線程同時訪問某個資源。

Semaphore semaphore = new Semaphore(3);
	   @Overridepublic void run() {try {// 獲取許可證,如果沒有許可證了,線程會阻塞semaphore.acquire();System.out.println("Thread " + id + " is accessing the shared resource.");Thread.sleep(1000); // 模擬訪問共享資源的時間System.out.println("Thread " + id + " has finished accessing the shared resource.");} catch (InterruptedException e) {e.printStackTrace();} finally {// 釋放許可證semaphore.release();}}
8、synchronized 和 ReentrantLock 的區別

相似點:

  • 都是互斥鎖

不同點:

  • 原理上:synchronized 是jdk提供的關鍵字,加鎖解鎖由JVM實現,內部使用監視器實現同步;ReentrantLock 是jdk提供的api,內部使用AQS實現,加鎖解鎖需要自己調用方法,更靈活。
  • 公平性:synchronized 是非公平鎖;ReentrantLock 可以通過傳參創建公平鎖。
  • 響應中斷:synchronized是不可中斷類型的鎖,除非加鎖的代碼中出現異常或正常執行完成;ReentrantLock 可以設置超時方法或者將lockInterruptibly()放到代碼塊中,調用interrupt方法進行中斷。
  • 多條件喚醒:synchronized不能綁定; ReentrantLock通過綁定Condition結合await()/singal()方法實現線程的精確喚醒,而不是像synchronized通過Object類的wait()/notify()/notifyAll()方法要么隨機喚醒一個線程要么喚醒全部線程。
9、線程狀態轉換

線程狀態:

可以使用 jstack 命令查看,上面就有線程的狀態。

img

Java8新特性

1、Java8新特性你都用過哪些?
2、如何使用stream找出某一個字段值最大的數據?

int max = list.stream().max(Comparator.comparingInt(i -> i)).get();

JVM

1、JVM都分為哪些模塊?都有什么作用?

在這里插入圖片描述

  • Class loader(類加載器):根據給定的全限定名類名(如:java.lang.Object)來裝載class文件 到運行時數據區中的方法區。
  • Execution engine(執行引擎):執行引擎也叫解釋器,負責解釋命令,交由操作系統執行;JIT編譯器。
  • Native Interface(本地接口):與native libraries交互,是其它編程語言交互的接口。
  • Runtime data area(運行時數據區域):這就是我們常說的JVM的內存,我們所有所寫的程序都被加載到這里,之后才開始運行。
2、類的加載過程是什么樣的?都涉及到哪些模塊?
  1. 加載
    1. 將字節碼文件加載到內存中
  2. 鏈接
    1. 驗證:保證加載的字節碼是合法、合理并符合規范的。
    2. 準備:為類的靜態變量分配內存,并將其初始化為默認值。
    3. 解析:將類、接口、字段和方法的符號引用轉為直接引用。
  3. 初始化
    1. 將靜態變量的賦值和靜態方法封裝為==()方法==,執行。
3、雙親委派與沙箱安全機制(這個我沒有被問到,但是我在回答過程中有提到,面試官沒有順著我的意思問…)

如果一個類加載器在接到加載類的請求時,它首先不會自己嘗試去加載這個類,而是把這個請求任務委托給父類加載器去完成,依次遞歸,如果父類加載器可以完成類加載任務,就成功返回。只有父類加載器無法完成此加載任務時,才自己去加載。

好處:(安全)

image-20210501175529542

?

4、詳細說一下堆?(此處發現面試官想要問垃圾回收機制,可以有意提到一些自己熟悉的知識點)

所有的對象實例以及數組都應當在運行時分配在堆上。

垃圾回收,分代回收。

新生代、老年代

image-20200707080154039

5、垃圾回收算法(不要遺漏分代回收)
  • 標記:引用計數、可達性分析

  • 清除:復制算法、標記-清除算法、標記-壓縮算法

  • 分代:分代收集算法

6、為什么新生代用標記復制?老年代用標記刪除、壓縮?(考察是否理解緣由,而非死記硬背)

根據新生代和老年代的特點來回答。

7、垃圾回收器你知道哪些?
  • Serial 收集器(串行收集器):回收時STW,簡單高效。一般單核CPU才使用。

    image-20200713100703799

  • ParNew 回收器(并行回收):復制算法、STW

    image-20200713102030127

  • Parallel 回收器:復制算法、并行回收和STW,新生代采用Parallel Scavenge收集器(復制算法)、老年代采用Parallel Old收集器(標記-壓縮)

    image-20200713110359441

  • CMS:老年代,標記 - 清除

    image-20200713205154007

    分為四個階段:初始標記、并發標記、重新標記和并發清除。初始標記和重新標記會STW,不過這兩段耗時是最短的。整體上低停頓。

    缺點:

    • 會產生內存碎片,FullGc時才會整理內存碎片。
    • CMS 收集器會消耗CPU,程序吞吐量會下降
    • CMS 收集器無法處理浮動垃圾。在并發標記階段產生的垃圾只能在下一次CMS或FullGc時才能回收
8、如何進行JVM調優?

內存溢出問題:

  1. 通過gc日志和程序日志分析,OOM是什么原因引起的。

  2. 觀察參數是否有不合理的地方。

  3. 調整參數、增大內存再觀察。

  4. 導出內存快照分析是否有內存泄漏問題(要改代碼了)。

對于線上應用如果出現OOM,首先觀察JVM參數設置是否合理。比如堆內存一般設置為容器內存的80%,要給容器預留一些內存,元空間最好加上限制。然后繼續觀察GC日志,觀察老年代的大小變化。

9、觸發Full Gc的情況?
  1. 調用 System.gc()時,系統建議執行 Full GC,但是不必然執行
  2. 老年代空間不足
  3. 方法區空間不足(元空間)
  4. 通過 Minor GC 后進入老年代的平均大小大于老年代的可用內存
  5. 由 Eden 區、survivor space0(From Space)區向 survivor space1(To Space)區復制時,對象大小大于 To Space 可用內存,則把該對象轉存到老年代,且老年代的可用內存小于該對象大小
10、方法區存儲什么信息?

存儲已被虛擬機加載的類型信息、常量、靜態變量、即時編譯器編譯后的代碼緩存等。

?

框架 SSM

1、Spring的IOC和AOP說說你的理解?

2、AOP實現的兩種方式?

3、使用jdk代理和cglib的區別?

4、SpringBean的生命周期

實例化 -> 屬性賦值 -> 初始化 -> 銷毀

5、默認是單例模式,那原因知道嗎?

可以從單例的好處出發回答。

為了提高性能,少創建實例,垃圾回收,緩存快速獲取。

缺點:

所有的請求都共享一個bean實例,不能做到線程安全!

6、單例模式是線程安全的嗎?如果需要保證線程安全該如何做?

餓漢式:由JVM保證線程安全

懶漢式:雙重檢測,單例變量用volatile修飾、靜態內部類、枚舉實現。懶漢式有這三種方式線程安全。

7、Spring如何解決循環依賴?(三級緩存)

spring 循環依賴以及解決方案(吊打面試官)_循環依賴解決方案-CSDN博客

三級緩存。

核心:bean在沒有完全完成創建過程時,會在初始化階段提前把自己暴露到三級緩存中,雖然此時創建流程并未完成,但是其引用不會改變,可以優先滿足其他bean對其產生的依賴。

8、Spring中用到了什么設計模式?(接Java基礎,單例,工廠,原型,模版 jdbcTemplate,策略<多線程拒絕策略>)

9、SpringBoot的作用是什么?

10、SpringBoot如何做到自動配置?

三個注解:

@SpringBootApplication
@EnableAutoConfiguration
@Import(AutoConfigurationImportSelector.class)
// AutoConfigurationImportSelector 類實現了 ImportSelector接口,也就實現了這個接口中的 selectImports方法,該方法主要用于獲取所有符合條件的類的全限定類名,這些類需要被加載到 IoC 容器中。

==核心:==自動讀取 META-INF/spring.factories 文件所有配置的類進行注入。

11、@Component、@Service、@Controller有什么區別?如果在Controller上使用@Service會怎么樣?

沒啥區別。

如果不使用springMVC時,三者使用其實是沒有什么差別的,但如果使用了springMVC,@Controller就被賦予了特殊的含義。

spring會遍歷上面掃描出來的所有bean,過濾出那些添加了注解@Controller的bean,將Controller中所有添加了注解@RequestMapping的方法解析出來封裝成RequestMappingInfo存儲到RequestMappingHandlerMapping中的mappingRegistry。后續請求到達時,會從mappingRegistry中查找能夠處理該請求的方法。

沒用SpringMVC,如果在Controller上使用@Service也是可以的。

12、Restful風格是什么?如何把@RestController換成@Controller會怎么樣?

單獨使? @Controller 不加 @ResponseBody 的話?般使?在要返回?個視圖的情況,這種情況 屬于??傳統的Spring MVC 的應?,對應于前后端不分離的情況。

前后端分離項目中:@RestController = @Controller +@ResponseBody

13、Mybatis中#和$的區別是什么?

14、Mybatis中解析sql是在那一層面完成的?

img

15、分頁是怎么實現,除了使用語句的方式?

16、spring事務的實現原理

在使用Spring框架的時候,可以有兩種實現方式,一種是編程式事務,另一種是聲明式事務。編程式事務需要用戶自定義代碼來控制事務的處理邏輯,類似于分布式事務中的TCC,聲明式事務通過@Transactional注解來實現。

聲明式事務@Transactional是AOP的一個核心體現,當一個方法添加@Transactional后,Spring會基于這個類生成一個代理對象,會將這個代理對象作為Bean,當使用這個代理對象的方法的時候,如果有事務處理,就會先把事務的自動提交給關閉,然后去執行具體的業務邏輯,如果業務邏輯執行沒問題,代理邏就會提交,如果出現任何異常就會回滾。當然,用戶也可以控制對哪些異常情況進行回滾。

注意事項:

  1. 不要在接口上聲明 @Transactional ,而要在具體類的方法上使用 @Transactional 注解,否則注解可能無效。
  2. 將 @Transactional 放置在類級的聲明中會使得所有方法都有事務。影響性能,推薦加在方法實現上。
  3. 使用了 @Transactional的方法,對同一個類里面的方法調用, @Transactional無效。比如有一個類Test,它的一個方法A,A再調用Test本類的方法B(不管B是否public還是private),但A沒有聲明注解事務,而B有。則外部調用A之后,B的事務是不會起作用的。(經常在這里出錯)
  4. 使用了 @Transactional 的方法, 只能是public, @Transactional注解的方法都是被外部其他類調用才有效,故只能是public。道理和上面的有關聯。故在 protected、private 或者 package-visible 的方法上使用 @Transactional 注解,它也不會報錯,但事務無效。

數據庫

1、MyIsam和Innodb的區別?

2、Innodb的事務隔離級別

可重復讀

3、如何實現事務?(MVCC)

image-20240322165512174

undo_log + read view

4、索引是越多越好嗎?為什么?

5、Innodb的索引和MyIsam的索引有什么區別?

6、索引是如何實現的?

7、為什么不用BTree而用B+Tree?

8、那使用索引中,索引失效、索引覆蓋都是什么意思?

索引失效:(無法依據索引使用二分查找)

  • 在索引列上進行運算操作,索引將失效。
  • 字符串類型字段使用時,不加引號,索引將失效。
  • 頭部模糊匹配,索引失效。
  • 用 or 分割開的條件,如果 or 其中一個條件的列沒有索引,那么涉及的索引都不會被用到。
  • MySQL 評估使用索引比全表更慢,則不使用索引。

9、聯合索引該如何使用?ABC的聯合索引,查詢BC會走索引嗎?

10、Mysql查詢時如何根據索引查找?(考察頁、槽)

按頁讀取,進行查詢,再讀入另一頁

11、執行計劃有用過嗎?其中哪些字段需要注意?

12、優化sql的流程

  1. 觀察聯表數量是否太多。太多可以考慮數據冗余或者拆分為多次查詢。
  2. 分析是否用到索引。查看其執行計劃。
  3. 減少查詢的字段

13、剛才提到創建索引,你是如何考慮索引的創建的?

查詢、GROUP BY 、ORDER BY

14、分庫分表你們項目中有涉及到嗎?

有的。shardingJDBC

15、分表如何判斷所需要查詢的數據在哪一張表中?

通過分庫路由和分表路由決定

16、項目中有跨表執行數據操作嗎?具體怎么做的?

沒有。單表查的。沒有創建綁定表,不涉及聯表查詢。

如果要跨表查,可以通過綁定表減少聯表的組合數量。

17、優化limit

當limit偏移量非常大時,會很慢。慢的原因:在系統中需要進行分頁操作的時候,我們通常會使用LIMIT加上偏移量 的辦法實現,同時加上合適的ORDER BY子句。如果有對應的索引,通 常效率會不錯,否則,MySQL需要做大量的文件排序操作。

# 方案一 :返回上次查詢的最大記錄(偏移量)
SELECT id, name FROM employee WHERE id > 10000 LIMIT 10;# 方案二:orderby + 索引
SELECT id, name FROM employee ORDER BY id LIMIT 10000, 10;# 方案三:在業務允許的情況下限制頁數,太靠后的頁不查了,因為絕大多數用戶都不會往后翻太多頁。# 方案四:延遲聯接,通過覆蓋索引優化查詢
# 比如:
SELECT * FROM student WHERE age > 10 LIMIT 10000,10;
# 此時會把所有滿足數據加載進內存,然后拋棄前面10000條。# 延遲聯接優化,此時子查詢會走覆蓋索引查詢需要記錄id,再通過id集合查詢需要的數據
SELECT * FROM student INNER JOIN (SELECT id FROM student WHERE age > 10 LIMIT 10000,10) AS s;

Redis

1、項目主要用Redis做什么?

2、項目中用到最多的數據類型?

3、在使用hash的時候,對于大Key值是如何操作的?

4、如果我要刪除一個hash的value,但是其中的鍵值對很多,如何刪除?

5、那如果值刪除一部分,而不是全部刪除,怎么做?

6、redis緩存機制你了解嗎?

7、RDB和AOF你們公司如何使用的?二者都用嗎還是選擇其一?

8、緩存雪崩、緩存擊穿和緩存穿透你知道嗎?都是什么意思?

緩存雪崩:

現象:緩存在同?時間??積的失效,或者redis服務宕機,后?的請求都直接落到了數據庫上,造成數據庫短時間內承受?量請求。

解決辦法:

  1. 采? Redis 集群,避免單機出現問題整個緩存服務都沒辦法使?。
  2. 限流,避免同時處理?量的請求。

緩存穿透:

現象:緩存穿透說簡單點就是?量請求的 key 根本不存在于緩存中,導致請求直接到了數據庫上,根本沒有經過緩存這?層。舉個例?:某個?客故意制造我們緩存中不存在的 key 發起?量請求,導 致?量請求落到數據庫。

解決辦法:

  1. 做好參數校驗。

  2. 布隆過濾器。(維持一個請求參數的Map)

9、剛剛提到布隆過濾器,你知道布隆過濾器是如何實現的嗎?

10、布隆過濾器的結果一定是準確無誤的嗎?

11、還有其他方式防止緩存穿透嗎?二者區別?

12、緩存雪崩如何解決,或者避免?

13、Redis的過期策略都有哪些?

14、你們有用過集群,主從嗎?

15、哨兵模式是什么,具體說說?

16、那如果哨兵掛了怎么辦?

17、使用集群或者主從是如何保證數據一致性的?

18、緩存一致性問題如何解決?

延遲雙刪:先刪緩存、更新數據庫,延遲T時間后再刪緩存。

不能完全解決。真要一致性,就別查緩存,直接從數據庫查。

19、redis的優缺點

優點:基于內存,操作非常快,而且提供了豐富的數據結構,能幫助我們解決不同的問題。

缺點:水能載舟亦能覆舟。基于內存,意味著斷電數據就沒了,需要一定的持久化策略或者集群部署。另一方面redis單機的性能瓶頸受限于內存大小。

分布式

1、你怎么理解分布式和微服務?

2、你們用的是SpringCloud是吧,那介紹一下SpringCloud都有哪些組件?

注冊中心、Feign、熔斷、網關

3、熔斷是怎么做的?

4、dubbo有用過嗎?(自己沒用過,老實說沒用過就好)

5、分布式中的鎖你知道怎么實現嗎?

6、用Redis實現需要注意什么?(這里較深,需要注意的地方也多,各種原子性,過期時間延長等等)

7、分布式事務是什么?如何實現?

分布式事務有這一篇就夠了! - 知乎 (zhihu.com)

2PC:兩階段提交,有兩種實現基于數據庫 XA 協議和Seata 實現(推薦)。由于 Seata 的 0 侵入性并且解決了傳統 2PC 長期鎖資源的問題,推薦采用 Seata 實現 2PC。

TCC:分為三個階段,業務檢查、確認提交、業務取消,三個階段需要用戶編程實現。這種方式優勢在于,可以讓應用自己定義數據操作的粒度,使得降低鎖沖突、提高吞吐量成為可能

try:
// 業務檢查
confirm:
// 確認提交
cancel:
// 業務取消

8、2PC和TCC可以詳細說一下嗎?

9、最大努力通知這種實現有了解嗎?

10、分布式鎖

image-20240322214035593

其他

1、打包時使用package和install的區別?

2、項目啟動時如何跳過單元測試?

3、單元測試作用是什么?

4、Nexus你了解嗎?

私服。

5、服務部署平時有做嗎?

6、Linux使用多嗎?

消息隊列

【RocketMQ面試題(23道)】-CSDN博客

1、項目組當中用到消息隊列的場景是什么?

2、 那消息丟失和重復你們有遇到過嗎?是如何解決的?

3、Kafka消息是全局有序的嗎?

不是。

4、Kafka如何保證消息有序消費

分區內消費是有序的。

  1. 1 個 Topic 只對應?個 Partition。

  2. (推薦)發送消息的時候指定 key/Partition。

RocketMq順序消息實現方式:

發送端單線程串行發送,接收端每個消費組單線程串行消費,每個消費組的消息發送到同一個隊列中。

5、RocketMQ如何保證消息的可用性/可靠性/不丟失呢?

img

從這三個過程考慮:

生產階段:

通過請求確認機制,來保證消息的可靠傳遞

  1. 同步發送的時候,要注意處理響應結果和異常。如果返回響應OK,表示消息成功發送到了Broker,如果響應失敗,或者發生其它異常,都應該重試。
  2. 異步發送的時候,應該在回調方法里檢查,如果發送失敗或者異常,都應該進行重試。
  3. 如果發生超時的情況,也可以通過查詢日志的API,來檢查是否在Broker存儲成功。

存儲階段:

存儲階段,可以通過配置可靠性優先的 Broker 參數來避免因為宕機丟消息,簡單說就是可靠性優先的場景都應該使用同步

  1. 消息只要持久化到CommitLog(日志文件)中,即使Broker宕機,未消費的消息也能重新恢復再消費。
  2. Broker的刷盤機制:同步刷盤和異步刷盤,不管哪種刷盤都可以保證消息一定存儲在pagecache中(內存中),但是同步刷盤更可靠,它是Producer發送消息后等數據持久化到磁盤之后再返回響應給Producer。
  3. Broker通過主從模式來保證高可用,Broker支持Master和Slave同步復制、Master和Slave異步復制模式,生產者的消息都是發送給Master,但是消費既可以從Master消費,也可以從Slave消費。同步復制模式可以保證即使Master宕機,消息肯定在Slave中有備份,保證了消息不會丟失。

消費階段:

邏輯執行完再發送消費進行確認

  • Consumer保證消息成功消費的關鍵在于確認的時機,不要在收到消息后就立即發送消費確認,而是應該在執行完所有消費業務邏輯之后,再發送消費確認。因為消息隊列維護了消費的位置,邏輯執行失敗了,沒有確認,再去隊列拉取消息,就還是之前的一條。

6、如何處理消息重復的問題呢?

處理消息重復問題,主要有業務端自己保證,主要的方式有兩種:業務冪等消息去重

業務冪等:第一種是保證消費邏輯的冪等性,也就是多次調用和一次調用的效果是一樣的。這樣一來,不管消息消費多少次,對業務都沒有影響。

消息去重:第二種是業務端,對重復的消息就不再消費了。這種方法,需要保證每條消息都有一個唯一的編號,通常是業務相關的,比如訂單號,消費的記錄需要落庫,而且需要保證和消息確認這一步的原子性。可以建立一個消費記錄表,拿到這個消息做數據庫的insert操作。給這個消息做一個唯一主鍵(primary key)或者唯一約束,那么就算出現重復消費的情況,就會導致主鍵沖突,那么就不再處理這條消息。

7、如何實現消息過濾?

8、事務消息的實現

9、死信隊列知道嗎?

死信隊列用于處理無法被正常消費的消息,即死信消息。

一條消息初次消費失敗,消息隊列 RocketMQ 會自動進行消息重試;達到最大重試次數后,若消費依然失敗,則表明消費者在正常情況下無法正確地消費該消息,此時,消息隊列 RocketMQ 不會立刻將消息丟棄,而是將其發送到該消費者對應的特殊隊列中,該特殊隊列稱為死信隊列

死信消息的特點

  • 不會再被消費者正常消費。
  • 有效期與正常消息相同,均為 3 天,3 天后會被自動刪除。因此,需要在死信消息產生后的 3 天內及時處理。

死信隊列的特點

  • 一個死信隊列對應一個 Group ID, 而不是對應單個消費者實例。
  • 如果一個 Group ID 未產生死信消息,消息隊列 RocketMQ 不會為其創建相應的死信隊列。
  • 一個死信隊列包含了對應 Group ID 產生的所有死信消息,不論該消息屬于哪個 Topic。

10.如何保證RocketMQ的高可用?

NameServer因為是無狀態,且不相互通信的,所以只要集群部署就可以保證高可用。

RocketMQ的高可用主要是在體現在Broker的讀和寫的高可用,Broker的高可用是通過集群主從實現的。

11、消息刷盤怎么實現的呢?

RocketMQ提供了兩種刷盤策略:同步刷盤和異步刷盤

  • 同步刷盤:在消息達到Broker的內存之后,必須刷到commitLog日志文件中才算成功,然后返回Producer數據已經發送成功。
  • 異步刷盤:異步刷盤是指消息達到Broker內存后就返回Producer數據已經發送成功,會喚醒一個線程去將數據持久化到CommitLog日志文件中。

計算機網絡

1、 TCP粘包和拆包問題有了解嗎?

面試題:聊聊TCP的粘包、拆包以及解決方案 - 知乎 (zhihu.com)

TCP是面向字節流的。

由于緩沖區的存在,兩個TCP報文被同一個緩沖區接收,就是粘包。一個TCP報文被多個緩沖區接收就是拆包。

對于粘包和拆包問題,常見的解決方案有四種:

  • 發送端將每個包都封裝成固定的長度,比如100字節大小。如果不足100字節可通過補0或空等進行填充到指定長度;
  • 發送端在每個包的末尾使用固定的分隔符,例如\r\n。如果發生拆包需等待多個包發送過來之后再找到其中的\r\n進行合并;例如,FTP協議;
  • 將消息分為頭部和消息體,頭部中保存整個消息的長度,只有讀取到足夠長度的消息之后才算是讀到了一個完整的消息;
  • 通過自定義協議進行粘包和拆包的處理。

Netty對粘包和拆包問題的處理:

  • LineBasedFrameDecoder:以行為單位進行數據包的解碼;
  • DelimiterBasedFrameDecoder:以特殊的符號作為分隔來進行數據包的解碼;
  • FixedLengthFrameDecoder:以固定長度進行數據包的解碼;
  • LenghtFieldBasedFrameDecode:適用于消息頭包含消息長度的協議(最常用);

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/12781.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/12781.shtml
英文地址,請注明出處:http://en.pswp.cn/web/12781.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

瑞_Docker安裝教程(超詳細圖文步驟,含卸載、離線安裝)

文章目錄 1 CentOS 在線安裝 Docker1.1 卸載舊版Docker1.2 安裝Docker1.2.1 安裝Docker的yum庫1.2.2 配置Docker的yum源1.2.3 安裝Docker-CE1.2.4 啟動和校驗&#xff08;開機自啟&#xff09;1.2.5 配置鏡像加速 1.3 安裝 Docker Compose1.4 啟動和校驗&#xff08;開機自啟&a…

Acrel-1000變電站綜合自動化監控系統 實時測控保護、遠動于一體

?一、 系統概述 1.1 概述 Acrel-1000 變電站綜合自動化監控系統&#xff0c;是我司根據電力系統自動化及無人值守的要求&#xff0c;總結國內外的研究和生產的先進經驗&#xff0c;專門研制出的新一代電力監控系統。本系統具有保護、遙測、遙信、遙脈、遙調、遙控功能&#x…

Python代碼:三、讀入字符串

1、題目 從變量輸出開始。請使用input函數讀入一個字符串&#xff0c;然后將其輸出。 2、代碼 import sys ainput() print(a) 3、在sublime運行的結果

DIYGW UniApp可視化工具:低代碼時代的前端開發新體驗

摘要&#xff1a; 隨著技術的不斷發展&#xff0c;前端開發領域也迎來了低代碼時代的浪潮。本文介紹了DIYGW UniApp可視化工具&#xff0c;這款工具以其傻瓜式、拖拽式、模塊化的特性&#xff0c;為前端開發者提供了一個全新的開發體驗。通過DIYGW UniApp&#xff0c;用戶無需深…

公域流量如何引流到私域流量?

公域流量和私域流量是數字營銷中常用的兩種流量類型。公域流量指的是通過搜索引擎、社交媒體等公共平臺獲取的流量&#xff0c;而私域流量則是指企業自身擁有的用戶群體和數據。那么&#xff0c;如何將公域流量引流到私域流量呢&#xff1f;下面我將為您詳細解答。 1、提供有價…

什么是超文本?

超文本&#xff08;Hypertext&#xff09;是一種文本類型&#xff0c;它允許通過鏈接&#xff08;通常稱為超鏈接&#xff09;從一個文檔跳轉到另一個文檔或文檔中的特定部分。這種鏈接機制是萬維網&#xff08;World Wide Web&#xff0c;簡稱Web&#xff09;的核心技術之一。…

HTML5+CSS3 將圖片和文字置于一行

將文字對齊圖片中心的水平位置 今天課堂作業上有一段是要做出文字與圖片在一行且文字對齊圖片的中心位置。課上用inline-block做的&#xff0c;但盒子總是不受控制。于是回來隨便找了個圖片用vertical-align做成功了。 這是原本的樣式&#xff08;加了邊框方便看盒子&#xff…

【數據可視化-05】:Plotly數據可視化寶典

一、引言 數據可視化是機器學習流程中不可或缺的一部分。通過圖形和圖表展示數據&#xff0c;我們可以更直觀地理解數據的分布、趨勢和關聯&#xff0c;從而更有效地進行數據分析、特征工程和模型評估。Plotly是一個功能強大且靈活的數據可視化庫&#xff0c;它提供了豐富的圖表…

WebLogic SSL應用

SSL 安全套接字層(SSL)是通過在客戶端和Web服務器端之間進行身份驗證,并對雙方交換的數據進行加密,從而提供安全連接。 驗證類型: 單向:客戶端驗證Web服務器端證書 雙向:客戶端驗證Web服務器證書, Web服務器驗證客戶端證書 Weblogic Server12c 支持 SSL 3.0 和 TLS1.0 …

5.2 操作系統安裝必備知識

目前操作系統安裝方式接近于全自動化&#xff0c;用戶無需做過多操作就能完成操作系統安裝。但是操作系統安裝也有其復雜的一面&#xff0c;例如固件及分區表的不同就會導致操作系統安裝失敗。本節主要介紹系統安裝的一些必備知識。 5.2.1 BIOS 概述 BIOS(Basic Input/Output …

Python實戰開發及案例分析(22)—— 深度優先

深度優先搜索&#xff08;Depth-First Search, DFS&#xff09;是一種用于遍歷或搜索樹或圖的算法。與廣度優先搜索不同&#xff0c;深度優先搜索盡可能深地遍歷圖的分支&#xff0c;直到找到目標或達到死胡同后才回溯。DFS可以使用遞歸實現或利用棧來進行非遞歸實現。 Python…

量子計算機接入歐洲最快超算!芬蘭加快混合架構算法開發

內容來源&#xff1a;量子前哨&#xff08;ID&#xff1a;Qforepost&#xff09; 文丨浪味仙 排版丨沛賢 深度好文&#xff1a;1900字丨7分鐘閱讀 摘要&#xff1a;芬蘭技術研究中心&#xff08;VTT&#xff09;與 CSC 展開合作&#xff0c;基于量子計算機超算架構進行算法開…

jspXMl標記語言基礎

1.打開命令框進入數據庫 打開eclipse創建需要連接的項目 粘貼驅動程序 查看驅動器 使用sql的包 int代表個 conlm代表列名 <%page import"java.sql.ResultSet"%> <%page import"java.sql.Statement"%> <%page import"java.sql.Connect…

蛋白聚乙二醇化修飾檢測試劑盒

蛋白多肽因其高生物活性、高特異性等優點備受藥物開發商和研究者的青睞。但分子量大、親水性強、穩定性差等劣勢限制了蛋白多肽在臨床上的應用&#xff0c;特別是蛋白多肽作為一種異源蛋白具有很強的免疫原性&#xff0c;容易被機體免疫系統識別并清除&#xff0c;導致藥物的血…

萬物皆可監控(shell腳本監控TIDB-DM和DSG同步狀態)

監控的方式有很多&#xff0c;常用的有zabbix和prometheus平臺&#xff0c;理論上都可以做到對有狀態服務的監控&#xff0c;因為我個人對這兩個監控平臺不是很熟悉&#xff0c;所以一般喜歡使用shell腳本來做監控&#xff1b; 純oracle 數據庫的監控推薦使用EMCC&#xff0c;…

前端面試題日常練-day12 【面試題】

題目 希望這些選擇題能夠幫助您進行前端面試的準備&#xff0c;答案在文末。 1. 在JavaScript中&#xff0c;以下哪個關鍵字用于聲明一個變量&#xff1f; a) letb) varc) constd) all of the above2. 下面哪個方法可以用于將一個字符串轉換為整數&#xff1f; a) toInteger(…

藍橋杯備戰15.完全二叉樹的權值

P8681 [藍橋杯 2019 省 AB] 完全二叉樹的權值 - 洛谷 | 計算機科學教育新生態 (luogu.com.cn) #include<bits/stdc.h> using namespace std; #define endl \n #define int long long const int N 2e510; int a[N]; signed main() {std::ios::sync_with_stdio(0),cin.ti…

C# Winform+Halcon結合標準視覺工具

介紹 winform與halcon結合標準化工具實例 軟件架構 軟件架構說明 基于NET6 WINFORMHALCON 實現標準化視覺檢測工具 集成相機通訊 集成PLC通訊 TCP等常見通訊 支持常見halcon算子 圖形采集blob分析高精度匹配顏色提取找幾何體二維碼提取OCR識別等等 。。。 安裝教程 …

【Kafka】2.深入理解Kafka事件流平臺及其核心概念

1.事件流(Event streaming) 事件流是人體中樞神經系統的數字化的等價物。它是構建“始終在線”世界的技術基礎&#xff0c;在這個世界中&#xff0c;企業越來越多地被定義為軟件化和自動化&#xff0c;而軟件的用戶本身也是軟件。 從技術上講&#xff0c;事件流是從數據庫、傳…

vue2 雙向數據綁定的實現及原理

Oject.defineProperty() 是 JavaScript 中用于定義或修改對象的屬性的方法&#xff0c;可以控制屬性的特性&#xff08;如可枚舉性、可配置性、可寫性等&#xff09; Object.defineProperty(obj, prop, descriptor) obj&#xff1a;要在其上定義屬性的對象。 prop&#xff1a;要…