面試題(長點心吧)

Redis相關

1.rdb和aof比較

​ 每一個redis操做的性能:redis

rdb速度更快,由於rdb針對每一個操做,只是操做內存鍵值對,而後fork子進程按照(900,1;300,10;60,10000)的頻率去作bgsave;
aof針對每一個操做,除了要操做內存鍵值對,而且還要寫到操做系統內存緩存裏(由於這個開銷的存在,因此aof會比rdb慢一點),而後按照(always,everysecond,no)的策略同步到磁盤

​ 數據載入速度:數據庫

rdb直接載入數據,加載到內存便可;
aof須要生成一個僞客戶端,從aof文件中便利全部命令數據,讀取命令數據,並執行命令數據

​ rdb和aof文件大小:緩存

rdb是壓縮的二進制文件,體積比較小;
aof是文本文件,沒有任何壓縮,體積較大,雖然他可能會執行bgrewriteaof,可是仍是不如rdb小

​ rdb和aof的數據完整性:網絡

rdb是按照(900,1;300,10;60,10000)的頻率作備份;
aof是按照(always,everysecond,no)的策略作刷盤備份;
一般aof更新頻率比rdb高,所以,若是同時開啓兩種持久化策略,redis server優先選擇aof文件來還原redis緩存狀態
2.那麼到底應該怎麼選擇rdb和aof呢?生產環節怎麼設置持久化機制呢?

redis4.0新增了一個「混合持久化」,兼顧aof的數據保障和rdb的快速恢復數據;socket

至於以前的版本,知不道了,只能選擇一個來進行數據恢復了,或者rdb文件,或者aof文件函數

# When rewriting the AOF file, Redis is able to use an RDB preamble in the
# AOF file for faster rewrites and recoveries. When this option is turned
# on the rewritten AOF file is composed of two different stanzas:
#
#   [RDB file][AOF tail]
#
# When loading Redis recognizes that the AOF file starts with the "REDIS"
# string and loads the prefixed RDB file, and continues loading the AOF
# tail.
#
# This is currently turned off by default in order to avoid the surprise
# of a format change, but will at some point be used as the default.
aof-use-rdb-preamble no
3.緩存雪崩&緩存穿透

​ 緩存雪崩:性能

事前:保證redis的高可用性,(主從+sentinel+集羣)
 事中:限流+降級,避免MySQL被打死
 過後:保證持久化機制,重啓redis,從新載入備份數據到redis內存

​ 緩存穿透:this

非法請求可能會經過一些數據庫和緩存中都不存在的值,來進行請求,這樣就會致使緩存被穿透,直接打到數據庫上,可是因爲數據庫中有沒有對應的值,致使能夠一直穿透緩存;
一個解決辦法就是給非法的請求在緩存中設置一個相似UNKNOWN的value,這樣下次請求過來就能夠在緩存中獲取到這個請求對應的值,不至於都打到數據庫上。

內存相關

1.內存泄漏的場景?操作系統

1.String#subString
jdk6以及以前版本的String#subString可能會致使內存泄露,由於subString以後和以前都是指向同一個底層char[]的value,這樣的話,若是原先的字符串已經設置爲Null了,可是因爲subString字符串還引用這個底層char[]的value,那char[]中的其它char就沒辦法釋放;
jdk7以後,對subString進行了改進,subString會指向一個新的底層char[]的value,就不影響原來的char[]的釋放了。

2.ThreadLocal
在ThreadLocalMap中的key是弱引用(即當垃圾收集器工做時,不管當前內存是否夠用,都會回收掉所引用關聯的對象),因此咱們在使用ThreadLocal時要及時remove,避免產生內存泄露。

3.監聽器
在釋放對象的時候卻沒有去刪除這些監聽器,增長了內存泄漏的機會。

4.靜態集合類引發內存泄漏
像HashMap、Vector等的使用最容易出現內存泄露,這些靜態變量的生命週期和應用程序一致,他們所引用的全部的對象Object也不能被釋放,由於他們也將一直被Vector等引用着。

5.各類鏈接
好比數據庫鏈接(dataSourse.getConnection()),網絡鏈接(socket)和io鏈接,除非其顯式的調用了其close()方法將其鏈接關閉,不然是不會自動被GC 回收的。

6.單例模式
不正確使用單例模式是引發內存泄漏的一個常見問題,單例對象在初始化後將在JVM的整個生命週期中存在(以靜態變量的方式),若是單例對象持有外部的引用,那麼這個對象將不能被JVM正常回收,致使內存泄漏。

7.使用非靜態內部類
非靜態內部類對象的構建依賴於其外部類,內部類對象會持有外部類對象的this引用,即時外部類對象再也不被使用了,其佔用的內存可能不會被GC回收,由於內部類的生命週期可能比外部類的生命週期要長,從而形成外部類對象不能被及時回收。解決辦法是儘可能使用靜態內部類,靜態內部類只是形式上在外部類的裏面,靜態內部類不會持有外部類的引用,能夠把靜態內部類理解成是一個獨立的類,和外部類沒什麼關係。
    引伸:爲何非靜態內部類對象會持有外部類對象的this引用?
   非靜態內部類雖然和外部類寫在同一個文件中, 可是編譯完成後, 仍是生成各自的class文件,經過以下三個步驟,內部類對象經過this訪問外部類對象的成員。
1) 編譯器自動爲內部類添加一個成員變量, 這個成員變量的類型和外部類的類型相同, 這個成員變量就是指向外部類對象(this)的引用;
2) 編譯器自動爲內部類的構造方法添加一個參數, 參數的類型是外部類的類型, 在構造方法內部使用這個參數爲內部類中添加的成員變量賦值;
3)在調用內部類的構造函數初始化內部類對象時,會默認傳入外部類的引用。
相關文章
相關標籤/搜索