外貿獨立站搭建東莞seo優(yōu)化推廣
目錄
- 1、mysql并發(fā)事務會帶來哪些問題,如何解決?
- 2、請詳細描述Redis持久化機制?
- 3、簡述Redis緩存雪崩和緩存穿透的問題和解決方案?
- 4、RabbitMQ消息丟失及對應解決方案
- 5、什么叫線程安全?舉例說明
- 6、舉例說明常用的加密算法
- 7、synchronized和ReentrantLock有什么區(qū)別?
- 8、synchronized和lock的區(qū)別
- 9、如何保證接口的冪等性
- 10、什么是分布式事務,如何解決
- 11、HashMap的結構和原理是什么
- 12、CurrentHashMap是如何保證線程安全的
- 13、java線程池有哪些參數(shù),都有什么含義
- 14、java 中的volatile關鍵字是干嘛的
- 15、java中垃圾收集的方法有哪些
- 16、什么是類加載器,類加載器有哪些
- 17、什么是雙親委派
- 18、其他常見面試題
1、mysql并發(fā)事務會帶來哪些問題,如何解決?
MySQL的并發(fā)事務可能會帶來以下幾個主要問題:
臟讀(Dirty Read):當一個事務讀取另一個未提交的事務的數(shù)據時,可能會讀取到不一致的數(shù)據。
不可重復讀(Non-repeatable Read):當一個事務在多次讀取同一數(shù)據時,可能會因為另一個并發(fā)的事務修改了數(shù)據而導致讀取到的結果不一致。
幻讀(Phantom Read):當一個事務在多次讀取某一范圍的數(shù)據時,可能會因為另一個并發(fā)的事務插入了新的數(shù)據而導致讀取到的結果不一致。
死鎖(Deadlock):當兩個或更多的事務互相等待對方釋放資源時,會導致事務無法繼續(xù)執(zhí)行。
性能問題:高并發(fā)下,如果事務處理不當,可能會導致數(shù)據庫性能下降,影響整個系統(tǒng)的性能。
解決方案:
臟讀:可以通過設置事務的隔離級別為READ COMMITTED或更高級別來避免臟讀。READ COMMITTED級別會確保只讀取已經提交的事務的數(shù)據。
不可重復讀和幻讀:可以通過設置事務的隔離級別為REPEATABLE READ或SERIALIZABLE來避免不可重復讀和幻讀。REPEATABLE READ級別會確保在一個事務內多次讀取同一數(shù)據時,結果是一致的。SERIALIZABLE級別是最嚴格的隔離級別,會確保并發(fā)事務之間互不干擾。
死鎖:可以通過設置合適的鎖策略和鎖超時時間來避免死鎖。例如,可以設置鎖的獲取順序,避免循環(huán)等待;可以設置鎖的超時時間,避免無限等待。
性能問題:可以通過優(yōu)化數(shù)據庫設計、使用索引、減少鎖的使用、使用樂觀鎖等方式來提高并發(fā)事務的性能。
總的來說,正確地處理并發(fā)事務需要理解它們可能帶來的問題,并根據具體的應用場景和需求選擇合適的解決方案。
2、請詳細描述Redis持久化機制?
Redis的持久化機制指的是將Redis內存中的數(shù)據保存到硬盤中,以便在服務器重啟或者宕機后可以快速地恢復數(shù)據。
Redis支持兩種持久化方式:RDB(Redis DataBase)和AOF(Append Only File)。
RDB持久化機制: 是在指定的時間間隔內生成數(shù)據集的快照(Snapshot)。RDB持久化可以在指定的時間間隔內生成數(shù)據快照,這個時間間隔通??梢杂捎脩粼谂渲梦募羞M行配置。當Redis需要持久化時,它會 fork 出一個子進程,子進程會將內存中的數(shù)據寫入硬盤中的一個臨時文件,當持久化過程完成后,子進程會退出。你可以在配置文件中通過設置rdb_save_time_interval參數(shù)來控制RDB快照的生成時間間隔。
AOF持久化機制: 是記錄Redis的所有寫操作到磁盤中。當Redis重啟時,可以通過執(zhí)行AOF文件中的命令來恢復數(shù)據集。AOF持久化比RDB持久化更加實時,可以保證數(shù)據的實時備份和持久化。你可以在配置文件中通過設置aof_enabled參數(shù)來開啟或關閉AOF持久化,aof_filename參數(shù)來指定AOF文件的名稱,aof_interval參數(shù)來控制AOF文件的寫入時間間隔,aof_no_checksum參數(shù)來禁用或啟用AOF文件的checksum。
在什么情況下選擇使用RDB或AOF持久化,需要根據具體的使用場景和需求進行選擇。如果你的應用需要備份大規(guī)模的數(shù)據,并且需要快速地恢復數(shù)據,那么RDB持久化可能更加適合。如果你的應用需要實時備份數(shù)據,并且需要持久化的數(shù)據比較小,那么AOF持久化可能更加適合。
3、簡述Redis緩存雪崩和緩存穿透的問題和解決方案?
緩存雪崩: 是指當緩存中大量數(shù)據同時過期時,這些請求會同時轉發(fā)到數(shù)據庫,導致數(shù)據庫壓力突然增大,就像雪崩一樣。這種情況通常是由于緩存策略不當所導致的,例如緩存時間設置相同或相近,導致緩存集體失效。
緩存穿透: 是指查詢一個不存在的key,由于緩存和數(shù)據庫中都沒有這個key,因此每次請求都會直接查詢數(shù)據庫,導致數(shù)據庫壓力增大。這種情況通常是由于惡意攻擊或者數(shù)據一致性校驗不嚴謹所導致的。
方式解決:
對應緩存雪崩:在緩存策略中引入隨機過期時間,避免大量緩存同時失效。例如,在原有的失效時間基礎上增加一個隨機值,比如1-5分鐘隨機,這樣每一個緩存的過期時間的重復率就會降低,就很難引發(fā)集體失效的事件。
使用互斥鎖,當緩存失效時,不是立即查詢數(shù)據庫,而是先使用互斥鎖等待一段時間,如果緩存在此期間被更新,則重新獲取緩存數(shù)據;如果沒有被更新,則再查詢數(shù)據庫。
對于緩存穿透:使用布隆過濾器,將存儲的數(shù)據放入布隆過濾器中,每次數(shù)據查詢首先查詢布隆過濾器,如果過濾器中判斷存在,再到緩存查詢,如果沒有,再進入數(shù)據查詢。這樣能大大減輕數(shù)據庫查詢壓力。
緩存空對象,當數(shù)據庫數(shù)據不存在時,將返回的空對象緩存起來,同時設置一個過期時間。這樣在訪問數(shù)據時,將從緩存中獲取,從而保護了數(shù)據庫。但要注意對空值設置過期時間,否則會出現(xiàn)數(shù)據更新后緩存數(shù)據未及時更新的問題。
對熱點數(shù)據進行永不過期處理,即不設置熱點數(shù)據的過期時間。但這只適用于熱點數(shù)據不會頻繁更新的情況。
4、RabbitMQ消息丟失及對應解決方案
(1) RabbitMQ事務機制和confirm模式:
生產者在發(fā)送數(shù)據之前開啟RabbitMQ事務機制,如channel.txSelect,然后發(fā)送消息。如果消息沒有成功被RabbitMQ接收到,那么生產者會收到異常報錯,此時可以回滾事務channel.txRollback,然后重試發(fā)送消息。如果收到了消息,那么可以提交事務channel.txCommit。這種機制類似于數(shù)據庫事務機制,可以保證消息的可靠性傳輸。另外,開啟confirm模式,生產者每次寫的消息都會分配一個唯一的ID,如果寫入了RabbitMQ中,RabbitMQ會回傳一個ack消息,告訴生產者這個消息已經收到,這樣可以避免消息丟失。
(2) Broker消息中間件自身丟失消息解決方案:
創(chuàng)建隊列時設置隊列持久化。在創(chuàng)建隊列時,將持久化參數(shù)設置為true,這樣可以保證RabbitMQ持久化queue的元數(shù)據,即使是RabbitMQ自身出現(xiàn)問題,恢復之后也會自動讀取之前存儲的數(shù)據。
設置消息的deliveryMode為2。在發(fā)送消息時,將deliveryMode設置為2,這樣RabbitMQ會將消息持久化到磁盤上,即使RabbitMQ出現(xiàn)問題,再次重啟后也會從磁盤上恢復queue和里面的數(shù)據。
以上是關于RabbitMQ消息丟失及對應解決方案的相關內容,希望能對你有所幫助。
5、什么叫線程安全?舉例說明
線程安全是指多線程環(huán)境下,一個對象或函數(shù)能夠在多個線程同時訪問的情況下,保證其行為的一致性和正確性。線程安全的主要目標是避免數(shù)據競爭和保證并發(fā)操作的正確性。
例如,一個ArrayList類在添加一個元素時,可能有兩步操作:一是在Items[Size]的位置存放此元素,二是增大Size的值。在單線程環(huán)境下,由于操作是順序執(zhí)行,所以沒有問題。但是在多線程環(huán)境下,如果兩個線程同時執(zhí)行這兩步操作,可能會產生問題。
在這種情況下,一種解決方法是使用同步機制,例如synchronized關鍵字或者Lock對象,來確保在任何時刻只有一個線程可以執(zhí)行ArrayList類的添加元素操作,這樣就可以避免數(shù)據競爭和并發(fā)操作的錯誤。這就是線程安全的一種實現(xiàn)方式。
6、舉例說明常用的加密算法
AES加密算法:全稱Advanced Encryption Standard,也就是高級加密標準,這是一種被廣泛使用的加密算法,可以有效保護敏感信息。
RSA加密算法:這是一種非對稱加密算法,使用公鑰和私鑰兩個密鑰,公鑰用于加密數(shù)據,私鑰用于解密數(shù)據,非常安全,廣泛用于數(shù)據傳輸?shù)葓鼍啊?br /> DES加密算法:全稱Data Encryption Standard,也就是數(shù)據加密標準,這是一種對稱加密算法,被廣泛用于保護敏感信息,但由于其密鑰長度較短,現(xiàn)在已經被認為不夠安全。
SHA-1和SHA-256加密算法:SHA是安全哈希算法,主要用于生成消息摘要,也就是將輸入的數(shù)據通過哈希算法生成一個固定長度的字符串,無法逆向生成原始數(shù)據。SHA-1和SHA-256是SHA算法的不同版本,SHA-256因為其安全性更高而被更廣泛使用。
RSA-SHA256混合加密算法:這是一種將SHA-256和RSA兩種算法結合使用的加密方式,先用RSA算法生成一個簽名,然后用SHA-256對數(shù)據進行摘要處理,同時用RSA公鑰對SHA-256生成的摘要進行加密,可以同時實現(xiàn)簽名和加密雙重保護。
MD5加密算法:MD5的全稱是Message-Digest Algorithm 5,它可以將任意長度的“字節(jié)串”變換成一個128位的大整數(shù),并且它是一個不可逆的字符串變換算法。即使你看到源程序和算法描述,也無法將一個MD5的值變換回原始的字符串。
7、synchronized和ReentrantLock有什么區(qū)別?
(1) 用法的不同:synchronized是Java語言內置的關鍵詞,由Java語言自動支持;而ReentrantLock是java.util.concurrent.locks包中的類,需要手動創(chuàng)建對象進行使用。
(2)鎖的獲取和釋放:synchronized是隱式獲取和釋放鎖,而ReentrantLock需要顯式地調用方法來獲取和釋放鎖。
(3)線程中斷響應:synchronized不支持線程中斷,當線程處于synchronized塊中時,不能響應中斷;而ReentrantLock支持線程中斷,可以在鎖被持有期間響應中斷。
(4)鎖的級別:synchronized是JVM級別的,而ReentrantLock是API級別的。synchronized是Java語言內置的,所有的Java代碼都可以使用;而ReentrantLock需要手動實現(xiàn),使用起來相對較復雜。
(5)公平性:synchronized不具有公平性,無法保證鎖的獲取順序;而ReentrantLock可以通過構造函數(shù)參數(shù)來設定公平性,有公平鎖和非公平鎖兩種模式。
(6)等待可中斷性:synchronized在發(fā)生異常時,會自動釋放線程占有的鎖,因此不會導致死鎖現(xiàn)象發(fā)生;而Lock在發(fā)生異常時,如果沒有主動通過unLock()去釋放鎖,則很可能造成死鎖現(xiàn)象,因此使用Lock時需要在finally塊中釋放鎖。
(7)鎖的底層實現(xiàn):synchronized和ReentrantLock底層實現(xiàn)方式不同。synchronized是使用樂觀并發(fā)策略實現(xiàn)的,而ReentrantLock是使用悲觀并發(fā)策略實現(xiàn)的。
參考:synchronized和ReentrantLock有什么區(qū)別
8、synchronized和lock的區(qū)別
區(qū)別:
1.synchronized是關鍵字,Lock是接口;
2.synchronized是隱式的加鎖,lock是顯式的加鎖;
3.synchronized可以作用于方法上,lock只能作用于方法塊;
4.synchronized底層采用的是objectMonitor,lock采用的AQS;
5.synchronized是阻塞式加鎖,lock是非阻塞式加鎖支持可中斷式加鎖,支持超時時間的加鎖;
6.synchronized在進行加鎖解鎖時,只有一個同步隊列和一個等待隊列, lock有一個同步隊列,可以有多個等待隊列;
7.synchronized只支持非公平鎖,lock支持非公平鎖和公平鎖;
8.synchronized使用了object類的wait和notify進行等待和喚醒, lock使用了condition接口進行等待和喚醒(await和signal);
9.lock支持個性化定制, 使用了模板方法模式,可以自行實現(xiàn)lock方法;
參考:synchronized和lock的區(qū)別
9、如何保證接口的冪等性
冪等性:指的是同一操作執(zhí)行多次時,結果是相同的,不會產生副作用或重復操作。
- 在接口中添加冪等性檢查邏輯。例如,對于更新操作,可以在接口中檢查傳入的參數(shù)是否與當前資源的狀態(tài)一致,如果不一致則返回錯誤。
- 使用樂觀鎖或者悲觀鎖來防止并發(fā)操作導致的問題。樂觀鎖通過在數(shù)據行中添加一個版本號來實現(xiàn),每次更新都會增加版本號。悲觀鎖則是通過鎖定數(shù)據行來實現(xiàn),只有一個線程可以執(zhí)行更新操作。
- 在數(shù)據庫層面保證冪等性。例如,使用數(shù)據庫的唯一約束來保證創(chuàng)建操作的冪等性。
- 使用令牌桶或者漏桶算法限制接口的調用頻率,防止由于客戶端的重復請求導致的問題。
- 對于需要多次請求的操作,可以使用分布式事務來保證操作的原子性。
參考:怎么保證 java 語言接口的冪等性?
10、什么是分布式事務,如何解決
分布式事務:在分布式系統(tǒng)中一次操作需要由多個服務協(xié)同完成,這種由不同的服務之間通過網絡協(xié)同完成的事務稱為分布式事務。例如:小明給張三轉賬100,A服務器上要先去A數(shù)據庫扣100,然后B服務器上B數(shù)據庫加100,兩個操作要么都成功,要么都失敗。
常見的分布式事務解決有:TCC、本地事務表、MQ事務消息等。
參考:七種常見分布式事務詳解
11、HashMap的結構和原理是什么
HashMap 基于 Map 接口實現(xiàn),元素以鍵值對的方式存儲,并且允許使用null建和null值,因為key不允許重復,因此只能有一個鍵為 null,另外 HashMap 不能保證放入元素的順序,它是無序的,和放入的順序并不能相同。HashMap是線程不安全的。
jdk1.7 底層實現(xiàn)是 數(shù)組 + 鏈表
jdk1.8 底層實現(xiàn)是 數(shù)組+鏈表+紅黑樹 。如果哈希表單向鏈表中元素超過8個,那么單向鏈表這種數(shù)據結構會變成紅黑樹數(shù)據結構。當紅黑樹上的節(jié)點數(shù)量小于6個,會重新把紅黑樹變成單向鏈表數(shù)據結構。
參考:HashMap底層實現(xiàn)原理解析
12、CurrentHashMap是如何保證線程安全的
鎖分段技術:HashTable容器在競爭激烈的并發(fā)環(huán)境下表現(xiàn)出效率低下的原因是所有訪問HashTable的線程都必須競爭同一把鎖,同個對象鎖,那假如容器里有多把鎖,每一把鎖用于鎖容器其中一部分數(shù)據,那么當多線程訪問容器里不同數(shù)據段的數(shù)據時,線程間就不會存在鎖競爭,從而可以有效的提高并發(fā)訪問效率,這就是ConcurrentHashMap所使用的鎖分段技術,首先將數(shù)據分成一段一段的存儲,然后給每一段數(shù)據配一把鎖,當一個線程占用鎖訪問其中一個段數(shù)據的時候,其他段的數(shù)據也能被其他線程訪問。ConcurrentHashMap使用分段鎖Segment來保護不同段的數(shù)據,Segment繼承ReentrantLock實現(xiàn)鎖的功能。
參考:java——CurrentHashMap
ConcurrentHashMap是如何保證線程安全的
13、java線程池有哪些參數(shù),都有什么含義
參考:線程池七大參數(shù)
14、java 中的volatile關鍵字是干嘛的
在 Java 中,volatile 是一個關鍵字,用于聲明變量。volatile 變量的作用是確保被聲明的變量在多個線程之間的可見性、有序性和禁止重排序,從而實現(xiàn)線程安全的操作。
具體來說,當一個變量被聲明為 volatile 時,volatile 變量的寫操作會立即刷新到主內存,而讀操作會從主內存中讀取最新值,而非從本地線程緩存中讀取。
需要注意的是,雖然 volatile 變量可以保證可見性和禁止指令重排,但它并不能保證線程安全,因為它只保證了可見性和有序性,而不保證原子性。對于一些需要多個操作才能完成的操作,比如 i++ 這樣的自增操作,就不能簡單地使用 volatile關鍵字來保證線程安全,需要使用更為嚴格的同步機制,比如synchronized 關鍵字或 Lock 接口。
15、java中垃圾收集的方法有哪些
(1)、標記-清除
這是垃圾收集算法中最基礎的,根據名字就可以知道,它的思想就是標記哪些要被回收的對象,然后統(tǒng)一回收。這種方法很簡單,但是會有兩個主要問題:1.效率不高,標記和清除的效率都很低;2.會產生大量不連續(xù)的內存碎片,導致以后程序在分配較大的對象時,由于沒有充足的連續(xù)內存而提前觸發(fā)一次GC動作。
(2)、復制算法
為了解決效率問題,復制算法將可用內存按容量劃分為相等的兩部分,然后每次只使用其中的一塊,當一塊內存用完時,就將還存活的對象復制到第二塊內存上,然后一次性清楚完第一塊內存,再將第二塊上的對象復制到第一塊。但是這種方式,內存的代價太高,每次基本上都要浪費一般的內存。 于是將該算法進行了改進,內存區(qū)域不再是按照1:1去劃分,而是將內存劃分為8:1:1三部分,較大那份內存交Eden區(qū),其余是兩塊較小的內存區(qū)叫Survior區(qū)。每次都會優(yōu)先使用Eden區(qū),若Eden區(qū)滿,就將對象復制到第二塊內存區(qū)上,然后清除Eden區(qū),如果此時存活的對象太多,以至于Survivor不夠時,會將這些對象通過分配擔保機制復制到老年代中。(java堆又分為新生代和老年代)
(3)、標記-整理
該算法主要是為了解決標記-清除,產生大量內存碎片的問題;當對象存活率較高時,也解決了復制算法的效率問題。它的不同之處就是在清除對象的時候現(xiàn)將可回收對象移動到一端,然后清除掉端邊界以外的對象,這樣就不會產生內存碎片了。
(4)、分代收集
現(xiàn)在的虛擬機垃圾收集大多采用這種方式,它根據對象的生存周期,將堆分為新生代和老年代。在新生代中,由于對象生存期短,每次回收都會有大量對象死去,那么這時就采用復制算法。老年代里的對象存活率較高,沒有額外的空間進行分配擔保,所以可以使用標記-整理 或者 標記-清除。
參考:堆內存分配及回收策略
16、什么是類加載器,類加載器有哪些
類加載器是實現(xiàn)通過類的權限定名獲取該類的二進制字節(jié)流的代碼塊。在Java中,類加載器主要有四種類型:
- 啟動類加載器:負責加載Java核心類庫,無法被Java程序直接引用。
- 擴展類加載器:類似于加載Java的擴展庫,Java虛擬機提供一個擴展庫目錄,該類加載器在此目錄里面查找并加載Java類。
- 系統(tǒng)類加載器:根據Java應用的類路徑來加載Java類,主要是加載自己寫的那些類,可以通過ClassLoader.getSystemClassLoader()來獲取它。
- 自定義加載器:用戶自己定義的類加載器。
17、什么是雙親委派
雙親委派(雙親優(yōu)先)是Java類加載器的一種工作機制,用于保護Java程序的安全性和穩(wěn)定性。
根據雙親委派模型,當一個類加載器需要加載某個類時,它首先將這個任務委派給它的父類加載器,只有當父加載器無法加載時,才由該加載器自己嘗試加載。如果都無法加載,會委派給引導類加載器(Bootstrap Class Loader)進行加載。
雙親委派的好處在于,它能夠保證Java虛擬機中的類的一致性和安全性,避免了不同類加載器之間可能出現(xiàn)的沖突和錯誤。同時,雙親委派模型也提高了Java虛擬機的性能和效率,因為它避免了不必要的類加載和重復加載。
18、其他常見面試題
(1)Java面試題及答案整理
(2)JAVA 面試題經典
(3)Java面試題及答案整理
(4)[史上最全Java面試題](https://www.cnblogs.com/aademeng/articles/11104249.html)
(5)技術面試題–java基礎
(6)我掏空了各大搜索引擎,給你整理了199道Java面試題,滿滿干貨記得收藏
(7)Java 面試知識
(8)21道Java基礎大廠面試題匯總
(9)大廠面試題系列
(10)MySQL必看15道面試題