一、memcached與redis的區(qū)別?
1.存儲方式不同。memcached把數(shù)據(jù)全部存在內(nèi)存之中,斷電之后會掛掉,而redis雖然也用到了內(nèi)存,但是會有部分數(shù)據(jù)存在硬盤中,保證數(shù)據(jù)持久性。
2.數(shù)據(jù)支持類型不同。memcached對數(shù)據(jù)支持比較簡單,而redis支持數(shù)據(jù)類型較豐富,如string、list、set、sorted set、hash。
3.底層實現(xiàn)不同。一般調(diào)用系統(tǒng)函數(shù),會消耗比較多的時間去請求,redis自己構(gòu)建了vm,速度會更快。
二、redis數(shù)據(jù)的淘汰策略?
1.volatile-lru:從已經(jīng)設(shè)置過期時間的數(shù)據(jù)集中,挑選最近最少使用的數(shù)據(jù)淘汰。
2.volatile-ttl:從已經(jīng)設(shè)置過期時間的數(shù)據(jù)集中,挑選即將要過期的數(shù)據(jù)淘汰。
3.volatile-random:從已經(jīng)設(shè)置過期時間的數(shù)據(jù)集中,隨機挑選數(shù)據(jù)淘汰。
4.allkeys-lru:從所有的數(shù)據(jù)集中,挑選最近最少使用的數(shù)據(jù)淘汰。
5.allkeys-random:從所有的數(shù)據(jù)集中,隨機挑選數(shù)據(jù)淘汰。
6。no-enviction:禁止淘汰數(shù)據(jù)。
三、為什么redis把所有數(shù)據(jù)都放到內(nèi)存中?
redis為了達到最快的讀寫速度,將數(shù)據(jù)都讀到內(nèi)存中,并通過異步的方式將數(shù)據(jù)寫入磁盤。如果不將數(shù)據(jù)放在內(nèi)存中,磁盤IO速度會嚴重影響redis的性能。
四、redis的并發(fā)競爭問題如何解決?
首先redis為單進程單線程模式,采用隊列模式將并發(fā)訪問變?yōu)榇性L問。redis本身時沒有鎖的概念的,redis對多個客戶端連接并不存在競爭,但是在Jedis客戶端對redis進行并發(fā)訪問時會產(chǎn)生一系列問題,這些問題時由于客戶端連接混亂造成的。有兩種方案解決。
1.在客戶端,對連接進行池化,同時對客戶端讀寫redis操作采用內(nèi)部鎖synchronized。
2.在服務(wù)器角度,利用setnx實現(xiàn)鎖。
五、redis過期鍵的刪除策略?
1.定時刪除:在設(shè)置鍵的過期時間的同時,創(chuàng)建一個timer,讓定時器在鍵的過期時間到達時,立即執(zhí)行對鍵的刪除操作。(主動刪除)
對內(nèi)存友好,但是對cpu時間不友好,有較多過期鍵的而情況下,刪除過期鍵會占用相當一部分cpu時間。
2.惰性刪除:放任過期鍵不管,但是每次從鍵空間中獲取鍵時,都檢查取到的鍵是否過去,如果過期就刪除,如果沒過期就返回該鍵。(被動刪除)
對cpu時間友好,程序只會在取出鍵的時候才會對鍵進行過期檢查,這不會在刪除其他無關(guān)過期鍵上花費任何cpu時間,但是如果一個鍵已經(jīng)過期,而這個鍵又保留在數(shù)據(jù)庫中,那么只要這個過期鍵不被刪除,他所占用的內(nèi)存就不會釋放,對內(nèi)存不友好。
3.定期刪除:每隔一段時間就對數(shù)據(jù)庫進行一次檢查,刪除里面的過期鍵。(主動刪除)
采用對內(nèi)存和cpu時間折中的方法,每個一段時間執(zhí)行一次刪除過期鍵操作,并通過限制操作執(zhí)行的時長和頻率來減少對cpu時間的影響。難點在于,選擇一個好的策略來設(shè)置刪除操作的時長和執(zhí)行頻率。
六、redis與一般db的同步過程?
有兩種方式。
第一種,先去redis中判斷數(shù)據(jù)是否存在,如果存在,則直接返回緩存好的數(shù)據(jù),如果不存在,去db中讀取數(shù)據(jù),并把數(shù)據(jù)緩存一份到redis中。適用與數(shù)據(jù)里比較大,但是不經(jīng)常更新的情況,如用戶排行。
第二種,先去redis中判斷數(shù)據(jù)是否存在,如果存在,則直接更新對應(yīng)數(shù)據(jù)(這一步會記錄下更新的key,并把更新后的數(shù)據(jù)返回給頁面,如果不存在,先去數(shù)據(jù)庫中更新內(nèi)容,然后把數(shù)據(jù)保存一份到redis中。再往后,后臺會進行一系列操作,把redis中更新的key讀取出來,找到數(shù)據(jù)庫中對應(yīng)的數(shù)據(jù),并更新數(shù)據(jù)庫。這種方式是把redis當作數(shù)據(jù)庫使用,適合大數(shù)據(jù)的頻繁變動。但是對redis的依賴很大,要做好掛掉之后的數(shù)據(jù)備份。
七、簡述redis的哨兵模式
哨兵是對redis進行實時的監(jiān)控,主要有兩個功能。
1.監(jiān)測主數(shù)據(jù)庫和從數(shù)據(jù)庫是否正常運行。2.當主數(shù)據(jù)庫出現(xiàn)故障的時候,可以自動將一個從數(shù)據(jù)庫轉(zhuǎn)換為主數(shù)據(jù)庫,實現(xiàn)自動切換。
八、redis的哨兵的監(jiān)控機制是怎樣的?
哨兵監(jiān)控也是有集群的,會有多個哨兵進行監(jiān)控,當判斷發(fā)生故障的哨兵達到一定數(shù)量的時候才進行修復(fù)。一個健壯的部署至少需要三個哨兵實例。
每個Sentinel以每秒鐘一次的頻率向它所知的Master,Slave以及其他 Sentinel 實例發(fā)送一個 PING 命令
2.如果一個實例(instance)距離最后一次有效回復(fù) PING 命令的時間超過 down-after-milliseconds 選項所指定的值, 則這個實例會被 Sentinel 標記為主觀下線。
3.如果一個Master被標記為主觀下線,則正在監(jiān)視這個Master的所有 Sentinel 要以每秒一次的頻率確認Master的確進入了主觀下線狀態(tài)。
4.當有足夠數(shù)量的 Sentinel(大于等于配置文件指定的值)在指定的時間范圍內(nèi)確認Master的確進入了主觀下線狀態(tài), 則Master會被標記為客觀下線
5.在一般情況下, 每個 Sentinel 會以每 10 秒一次的頻率向它已知的所有Master,Slave發(fā)送 INFO 命令
6.當Master被 Sentinel 標記為客觀下線時,Sentinel 向下線的 Master 的所有 Slave 發(fā)送 INFO 命令的頻率會從 10 秒一次改為每秒一次
7.若沒有足夠數(shù)量的 Sentinel 同意 Master 已經(jīng)下線, Master 的客觀下線狀態(tài)就會被移除。若 Master 重新向 Sentinel 的 PING 命令返回有效回復(fù), Master 的主觀下線狀態(tài)就會被移除。
擴展閱讀
企業(yè)面試中關(guān)于MYSQL重點的28道面試題解答