Redis(Remote Dictionary Server) 是一個使用 C 語言編寫的,開源的(BSD許可)高性能非關系型(NoSQL)的鍵值對數據庫嗤栓。
Redis 可以存儲鍵和五種不同類型的值之間的映射冻河。鍵的類型只能為字符串,值支持五種數據類型:字符串茉帅、列表叨叙、集合、散列表堪澎、有序集合擂错。
與傳統(tǒng)數據庫不同的是 Redis 的數據是存在內存中的,所以讀寫速度非秤8颍快钮呀,因此 redis 被廣泛應用于緩存方向剑鞍,每秒可以處理超過 10萬次讀寫操作,是已知性能最快的Key-Value DB爽醋。另外蚁署,Redis 也經常用來做分布式鎖。除此之外蚂四,Redis 支持事務 光戈、持久化、LUA腳本遂赠、LRU驅動事件久妆、多種集群方案。
今天就來講講Redis 的面試題解愤,為復工后的面試做好準備镇饺。
概述
1、Redis有哪些優(yōu)缺點
優(yōu)點
讀寫性能優(yōu)異送讲, Redis能讀的速度是110000次/s奸笤,寫的速度是81000次/s。
支持數據持久化哼鬓,支持AOF和RDB兩種持久化方式监右。
支持事務,Redis的所有操作都是原子性的异希,同時Redis還支持對幾個操作合并后的原子性執(zhí)行健盒。
數據結構豐富,除了支持string類型的value外還支持hash称簿、set扣癣、zset、list等數據結構憨降。
支持主從復制父虑,主機會自動將數據同步到從機,可以進行讀寫分離授药。
缺點
數據庫容量受到物理內存的限制士嚎,不能用作海量數據的高性能讀寫,因此Redis適合的場景主要局限在較小數據量的高性能操作和運算上悔叽。
Redis 不具備自動容錯和恢復功能莱衩,主機從機的宕機都會導致前端部分讀寫請求失敗,需要等待機器重啟或者手動切換前端的IP才能恢復娇澎。
主機宕機笨蚁,宕機前有部分數據未能及時同步到從機,切換IP后還會引入數據不一致的問題,降低了系統(tǒng)的可用性赚窃。
Redis 較難支持在線擴容册招,在集群容量達到上限時在線擴容會變得很復雜。為避免這一問題勒极,運維人員在系統(tǒng)上線時必須確保有足夠的空間是掰,這對資源造成了很大的浪費。
2辱匿、為什么要用 Redis /為什么要用緩存
主要從“高性能”和“高并發(fā)”這兩點來看待這個問題键痛。
高性能:
假如用戶第一次訪問數據庫中的某些數據。這個過程會比較慢匾七,因為是從硬盤上讀取的絮短。將該用戶訪問的數據存在數緩存中,這樣下一次再訪問這些數據的時候就可以直接從緩存中獲取了昨忆。操作緩存就是直接操作內存丁频,所以速度相當快。如果數據庫中的對應數據改變的之后邑贴,同步改變緩存中相應的數據即可席里!
高并發(fā):
直接操作緩存能夠承受的請求是遠遠大于直接訪問數據庫的,所以我們可以考慮把數據庫中的部分數據轉移到緩存中去拢驾,這樣用戶的一部分請求會直接到緩存這里而不用經過數據庫奖磁。
3、為什么要用 Redis 而不用 map/guava 做緩存?
緩存分為本地緩存和分布式緩存繁疤。以 Java 為例咖为,使用自帶的 map 或者 guava 實現的是本地緩存,最主要的特點是輕量以及快速稠腊,生命周期隨著 jvm 的銷毀而結束躁染,并且在多實例的情況下,每個實例都需要各自保存一份緩存架忌,緩存不具有一致性褐啡。
使用 redis 或 memcached 之類的稱為分布式緩存,在多實例的情況下鳖昌,各實例共用一份緩存數據,緩存具有一致性低飒。缺點是需要保持 redis 或 memcached服務的高可用许昨,整個程序架構上較為復雜。
4褥赊、Redis為什么這么快
1)完全基于內存糕档,絕大部分請求是純粹的內存操作,非常快速速那。數據存在內存中俐银,類似于 HashMap,HashMap 的優(yōu)勢就是查找和操作的時間復雜度都是O(1)端仰;
2)數據結構簡單捶惜,對數據操作也簡單,Redis 中的數據結構是專門進行設計的荔烧;
3)采用單線程吱七,避免了不必要的上下文切換和競爭條件,也不存在多進程或者多線程導致的切換而消耗 CPU鹤竭,不用去考慮各種鎖的問題踊餐,不存在加鎖釋放鎖操作,沒有因為可能出現死鎖而導致的性能消耗臀稚;
4)使用多路 I/O 復用模型吝岭,非阻塞 IO;
5使用底層模型不同吧寺,它們之間底層實現方式以及與客戶端之間通信的應用協議不一樣窜管,Redis 直接自己構建了 VM 機制 ,因為一般的系統(tǒng)調用系統(tǒng)函數的話撮执,會浪費一定的時間去移動和請求微峰;
數據類型
5、Redis有哪些數據類型
Redis主要有5種數據類型抒钱,包括String蜓肆,List,Set谋币,Zset仗扬,Hash,滿足大部分的使用要求
6蕾额、Redis的應用場景
總結一
計數器:可以對 String 進行自增自減運算早芭,從而實現計數器功能。Redis 這種內存型數據庫的讀寫性能非常高诅蝶,很適合存儲頻繁讀寫的計數量退个。
緩存:將熱點數據放到內存中,設置內存的最大使用量以及淘汰策略來保證緩存的命中率调炬。
會話緩存:可以使用 Redis 來統(tǒng)一存儲多臺應用服務器的會話信息语盈。當應用服務器不再存儲用戶的會話信息,也就不再具有狀態(tài)缰泡,一個用戶可以請求任意一個應用服務器刀荒,從而更容易實現高可用性以及可伸縮性。
全頁緩存(FPC):除基本的會話token之外,Redis還提供很簡便的FPC平臺缠借。以Magento為例干毅,Magento提供一個插件來使用Redis作為全頁緩存后端。此外泼返,對WordPress的用戶來說硝逢,Pantheon有一個非常好的插件 wp-redis,這個插件能幫助你以最快速度加載你曾瀏覽過的頁面符隙。
查找表:例如 DNS 記錄就很適合使用 Redis 進行存儲趴捅。查找表和緩存類似,也是利用了 Redis 快速的查找特性霹疫。但是查找表的內容不能失效拱绑,而緩存的內容可以失效,因為緩存不作為可靠的數據來源丽蝎。
消息隊列(發(fā)布/訂閱功能):List 是一個雙向鏈表猎拨,可以通過 lpush 和 rpop 寫入和讀取消息。不過最好使用 Kafka屠阻、RabbitMQ 等消息中間件红省。
分布式鎖實現:在分布式場景下,無法使用單機環(huán)境下的鎖來對多個節(jié)點上的進程進行同步国觉“墒眩可以使用 Redis 自帶的 SETNX 命令實現分布式鎖,除此之外麻诀,還可以使用官方提供的 RedLock 分布式鎖實現痕寓。
其它:Set 可以實現交集、并集等操作蝇闭,從而實現共同好友等功能呻率。ZSet 可以實現有序性操作,從而實現排行榜等功能呻引。
總結二
Redis相比其他緩存礼仗,有一個非常大的優(yōu)勢,就是支持多種數據類型逻悠。
數據類型說明string字符串元践,最簡單的k-v存儲hashhash格式,value為field和value童谒,適合ID-Detail這樣的場景单旁。list簡單的list,順序列表惠啄,支持首位或者末尾插入數據set無序list,查找速度快,適合交集撵渡、并集融柬、差集處理sorted set有序的set
其實,通過上面的數據類型的特性趋距,基本就能想到合適的應用場景了粒氧。
string——適合最簡單的k-v存儲,類似于memcached的存儲結構节腐,短信驗證碼外盯,配置信息等,就用這種類型來存儲翼雀。
hash——一般key為ID或者唯一標示饱苟,value對應的就是詳情了。如商品詳情狼渊,個人信息詳情箱熬,新聞詳情等。
list——因為list是有序的狈邑,比較適合存儲一些有序且數據相對固定的數據城须。如省市區(qū)表、字典表等米苹。因為list是有序的糕伐,適合根據寫入的時間來排序,如:最新的***蘸嘶,消息隊列等良瞧。
set——可以簡單的理解為ID-List的模式,如微博中一個人有哪些好友亏较,set最牛的地方在于莺褒,可以對兩個set提供交集、并集雪情、差集操作遵岩。例如:查找兩個人共同的好友等。
Sorted Set——是set的增強版本巡通,增加了一個score參數尘执,自動會根據score的值進行排序。比較適合類似于top 10等不根據插入的時間來排序的數據宴凉。
如上所述誊锭,雖然Redis不像關系數據庫那么復雜的數據結構,但是弥锄,也能適合很多場景丧靡,比一般的緩存數據結構要多蟆沫。了解每種數據結構適合的業(yè)務場景,不僅有利于提升開發(fā)效率温治,也能有效利用Redis的性能饭庞。
持久化
7、什么是Redis持久化?
持久化就是把內存的數據寫到磁盤中去,防止服務宕機了內存數據丟失藐不。
8程梦、Redis 的持久化機制是什么?各自的優(yōu)缺點?
Redis 提供兩種持久化機制 RDB(默認) 和 AOF 機制:
RDB:是Redis DataBase縮寫快照
RDB是Redis默認的持久化方式。按照一定的時間將內存的數據以快照的形式保存到硬盤中,對應產生的數據文件為dump.rdb若债。通過配置文件中的save參數來定義快照的周期。
優(yōu)點:
1本今、只有一個文件 dump.rdb拆座,方便持久化。
2冠息、容災性好挪凑,一個文件可以保存到安全的磁盤。
3逛艰、性能最大化躏碳,fork 子進程來完成寫操作,讓主進程繼續(xù)處理命令散怖,所以是 IO 最大化菇绵。使用單獨子進程來進行持久化,主進程不會進行任何 IO 操作镇眷,保證了 redis 的高性能
4.相對于數據集大時咬最,比 AOF 的啟動效率更高。
缺點:
1欠动、數據安全性低永乌。RDB 是間隔一段時間進行持久化,如果持久化之間 redis 發(fā)生故障具伍,會發(fā)生數據丟失翅雏。所以這種方式更適合數據要求不嚴謹的時候)
2、AOF(Append-only file)持久化方式:是指所有的命令行記錄以 redis 命令請 求協議的格式完全持久化存儲)保存為 aof 文件人芽。
AOF:持久化
AOF持久化(即Append Only File持久化)望几,則是將Redis執(zhí)行的每次寫命令記錄到單獨的日志文件中,當重啟Redis會重新將持久化的日志中文件恢復數據萤厅。
當兩種方式同時開啟時橄抹,數據恢復Redis會優(yōu)先選擇AOF恢復靴迫。
優(yōu)點:
1、數據安全楼誓,aof 持久化可以配置 appendfsync 屬性矢劲,有 always,每進行一次 命令操作就記錄到 aof 文件中一次慌随。
2、通過 append 模式寫文件躺同,即使中途服務器宕機阁猜,可以通過 redis-check-aof 工具解決數據一致性問題。
3蹋艺、AOF 機制的 rewrite 模式剃袍。AOF 文件沒被 rewrite 之前(文件過大時會對命令 進行合并重寫),可以刪除其中的某些命令(比如誤操作的 flushall))
缺點:
1捎谨、AOF 文件比 RDB 文件大民效,且恢復速度慢。
2涛救、數據集大的時候畏邢,比 rdb 啟動效率低。
優(yōu)缺點是什么检吆?
AOF文件比RDB更新頻率高舒萎,優(yōu)先使用AOF還原數據。
AOF比RDB更安全也更大
RDB性能比AOF好
如果兩個都配了優(yōu)先加載AOF
9蹭沛、如何選擇合適的持久化方式
一般來說臂寝, 如果想達到足以媲美PostgreSQL的數據安全性,你應該同時使用兩種持久化功能摊灭。在這種情況下咆贬,當 Redis 重啟的時候會優(yōu)先載入AOF文件來恢復原始的數據,因為在通常情況下AOF文件保存的數據集要比RDB文件保存的數據集要完整帚呼。
如果你非常關心你的數據掏缎, 但仍然可以承受數分鐘以內的數據丟失,那么你可以只使用RDB持久化萝挤。
有很多用戶都只使用AOF持久化御毅,但并不推薦這種方式,因為定時生成RDB快照(snapshot)非常便于進行數據庫備份怜珍, 并且 RDB 恢復數據集的速度也要比AOF恢復的速度要快端蛆,除此之外,使用RDB還可以避免AOF程序的bug酥泛。
如果你只希望你的數據在服務器運行的時候存在今豆,你也可以不使用任何持久化方式嫌拣。
10、Redis持久化數據和緩存怎么做擴容呆躲?
如果Redis被當做緩存使用异逐,使用一致性哈希實現動態(tài)擴容縮容。
如果Redis被當做一個持久化存儲使用插掂,必須使用固定的keys-to-nodes映射關系灰瞻,節(jié)點的數量一旦確定不能變化。否則的話(即Redis節(jié)點需要動態(tài)變化的情況)辅甥,必須使用可以在運行時進行數據再平衡的一套系統(tǒng)酝润,而當前只有Redis集群可以做到這樣。
過期鍵的刪除策略
11璃弄、Redis的過期鍵的刪除策略
我們都知道要销,Redis是key-value數據庫,我們可以設置Redis中緩存的key的過期時間夏块。Redis的過期策略就是指當Redis中緩存的key過期了疏咐,Redis如何處理。
過期策略通常有以下三種:
定時過期:每個設置過期時間的key都需要創(chuàng)建一個定時器脐供,到過期時間就會立即清除浑塞。該策略可以立即清除過期的數據,對內存很友好政己;但是會占用大量的CPU資源去處理過期的數據缩举,從而影響緩存的響應時間和吞吐量。
惰性過期:只有當訪問一個key時匹颤,才會判斷該key是否已過期仅孩,過期則清除。該策略可以最大化地節(jié)省CPU資源印蓖,卻對內存非常不友好辽慕。極端情況可能出現大量的過期key沒有再次被訪問,從而不會被清除赦肃,占用大量內存溅蛉。
定期過期:每隔一定的時間,會掃描一定數量的數據庫的expires字典中一定數量的key他宛,并清除其中已過期的key船侧。該策略是前兩者的一個折中方案。通過調整定時掃描的時間間隔和每次掃描的限定耗時厅各,可以在不同情況下使得CPU和內存資源達到最優(yōu)的平衡效果镜撩。
(expires字典會保存所有設置了過期時間的key的過期時間數據,其中队塘,key是指向鍵空間中的某個鍵的指針袁梗,value是該鍵的毫秒精度的UNIX時間戳表示的過期時間宜鸯。鍵空間是指該Redis集群中保存的所有鍵。)
Redis中同時使用了惰性過期和定期過期兩種過期策略遮怜。
12淋袖、Redis key的過期時間和永久有效分別怎么設置?
EXPIRE和PERSIST命令锯梁。
13即碗、我們知道通過expire來設置key 的過期時間,那么對過期的數據怎么處理呢?
除了緩存服務器自帶的緩存失效策略之外(Redis默認的有6中策略可供選擇)陌凳,我們還可以根據具體的業(yè)務需求進行自定義的緩存淘汰拜姿,常見的策略有兩種:
定時去清理過期的緩存;
當有用戶請求過來時冯遂,再判斷這個請求所用到的緩存是否過期,過期的話就去底層系統(tǒng)得到新數據并更新緩存谒获。
兩者各有優(yōu)劣蛤肌,第一種的缺點是維護大量緩存的key是比較麻煩的,第二種的缺點就是每次用戶請求過來都要判斷緩存失效批狱,邏輯相對比較復雜裸准!具體用哪種方案,大家可以根據自己的應用場景來權衡赔硫。
內存相關
14炒俱、MySQL里有2000w數據,redis中只存20w的數據爪膊,如何保證redis中的數據都是熱點數據权悟?
redis內存數據集大小上升到一定大小的時候,就會施行數據淘汰策略推盛。
15峦阁、Redis的內存淘汰策略有哪些?
Redis的內存淘汰策略是指在Redis的用于緩存的內存不足時耘成,怎么處理需要新寫入且需要申請額外空間的數據榔昔。
全局的鍵空間選擇性移除
noeviction:當內存不足以容納新寫入數據時,新寫入操作會報錯瘪菌。
allkeys-lru:當內存不足以容納新寫入數據時撒会,在鍵空間中,移除最近最少使用的key师妙。(這個是最常用的)
allkeys-random:當內存不足以容納新寫入數據時诵肛,在鍵空間中,隨機移除某個key默穴。
設置過期時間的鍵空間選擇性移除
volatile-lru:當內存不足以容納新寫入數據時曾掂,在設置了過期時間的鍵空間中惫谤,移除最近最少使用的key。
volatile-random:當內存不足以容納新寫入數據時珠洗,在設置了過期時間的鍵空間中溜歪,隨機移除某個key。
volatile-ttl:當內存不足以容納新寫入數據時许蓖,在設置了過期時間的鍵空間中蝴猪,有更早過期時間的key優(yōu)先移除。
總結
Redis的內存淘汰策略的選取并不會影響過期的key的處理膊爪。內存淘汰策略用于處理內存不足時的需要申請額外空間的數據自阱;過期策略用于處理過期的緩存數據。
16米酬、Redis主要消耗什么物理資源沛豌?
內存。
17赃额、Redis的內存用完了會發(fā)生什么加派?
如果達到設置的上限,Redis的寫命令會返回錯誤信息(但是讀命令還可以正常返回跳芳。)或者你可以配置內存淘汰機制芍锦,當Redis達到內存上限時會沖刷掉舊的內容。
18飞盆、Redis如何做內存優(yōu)化娄琉?
可以好好利用Hash,list,sorted set,set等集合類型數據,因為通常情況下很多小的Key-Value可以用更緊湊的方式存放到一起吓歇。盡可能使用散列表(hashes)孽水,散列表(是說散列表里面存儲的數少)使用的內存非常小,所以你應該盡可能的將你的數據模型抽象到一個散列表里面城看。比如你的web系統(tǒng)中有一個用戶對象匈棘,不要為這個用戶的名稱,姓氏析命,郵箱主卫,密碼設置單獨的key,而是應該把這個用戶的所有信息存儲到一張散列表里面鹃愤。
線程模型
19簇搅、Redis線程模型
Redis基于Reactor模式開發(fā)了網絡事件處理器,這個處理器被稱為文件事件處理器(file event handler)软吐。它的組成結構為4部分:多個套接字瘩将、IO多路復用程序、文件事件分派器、事件處理器姿现。因為文件事件分派器隊列的消費是單線程的肠仪,所以Redis才叫單線程模型。
文件事件處理器使用 I/O 多路復用(multiplexing)程序來同時監(jiān)聽多個套接字备典, 并根據套接字目前執(zhí)行的任務來為套接字關聯不同的事件處理器异旧。
當被監(jiān)聽的套接字準備好執(zhí)行連接應答(accept)、讀忍嵊丁(read)吮蛹、寫入(write)、關閉(close)等操作時拌屏, 與操作相對應的文件事件就會產生潮针, 這時文件事件處理器就會調用套接字之前關聯好的事件處理器來處理這些事件。
雖然文件事件處理器以單線程方式運行倚喂, 但通過使用 I/O 多路復用程序來監(jiān)聽多個套接字每篷, 文件事件處理器既實現了高性能的網絡通信模型, 又可以很好地與 redis 服務器中其他同樣以單線程方式運行的模塊進行對接端圈, 這保持了 Redis 內部單線程設計的簡單性焦读。
事務
20、什么是事務枫笛?
事務是一個單獨的隔離操作:事務中的所有命令都會序列化、按順序地執(zhí)行刚照。事務在執(zhí)行的過程中刑巧,不會被其他客戶端發(fā)送來的命令請求所打斷。
事務是一個原子操作:事務中的命令要么全部被執(zhí)行无畔,要么全部都不執(zhí)行啊楚。
21、Redis事務的概念
Redis 事務的本質是通過MULTI浑彰、EXEC恭理、WATCH等一組命令的集合。事務支持一次執(zhí)行多個命令郭变,一個事務中所有命令都會被序列化颜价。在事務執(zhí)行過程,會按照順序串行化執(zhí)行隊列中的命令诉濒,其他客戶端提交的命令請求不會插入到事務執(zhí)行命令序列中周伦。
總結說:redis事務就是一次性、順序性未荒、排他性的執(zhí)行一個隊列中的一系列命令专挪。
22、Redis事務的三個階段
事務開始 MULTI
命令入隊
事務執(zhí)行 EXEC
事務執(zhí)行過程中,如果服務端收到有EXEC寨腔、DISCARD速侈、WATCH、MULTI之外的請求迫卢,將會把請求放入隊列中排隊倚搬。
23、Redis事務相關命令
Redis事務功能是通過MULTI靖避、EXEC潭枣、DISCARD和WATCH 四個原語實現的。
Redis會將一個事務中的所有命令序列化幻捏,然后按順序執(zhí)行盆犁。
1)redis 不支持回滾,“Redis 在事務失敗時不進行回滾篡九,而是繼續(xù)執(zhí)行余下的命令”谐岁, 所以 Redis 的內部可以保持簡單且快速。
2)如果在一個事務中的命令出現錯誤榛臼,那么所有的命令都不會執(zhí)行伊佃;
.3)如果在一個事務中出現運行錯誤,那么正確的命令會被執(zhí)行沛善。
WATCH 命令是一個樂觀鎖航揉,可以為 Redis 事務提供 check-and-set (CAS)行為〗鸬螅可以監(jiān)控一個或多個鍵帅涂,一旦其中有一個鍵被修改(或刪除),之后的事務就不會執(zhí)行尤蛮,監(jiān)控一直持續(xù)到EXEC命令媳友。
MULTI命令用于開啟一個事務,它總是返回OK产捞。MULTI執(zhí)行之后醇锚,客戶端可以繼續(xù)向服務器發(fā)送任意多條命令,這些命令不會立即被執(zhí)行坯临,而是被放到一個隊列中焊唬,當EXEC命令被調用時,所有隊列中的命令才會被執(zhí)行看靠。
EXEC:執(zhí)行所有事務塊內的命令求晶。返回事務塊內所有命令的返回值,按命令執(zhí)行的先后順序排列衷笋。當操作被打斷時芳杏,返回空值 nil 矩屁。
通過調用DISCARD,客戶端可以清空事務隊列爵赵,并放棄執(zhí)行事務吝秕, 并且客戶端會從事務狀態(tài)中退出。
UNWATCH命令可以取消watch對所有key的監(jiān)控空幻。
24烁峭、事務管理(ACID)概述
原子性(Atomicity):原子性是指事務是一個不可分割的工作單位,事務中的操作要么都發(fā)生秕铛,要么都不發(fā)生约郁。
一致性(Consistency):事務前后數據的完整性必須保持一致。
隔離性(Isolation):多個事務并發(fā)執(zhí)行時但两,一個事務的執(zhí)行不應影響其他事務的執(zhí)行鬓梅。
持久性(Durability):持久性是指一個事務一旦被提交,它對數據庫中數據的改變就是永久性的谨湘,接下來即使數據庫發(fā)生故障也不應該對其有任何影響
Redis的事務總是具有ACID中的一致性和隔離性绽快,其他特性是不支持的。當服務器運行在AOF持久化模式下紧阔,并且appendfsync選項的值為always時坊罢,事務也具有耐久性。
25擅耽、Redis事務支持隔離性嗎活孩?
Redis 是單進程程序,并且它保證在執(zhí)行事務時乖仇,不會對事務進行中斷憾儒,事務可以運行直到執(zhí)行完所有事務隊列中的命令為止。因此这敬,Redis 的事務是總是帶有隔離性的航夺。
26蕉朵、Redis事務保證原子性嗎崔涂,支持回滾嗎?
Redis中始衅,單條命令是原子性執(zhí)行的冷蚂,但事務不保證原子性,且沒有回滾汛闸。事務中任意命令執(zhí)行失敗蝙茶,其余的命令仍會被執(zhí)行。
27诸老、Redis事務其他實現
基于Lua腳本隆夯,Redis可以保證腳本內的命令一次性、按順序地執(zhí)行,其同時也不提供事務運行錯誤的回滾蹄衷,執(zhí)行過程中如果部分命令運行錯誤忧额,剩下的命令還是會繼續(xù)運行完
基于中間標記變量,通過另外的標記變量來標識事務是否執(zhí)行完成愧口,讀取數據時先讀取該標記變量判斷是否事務執(zhí)行完成睦番。但這樣會需要額外寫代碼實現,比較繁瑣耍属。
集群方案
28托嚣、哨兵模式
哨兵的介紹:
sentinel,中文名是哨兵厚骗。哨兵是 redis 集群機構中非常重要的一個組件娃承,主要有以下功能:
集群監(jiān)控:負責監(jiān)控 redis master 和 slave 進程是否正常工作。
消息通知:如果某個 redis 實例有故障蛾坯,那么哨兵負責發(fā)送消息作為報警通知給管理員括荡。
故障轉移:如果 master node 掛掉了,會自動轉移到 slave node 上提揍。
配置中心:如果故障轉移發(fā)生了啤月,通知 client 客戶端新的 master 地址。
哨兵用于實現 redis 集群的高可用劳跃,本身也是分布式的谎仲,作為一個哨兵集群去運行,互相協同工作刨仑。
故障轉移時郑诺,判斷一個 master node 是否宕機了,需要大部分的哨兵都同意才行杉武,涉及到了分布式選舉的問題辙诞。
即使部分哨兵節(jié)點掛掉了,哨兵集群還是能正常工作的轻抱,因為如果一個作為高可用機制重要組成部分的故障轉移系統(tǒng)本身是單點的飞涂,那就很坑爹了。
哨兵的核心知識
哨兵至少需要 3 個實例祈搜,來保證自己的健壯性较店。
哨兵 + redis 主從的部署架構,是不保證數據零丟失的容燕,只能保證 redis 集群的高可用性梁呈。
對于哨兵 + redis 主從這種復雜的部署架構,盡量在測試環(huán)境和生產環(huán)境蘸秘,都進行充足的測試和演練官卡。
29蝗茁、官方Redis Cluster 方案(服務端路由查詢)
redis 集群模式的工作原理能說一下么?在集群模式下寻咒,redis 的 key 是如何尋址的评甜?分布式尋址都有哪些算法?了解一致性 hash 算法嗎仔涩?
簡介
Redis Cluster是一種服務端Sharding技術忍坷,3.0版本開始正式提供。Redis Cluster并沒有使用一致性hash熔脂,而是采用slot(槽)的概念佩研,一共分成16384個槽。將請求發(fā)送到任意節(jié)點霞揉,接收到請求的節(jié)點會將查詢請求發(fā)送到正確的節(jié)點上執(zhí)行
方案說明
通過哈希的方式旬薯,將數據分片,每個節(jié)點均分存儲一定哈希槽(哈希值)區(qū)間的數據适秩,默認分配了16384 個槽位
每份數據分片會存儲在多個互為主從的多節(jié)點上
數據寫入先寫主節(jié)點绊序,再同步到從節(jié)點(支持配置為阻塞同步)
同一分片多個節(jié)點間的數據不保持一致性
讀取數據時,當客戶端操作的key沒有分配在該節(jié)點上時秽荞,redis會返回轉向指令骤公,指向正確的節(jié)點
擴容時時需要需要把舊節(jié)點的數據遷移一部分到新節(jié)點
在 redis cluster 架構下,每個 redis 要放開兩個端口號扬跋,比如一個是 6379阶捆,另外一個就是 加1w 的端口號,比如 16379钦听。
16379 端口號是用來進行節(jié)點間通信的洒试,也就是 cluster bus 的東西,cluster bus 的通信朴上,用來進行故障檢測垒棋、配置更新、故障轉移授權痪宰。cluster bus 用了另外一種二進制的協議叼架,gossip 協議,用于節(jié)點間進行高效的數據交換酵镜,占用更少的網絡帶寬和處理時間碉碉。
節(jié)點間的內部通信機制
(基本通信原理)集群元數據的維護有兩種方式:集中式柴钻、Gossip 協議淮韭。redis cluster 節(jié)點間采用 gossip 協議進行通信。
分布式尋址算法
hash 算法(大量緩存重建)
一致性 hash 算法(自動緩存遷移)+ 虛擬節(jié)點(自動負載均衡)
redis cluster 的 hash slot 算法
優(yōu)點
無中心架構贴届,支持動態(tài)擴容靠粪,對業(yè)務透明
具備Sentinel的監(jiān)控和自動Failover(故障轉移)能力
客戶端不需要連接集群所有節(jié)點蜡吧,連接集群中任何一個可用節(jié)點即可
高性能,客戶端直連redis服務占键,免去了proxy代理的損耗
缺點
運維也很復雜昔善,數據遷移需要人工干預
只能使用0號數據庫
不支持批量操作(pipeline管道操作)
分布式邏輯和存儲模塊耦合等
30、基于客戶端分配
簡介
Redis Sharding是Redis Cluster出來之前畔乙,業(yè)界普遍使用的多Redis實例集群方法君仆。其主要思想是采用哈希算法將Redis數據的key進行散列,通過hash函數牲距,特定的key會映射到特定的Redis節(jié)點上返咱。Java redis客戶端驅動jedis,支持Redis Sharding功能牍鞠,即ShardedJedis以及結合緩存池的ShardedJedisPool
優(yōu)點
優(yōu)勢在于非常簡單咖摹,服務端的Redis實例彼此獨立,相互無關聯难述,每個Redis實例像單服務器一樣運行萤晴,非常容易線性擴展,系統(tǒng)的靈活性很強
缺點
由于sharding處理放到客戶端胁后,規(guī)模進一步擴大時給運維帶來挑戰(zhàn)店读。
客戶端sharding不支持動態(tài)增刪節(jié)點。服務端Redis實例群拓撲結構有變化時攀芯,每個客戶端都需要更新調整两入。連接不能共享,當應用規(guī)模增大時敲才,資源浪費制約優(yōu)化
31裹纳、基于代理服務器分片
簡介
客戶端發(fā)送請求到一個代理組件,代理解析客戶端的數據紧武,并將請求轉發(fā)至正確的節(jié)點剃氧,最后將結果回復給客戶端
特征
透明接入,業(yè)務程序不用關心后端Redis實例阻星,切換成本低
Proxy 的邏輯和存儲的邏輯是隔離的
代理層多了一次轉發(fā)朋鞍,性能有所損耗
業(yè)界開源方案
Twtter開源的Twemproxy
豌豆莢開源的Codis
32、Redis 主從架構
單機的 redis妥箕,能夠承載的 QPS 大概就在上萬到幾萬不等滥酥。對于緩存來說,一般都是用來支撐讀高并發(fā)的畦幢。因此架構做成主從(master-slave)架構坎吻,一主多從,主負責寫宇葱,并且將數據復制到其它的 slave 節(jié)點瘦真,從節(jié)點負責讀刊头。所有的讀請求全部走從節(jié)點。這樣也可以很輕松實現水平擴容诸尽,支撐讀高并發(fā)原杂。
redis replication -> 主從架構 -> 讀寫分離 -> 水平擴容支撐讀高并發(fā)
redis replication 的核心機制
redis 采用異步方式復制數據到 slave 節(jié)點,不過 redis2.8 開始您机,slave node 會周期性地確認自己每次復制的數據量穿肄;
一個 master node 是可以配置多個 slave node 的;
slave node 也可以連接其他的 slave node际看;
slave node 做復制的時候被碗,不會 block master node 的正常工作;
slave node 在做復制的時候仿村,也不會 block 對自己的查詢操作锐朴,它會用舊的數據集來提供服務;但是復制完成的時候蔼囊,需要刪除舊數據集焚志,加載新數據集,這個時候就會暫停對外服務了畏鼓;
slave node 主要用來進行橫向擴容酱酬,做讀寫分離,擴容的 slave node 可以提高讀的吞吐量云矫。
注意膳沽,如果采用了主從架構,那么建議必須開啟 master node 的持久化让禀,不建議用 slave node 作為 master node 的數據熱備挑社,因為那樣的話,如果你關掉 master 的持久化巡揍,可能在 master 宕機重啟的時候數據是空的痛阻,然后可能一經過復制, slave node 的數據也丟了腮敌。
另外阱当,master 的各種備份方案,也需要做糜工。萬一本地的所有文件丟失了弊添,從備份中挑選一份 rdb 去恢復 master,這樣才能確保啟動的時候捌木,是有數據的油坝,即使采用了后續(xù)講解的高可用機制,slave node 可以自動接管 master node,但也可能 sentinel 還沒檢測到 master failure免钻,master node 就自動重啟了,還是可能導致上面所有的 slave node 數據被清空崔拥。
redis 主從復制的核心原理
當啟動一個 slave node 的時候极舔,它會發(fā)送一個 PSYNC 命令給 master node。
如果這是 slave node 初次連接到 master node链瓦,那么會觸發(fā)一次 full resynchronization 全量復制拆魏。此時 master 會啟動一個后臺線程,開始生成一份 RDB 快照文件慈俯。
同時還會將從客戶端 client 新收到的所有寫命令緩存在內存中渤刃。RDB 文件生成完畢后, master 會將這個 RDB 發(fā)送給 slave贴膘,slave 會先寫入本地磁盤卖子,然后再從本地磁盤加載到內存中。
接著 master 會將內存中緩存的寫命令發(fā)送到 slave刑峡,slave 也會同步這些數據洋闽。
slave node 如果跟 master node 有網絡故障,斷開了連接突梦,會自動重連诫舅,連接之后 master node 僅會復制給 slave 部分缺少的數據。
過程原理
當從庫和主庫建立MS關系后宫患,會向主數據庫發(fā)送SYNC命令
主庫接收到SYNC命令后會開始在后臺保存快照(RDB持久化過程)刊懈,并將期間接收到的寫命令緩存起來
當快照完成后,主Redis會將快照文件和所有緩存的寫命令發(fā)送給從Redis
從Redis接收到后娃闲,會載入快照文件并且執(zhí)行收到的緩存的命令
之后虚汛,主Redis每當接收到寫命令時就會將命令發(fā)送從Redis,從而保證數據的一致
缺點
所有的slave節(jié)點數據的復制和同步都由master節(jié)點來處理皇帮,會照成master節(jié)點壓力太大泽疆,使用主從從結構來解決
33、Redis集群的主從復制模型是怎樣的玲献?
為了使在部分節(jié)點失敗或者大部分節(jié)點無法通信的情況下集群仍然可用殉疼,所以集群使用了主從復制模型,每個節(jié)點都會有N-1個復制品
34捌年、生產環(huán)境中的 redis 是怎么部署的瓢娜?
redis cluster,10 臺機器礼预,5 臺機器部署了 redis 主實例眠砾,另外 5 臺機器部署了 redis 的從實例,每個主實例掛了一個從實例托酸,5 個節(jié)點對外提供讀寫服務褒颈,每個節(jié)點的讀寫高峰qps可能可以達到每秒 5 萬柒巫,5 臺機器最多是 25 萬讀寫請求/s。
機器是什么配置谷丸?32G 內存+ 8 核 CPU + 1T 磁盤堡掏,但是分配給 redis 進程的是10g內存,一般線上生產環(huán)境刨疼,redis 的內存盡量不要超過 10g泉唁,超過 10g 可能會有問題。
5 臺機器對外提供讀寫揩慕,一共有 50g 內存亭畜。
因為每個主實例都掛了一個從實例,所以是高可用的迎卤,任何一個主實例宕機拴鸵,都會自動故障遷移,redis 從實例會自動變成主實例繼續(xù)提供讀寫服務蜗搔。
你往內存里寫的是什么數據宝踪?每條數據的大小是多少?商品數據碍扔,每條數據是 10kb瘩燥。100 條數據是 1mb,10 萬條數據是 1g不同。常駐內存的是 200 萬條商品數據厉膀,占用內存是 20g,僅僅不到總內存的 50%二拐。目前高峰期每秒就是 3500 左右的請求量服鹅。
其實大型的公司,會有基礎架構的 team 負責緩存集群的運維百新。
35企软、說說Redis哈希槽的概念?
Redis集群沒有使用一致性hash,而是引入了哈希槽的概念饭望,Redis集群有16384個哈希槽仗哨,每個key通過CRC16校驗后對16384取模來決定放置哪個槽,集群的每個節(jié)點負責一部分hash槽铅辞。
36厌漂、Redis集群會有寫操作丟失嗎?為什么斟珊?
Redis并不能保證數據的強一致性苇倡,這意味這在實際中集群在特定的條件下可能會丟失寫操作。
37、Redis集群之間是如何復制的旨椒?
異步復制
38晓褪、Redis集群最大節(jié)點個數是多少?
16384個
39综慎、Redis集群如何選擇數據庫涣仿?
Redis集群目前無法做數據庫選擇,默認在0數據庫寥粹。
分區(qū)
40变过、Redis是單線程的埃元,如何提高多核CPU的利用率涝涤?
可以在同一個服務器部署多個Redis的實例,并把他們當作不同的服務器來使用岛杀,在某些時候阔拳,無論如何一個服務器是不夠的, 所以类嗤,如果你想使用多個CPU糊肠,你可以考慮一下分片(shard)。
41遗锣、為什么要做Redis分區(qū)货裹?
分區(qū)可以讓Redis管理更大的內存,Redis將可以使用所有機器的內存精偿。如果沒有分區(qū)弧圆,你最多只能使用一臺機器的內存。分區(qū)使Redis的計算能力通過簡單地增加計算機得到成倍提升笔咽,Redis的網絡帶寬也會隨著計算機和網卡的增加而成倍增長搔预。
42、你知道有哪些Redis分區(qū)實現方案叶组?
客戶端分區(qū)就是在客戶端就已經決定數據會被存儲到哪個redis節(jié)點或者從哪個redis節(jié)點讀取拯田。大多數客戶端已經實現了客戶端分區(qū)。
代理分區(qū) 意味著客戶端將請求發(fā)送給代理甩十,然后代理決定去哪個節(jié)點寫數據或者讀數據船庇。代理根據分區(qū)規(guī)則決定請求哪些Redis實例,然后根據Redis的響應結果返回給客戶端侣监。redis和memcached的一種代理實現就是Twemproxy
查詢路由(Query routing) 的意思是客戶端隨機地請求任意一個redis實例溢十,然后由Redis將請求轉發(fā)給正確的Redis節(jié)點。Redis Cluster實現了一種混合形式的查詢路由达吞,但并不是直接將請求從一個redis節(jié)點轉發(fā)到另一個redis節(jié)點张弛,而是在客戶端的幫助下直接redirected到正確的redis節(jié)點。
43、Redis分區(qū)有什么缺點吞鸭?
涉及多個key的操作通常不會被支持寺董。例如你不能對兩個集合求交集,因為他們可能被存儲到不同的Redis實例(實際上這種情況也有辦法刻剥,但是不能直接使用交集指令)遮咖。
同時操作多個key,則不能使用Redis事務.
分區(qū)使用的粒度是key,不能使用一個非常長的排序key存儲一個數據集(The partitioning granularity is the key, so it is not possible to shard a dataset with a single huge key like a very big sorted set)
當使用分區(qū)的時候造虏,數據處理會非常復雜御吞,例如為了備份你必須從不同的Redis實例和主機同時收集RDB / AOF文件。
分區(qū)時動態(tài)擴容或縮容可能非常復雜漓藕。Redis集群在運行時增加或者刪除Redis節(jié)點陶珠,能做到最大程度對用戶透明地數據再平衡,但其他一些客戶端分區(qū)或者代理分區(qū)方法則不支持這種特性享钞。然而揍诽,有一種預分片的技術也可以較好的解決這個問題。
分布式問題
44栗竖、Redis實現分布式鎖
Redis為單進程單線程模式暑脆,采用隊列模式將并發(fā)訪問變成串行訪問,且多客戶端對Redis的連接并不存在競爭關系Redis中可以使用SETNX命令實現分布式鎖狐肢。
當且僅當 key 不存在添吗,將 key 的值設為 value。若給定的 key 已經存在份名,則 SETNX 不做任何動作碟联。
SETNX 是『SET if Not eXists』(如果不存在,則 SET)的簡寫同窘。
返回值:設置成功玄帕,返回 1 。設置失敗想邦,返回 0 裤纹。
使用SETNX完成同步鎖的流程及事項如下:
使用SETNX命令獲取鎖,若返回0(key已存在丧没,鎖已存在)則獲取失敗鹰椒,反之獲取成功。
為了防止獲取鎖后程序出現異常呕童,導致其他線程/進程調用SETNX命令總是返回0而進入死鎖狀態(tài)漆际,需要為該key設置一個“合理”的過期時間。
釋放鎖夺饲,使用DEL命令將鎖數據刪除奸汇。
45施符、如何解決 Redis 的并發(fā)競爭 Key 問題
所謂 Redis 的并發(fā)競爭 Key 的問題也就是多個系統(tǒng)同時對一個 key 進行操作,但是最后執(zhí)行的順序和我們期望的順序不同擂找,這樣也就導致了結果的不同戳吝!
推薦一種方案:分布式鎖(zookeeper 和 redis 都可以實現分布式鎖)。(如果不存在 Redis 的并發(fā)競爭 Key 問題贯涎,不要使用分布式鎖听哭,這樣會影響性能)
基于zookeeper臨時有序節(jié)點可以實現的分布式鎖。大致思想為:每個客戶端對某個方法加鎖時塘雳,在zookeeper上的與該方法對應的指定節(jié)點的目錄下陆盘,生成一個唯一的瞬時有序節(jié)點。判斷是否獲取鎖的方式很簡單败明,只需要判斷有序節(jié)點中序號最小的一個隘马。當釋放鎖的時候,只需將這個瞬時節(jié)點刪除即可肩刃。同時祟霍,其可以避免服務宕機導致的鎖無法釋放杏头,而產生的死鎖問題盈包。完成業(yè)務流程后,刪除對應的子節(jié)點釋放鎖醇王。
在實踐中呢燥,當然是從以可靠性為主。所以首推Zookeeper寓娩。
參考:
http://www.reibang.com/p/8bddd381de06
46叛氨、分布式Redis是前期做還是后期規(guī)模上來了再做好?為什么棘伴?
既然Redis是如此的輕量(單實例只使用1M內存)寞埠,為防止以后的擴容,最好的辦法就是一開始就啟動較多實例焊夸。即便你只有一臺服務器仁连,你也可以一開始就讓Redis以分布式的方式運行,使用分區(qū)阱穗,在同一臺服務器上啟動多個實例饭冬。
一開始就多設置幾個Redis實例,例如32或者64個實例揪阶,對大多數用戶來說這操作起來可能比較麻煩昌抠,但是從長久來看做這點犧牲是值得的。
這樣的話鲁僚,當你的數據不斷增長炊苫,需要更多的Redis服務器時裁厅,你需要做的就是僅僅將Redis實例從一臺服務遷移到另外一臺服務器而已(而不用考慮重新分區(qū)的問題)。一旦你添加了另一臺服務器侨艾,你需要將你一半的Redis實例從第一臺機器遷移到第二臺機器姐直。
47、什么是 RedLock
Redis 官方站提出了一種權威的基于 Redis 實現分布式鎖的方式名叫 Redlock蒋畜,此種方式比原先的單節(jié)點的方法更安全声畏。它可以保證以下特性:
安全特性:互斥訪問,即永遠只有一個 client 能拿到鎖
避免死鎖:最終 client 都可能拿到鎖姻成,不會出現死鎖的情況插龄,即使原本鎖住某資源的 client crash 了或者出現了網絡分區(qū)
容錯性:只要大部分 Redis 節(jié)點存活就可以正常提供服務
緩存異常
48、緩存雪崩
緩存雪崩是指緩存同一時間大面積的失效科展,所以蓝厌,后面的請求都會落到數據庫上徽千,造成數據庫短時間內承受大量請求而崩掉。
解決方案:
緩存數據的過期時間設置隨機,防止同一時間大量數據過期現象發(fā)生驯杜。
一般并發(fā)量不是特別多的時候,使用最多的解決方案是加鎖排隊玩般。
給每一個緩存數據增加相應的緩存標記爆袍,記錄緩存的是否失效,如果緩存標記失效坞琴,則更新數據緩存哨查。
49、緩存穿透
緩存穿透是指緩存和數據庫中都沒有的數據剧辐,導致所有的請求都落到數據庫上寒亥,造成數據庫短時間內承受大量請求而崩掉。
解決方案:
接口層增加校驗荧关,如用戶鑒權校驗溉奕,id做基礎校驗,id<=0的直接攔截忍啤;
從緩存取不到的數據加勤,在數據庫中也沒有取到,這時也可以將key-value對寫為key-null檀轨,緩存有效時間可以設置短點胸竞,如30秒(設置太長會導致正常情況也沒法使用)。這樣可以防止攻擊用戶反復用同一個id暴力攻擊
采用布隆過濾器参萄,將所有可能存在的數據哈希到一個足夠大的 bitmap 中卫枝,一個一定不存在的數據會被這個 bitmap 攔截掉,從而避免了對底層存儲系統(tǒng)的查詢壓力
附加:
對于空間的利用到達了一種極致讹挎,那就是Bitmap和布隆過濾器(Bloom Filter)校赤。
Bitmap:典型的就是哈希表
缺點是吆玖,Bitmap對于每個元素只能記錄1bit信息,如果還想完成額外的功能马篮,恐怕只能靠犧牲更多的空間沾乘、時間來完成了。
布隆過濾器(推薦)
就是引入了k(k>1)k(k>1)個相互獨立的哈希函數浑测,保證在給定的空間翅阵、誤判率下,完成元素判重的過程迁央。
它的優(yōu)點是空間效率和查詢時間都遠遠超過一般的算法掷匠,缺點是有一定的誤識別率和刪除困難。
Bloom-Filter算法的核心思想就是利用多個不同的Hash函數來解決“沖突”岖圈。
Hash存在一個沖突(碰撞)的問題讹语,用同一個Hash得到的兩個URL的值有可能相同。為了減少沖突蜂科,我們可以多引入幾個Hash顽决,如果通過其中的一個Hash值我們得出某元素不在集合中,那么該元素肯定不在集合中导匣。只有在所有的Hash函數告訴我們該元素在集合中時才菠,才能確定該元素存在于集合中。這便是Bloom-Filter的基本思想逐抑。
Bloom-Filter一般用于在大數據量的集合中判定某元素是否存在鸠儿。
50屹蚊、緩存擊穿
緩存擊穿是指緩存中沒有但數據庫中有的數據(一般是緩存時間到期)厕氨,這時由于并發(fā)用戶特別多,同時讀緩存沒讀到數據汹粤,又同時去數據庫去取數據命斧,引起數據庫壓力瞬間增大,造成過大壓力嘱兼。和緩存雪崩不同的是国葬,緩存擊穿指并發(fā)查同一條數據,緩存雪崩是不同數據都過期了芹壕,很多數據都查不到從而查數據庫汇四。
解決方案
設置熱點數據永遠不過期。
加互斥鎖踢涌,互斥鎖
51通孽、緩存預熱
緩存預熱就是系統(tǒng)上線后,將相關的緩存數據直接加載到緩存系統(tǒng)睁壁。這樣就可以避免在用戶請求的時候背苦,先查詢數據庫互捌,然后再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據行剂!
解決方案:
直接寫個緩存刷新頁面秕噪,上線時手工操作一下;
數據量不大厚宰,可以在項目啟動的時候自動進行加載腌巾;
定時刷新緩存;
52铲觉、緩存降級
當訪問量劇增壤躲、服務出現問題(如響應時間慢或不響應)或非核心服務影響到核心流程的性能時,仍然需要保證服務還是可用的备燃,即使是有損服務碉克。系統(tǒng)可以根據一些關鍵數據進行自動降級,也可以配置開關實現人工降級并齐。漏麦、
緩存降級的最終目的是保證核心服務可用,即使是有損的况褪。而且有些服務是無法降級的(如加入購物車撕贞、結算)。
在進行降級之前要對系統(tǒng)進行梳理测垛,看看系統(tǒng)是不是可以丟卒保帥捏膨;從而梳理出哪些必須誓死保護,哪些可降級食侮;比如可以參考日志級別設置預案:
一般:比如有些服務偶爾因為網絡抖動或者服務正在上線而超時号涯,可以自動降級;
警告:有些服務在一段時間內成功率有波動(如在95~100%之間)锯七,可以自動降級或人工降級链快,并發(fā)送告警;
錯誤:比如可用率低于90%眉尸,或者數據庫連接池被打爆了域蜗,或者訪問量突然猛增到系統(tǒng)能承受的最大閥值,此時可以根據情況自動降級或者人工降級噪猾;
嚴重錯誤:比如因為特殊原因數據錯誤了霉祸,此時需要緊急人工降級。
服務降級的目的袱蜡,是為了防止Redis服務故障丝蹭,導致數據庫跟著一起發(fā)生雪崩問題。因此戒劫,對于不重要的緩存數據半夷,可以采取服務降級策略婆廊,例如一個比較常見的做法就是,Redis出現問題巫橄,不去數據庫查詢淘邻,而是直接返回默認值給用戶。
53湘换、熱點數據和冷數據
熱點數據宾舅,緩存才有價值。
對于冷數據而言彩倚,大部分數據可能還沒有再次訪問到就已經被擠出內存筹我,不僅占用內存,而且價值不大帆离。頻繁修改的數據蔬蕊,看情況考慮使用緩存
對于熱點數據,比如我們的某IM產品哥谷,生日祝福模塊岸夯,當天的壽星列表,緩存以后可能讀取數十萬次们妥。再舉個例子猜扮,某導航產品,我們將導航信息监婶,緩存以后可能讀取數百萬次旅赢。
數據更新前至少讀取兩次,緩存才有意義惑惶。這個是最基本的策略煮盼,如果緩存還沒有起作用就失效了,那就沒有太大價值了集惋。
那存不存在孕似,修改頻率很高,但是又不得不考慮緩存的場景呢刮刑?有!比如养渴,這個讀取接口對數據庫的壓力很大雷绢,但是又是熱點數據,這個時候就需要考慮通過緩存手段理卑,減少數據庫的壓力翘紊,比如我們的某助手產品的,點贊數藐唠,收藏數帆疟,分享數等是非常典型的熱點數據鹉究,但是又不斷變化,此時就需要將數據同步保存到Redis緩存踪宠,減少數據庫壓力自赔。
54、緩存熱點key
緩存中的一個Key(比如一個促銷商品)柳琢,在某個時間點過期的時候绍妨,恰好在這個時間點對這個Key有大量的并發(fā)請求過來,這些請求發(fā)現緩存過期一般都會從后端DB加載數據并回設到緩存柬脸,這個時候大并發(fā)的請求可能會瞬間把后端DB壓垮他去。
解決方案:
對緩存查詢加鎖,如果KEY不存在倒堕,就加鎖灾测,然后查DB入緩存,然后解鎖垦巴;其他進程如果發(fā)現有鎖就等待行施,然后等解鎖后返回數據或者進入DB查詢
常用工具
55、Redis支持的Java客戶端都有哪些魂那?官方推薦用哪個蛾号?
Redisson、Jedis涯雅、lettuce等等鲜结,官方推薦使用Redisson。
56活逆、Redis和Redisson有什么關系精刷?
Redisson是一個高級的分布式協調Redis客服端,能幫助用戶在分布式環(huán)境中輕松實現一些Java的對象 (Bloom filter, BitSet, Set, SetMultimap, ScoredSortedSet, SortedSet, Map, ConcurrentMap, List, ListMultimap, Queue, BlockingQueue, Deque, BlockingDeque, Semaphore, Lock, ReadWriteLock, AtomicLong, CountDownLatch, Publish / Subscribe, HyperLogLog)蔗候。
57怒允、Jedis與Redisson對比有什么優(yōu)缺點?
Jedis是Redis的Java實現的客戶端锈遥,其API提供了比較全面的Redis命令的支持纫事;Redisson實現了分布式和可擴展的Java數據結構,和Jedis相比所灸,功能較為簡單丽惶,不支持字符串操作,不支持排序爬立、事務钾唬、管道、分區(qū)等Redis特性。Redisson的宗旨是促進使用者對Redis的關注分離抡秆,從而讓使用者能夠將精力更集中地放在處理業(yè)務邏輯上奕巍。
其他問題
58、Redis與Memcached的區(qū)別
兩者都是非關系型內存鍵值數據庫儒士,現在公司一般都是用 Redis 來實現緩存的止,而且 Redis 自身也越來越強大了!Redis 與 Memcached 主要有以下不同:
(1) memcached所有的值均是簡單的字符串乍桂,redis作為其替代者冲杀,支持更為豐富的數據類型
(2) redis的速度比memcached快很多
(3) redis可以持久化其數據
59、如何保證緩存與數據庫雙寫時的數據一致性睹酌?
你只要用緩存权谁,就可能會涉及到緩存與數據庫雙存儲雙寫,你只要是雙寫憋沿,就一定會有數據一致性的問題旺芽,那么你如何解決一致性問題?
一般來說辐啄,就是如果你的系統(tǒng)不是嚴格要求緩存+數據庫必須一致性的話采章,緩存可以稍微的跟數據庫偶爾有不一致的情況,最好不要做這個方案壶辜,讀請求和寫請求串行化悯舟,串到一個內存隊列里去,這樣就可以保證一定不會出現不一致的情況
串行化之后砸民,就會導致系統(tǒng)的吞吐量會大幅度的降低抵怎,用比正常情況下多幾倍的機器去支撐線上的一個請求。
還有一種方式就是可能會暫時產生不一致的情況岭参,但是發(fā)生的幾率特別小反惕,就是先更新數據庫,然后再刪除緩存演侯。
60姿染、Redis常見性能問題和解決方案?
Master最好不要做任何持久化工作秒际,包括內存快照和AOF日志文件悬赏,特別是不要啟用內存快照做持久化。
如果數據比較關鍵程癌,某個Slave開啟AOF備份數據舷嗡,策略為每秒同步一次。
為了主從復制的速度和連接的穩(wěn)定性嵌莉,Slave和Master最好在同一個局域網內。
盡量避免在壓力較大的主庫上增加從庫
Master調用BGREWRITEAOF重寫AOF文件捻脖,AOF在重寫的時候會占大量的CPU和內存資源锐峭,導致服務load過高中鼠,出現短暫服務暫停現象沿癞。
為了Master的穩(wěn)定性援雇,主從復制不要用圖狀結構,用單向鏈表結構更穩(wěn)定椎扬,即主從關系為:Master<–Slave1<–Slave2<–Slave3…惫搏,這樣的結構也方便解決單點故障問題,實現Slave對Master的替換蚕涤,也即筐赔,如果Master掛了,可以立馬啟用Slave1做Master揖铜,其他不變茴丰。
61、Redis官方為什么不提供Windows版本天吓?
因為目前Linux版本已經相當穩(wěn)定贿肩,而且用戶量很大,無需開發(fā)windows版本龄寞,反而會帶來兼容性等問題汰规。
62、一個字符串類型的值能存儲最大容量是多少物邑?
512M
63溜哮、Redis如何做大量數據插入?
Redis2.6開始redis-cli支持一種新的被稱之為pipe mode的新模式用于執(zhí)行大量數據插入工作拂封。
64茬射、假如Redis里面有1億個key,其中有10w個key是以某個固定的已知的前綴開頭的冒签,如果將它們全部找出來在抛?
使用keys指令可以掃出指定模式的key列表。
對方接著追問:如果這個redis正在給線上的業(yè)務提供服務萧恕,那使用keys指令會有什么問題刚梭?
這個時候你要回答redis關鍵的一個特性:redis的單線程的。keys指令會導致線程阻塞一段時間票唆,線上服務會停頓朴读,直到指令執(zhí)行完畢,服務才能恢復走趋。這個時候可以使用scan指令衅金,scan指令可以無阻塞的提取出指定模式的key列表,但是會有一定的重復概率,在客戶端做一次去重就可以了氮唯,但是整體所花費的時間會比直接用keys指令長鉴吹。
65、使用Redis做過異步隊列嗎惩琉,是如何實現的豆励?
使用list類型保存數據信息,rpush生產消息瞒渠,lpop消費消息良蒸,當lpop沒有消息時,可以sleep一段時間伍玖,然后再檢查有沒有信息嫩痰,如果不想sleep的話,可以使用blpop, 在沒有信息的時候私沮,會一直阻塞始赎,直到信息的到來。redis可以通過pub/sub主題訂閱模式實現一個生產者仔燕,多個消費者造垛,當然也存在一定的缺點,當消費者下線時晰搀,生產的消息會丟失五辽。
66、Redis如何實現延時隊列外恕?
使用sortedset杆逗,使用時間戳做score, 消息內容作為key,調用zadd來生產消息,消費者使用zrangbyscore獲取n秒之前的數據做輪詢處理鳞疲。
67罪郊、Redis回收進程如何工作的?
一個客戶端運行了新的命令尚洽,添加了新的數據悔橄。
Redis檢查內存使用情況,如果大于maxmemory的限制腺毫, 則根據設定好的策略進行回收癣疟。
一個新的命令被執(zhí)行,等等潮酒。
所以我們不斷地穿越內存限制的邊界睛挚,通過不斷達到邊界然后不斷地回收回到邊界以下。
如果一個命令的結果導致大量內存被使用(例如很大的集合的交集保存到一個新的鍵)急黎,不用多久內存限制就會被這個內存使用量超越扎狱。
68侧到、Redis回收使用的是什么算法?
LRU算法委乌。
需要更多面試資料的小伙伴可以私信【面試】即可獲取