文章原創於公眾號:程式猿周先森。本平臺不定時更新,喜歡我的文章,歡迎關注我的微信公眾號。
前面幾篇已經對Redis中幾個關鍵知識點做了介紹,本篇主要對Redis系列做一下總結以及對Redis中常見面試題簡單進行介紹一下。首先我們對前面幾篇談到的Redis知識點進行總結。
第1篇:Redis系列開篇文章可以一文了解Redis。
- http://mp.weixin.qq.com/s?__biz=MzU5MTc1ODA0OQ==&mid=2247484785&idx=1&sn=cd13725437d7f790e749e0c7f1f22f0b&chksm=fe2b52ffc95cdbe96be69bc213e1aaebbed2f767e212d6b0613d9eebe2738efa02de6c6dd7ef&scene=21#wechat_redirect
第2篇:通過對比Redis和Memcached的區別來解釋Redis為什麼高效能。
- http://mp.weixin.qq.com/s?__biz=MzU5MTc1ODA0OQ==&mid=2247484894&idx=1&sn=b00d737d99a5aeb38546d7c145672597&chksm=fe2b5250c95cdb46768f20fec9b1857b2c7b41170e725c611da05d09160e27a4c2b716d0f33c&scene=21#wechat_redirect
第3篇:Redis中使用最頻繁的有5種資料型別:String、List、Hash、Set、SortSet。本篇對Redis中常用的5種資料型別進行了細微的講解以及常用場景進行介紹。
- http://mp.weixin.qq.com/s?__biz=MzU5MTc1ODA0OQ==&mid=2247484900&idx=1&sn=95fa2d350a75497f460d80b5977acef8&chksm=fe2b526ac95cdb7c24de3ef3c99e7ee4bb98c1fdeab20f054a6f1ebc62c985716ad677b448c1&scene=21#wechat_redirect
第4篇:如果同一臺機器有多個執行緒搶奪同一個共享資源,同一個執行緒多次執行會出現異常,這種情況下就會出現非執行緒安全。我們解決方法通常使用鎖來解決。但是如果有多臺機器呢?這時候我們通常使用分散式鎖來解決分散式環境下共享資源的同步問題。本篇對於單機部署分散式鎖幾種常規方案進行分別的說明。
- http://mp.weixin.qq.com/s?__biz=MzU5MTc1ODA0OQ==&mid=2247484906&idx=1&sn=a9354f62a8ca4280773050ef1fd23266&chksm=fe2b5264c95cdb7230c6d431a59be401fa993edefb5eb7cc378148fb6e3a7f4c0d48489cf1ac&scene=21#wechat_redirect
第5篇:對保持雙庫資料一致性方案進行了分析以及分析通用的保持資料一致性的方案。
- http://mp.weixin.qq.com/s?__biz=MzU5MTc1ODA0OQ==&mid=2247484915&idx=1&sn=dc77d258970cc1734863bcca844d5fd8&chksm=fe2b527dc95cdb6bc432695ae43385e20a7ec0213e88dcaf48ff0c1f1953c71c03ff24e57132&scene=21#wechat_redirect
第6篇:主要針對Redis的記憶體淘汰機制以及Redis容易引發的三大問題:快取擊穿、快取穿透以及快取雪崩進行了詳細的講解以及提供了業界常用的解決方案。因為涉及到快取淘汰機制,所以內容包含快取淘汰機制的知識點。
- http://mp.weixin.qq.com/s?biz=MzU5MTc1ODA0OQ==&mid=2247484921&idx=1&sn=456f63d1febeeafc9cdd6fd5fd147433&chksm=fe2b5277c95cdb6111052b1c13017619a1c317c12a04f5971efba13d26b7fbd8e54476d7d56d&scene=21#wechat_redirect
第7篇:Redis受開發者歡迎的一大原因就是因為可持久化的特性。我們如何保證Redis當機之後重啟可以將資料進行恢復?所以一般情況下我們需要定時進行持久化將記憶體中的資料寫入到硬碟中。而Redis中支援兩種不同的持久化機制:RDB持久化以及AOF持久化。
- http://mp.weixin.qq.com/s?biz=MzU5MTc1ODA0OQ==&mid=2247484927&idx=1&sn=5833dcf099be8dcbdc6e26be26f003d1&chksm=fe2b5271c95cdb67c4a815f5afb49bfee577deda9377852831e5bcac641ea4238b0106595828&scene=21#wechat_redirect
第8篇:在80%左右企業使用的都是Redis單機服務,在生產環境下使用單機環境的Redis容易面臨風險,如果Redis持久化的硬碟出現故障,則有可能導致持久化的備份資料出現丟失,所以我們需要一個方案解決這個問題,所以我們需要將原來集中式的資料庫中的資料分別複製到不同Redis節點上進行儲存,這也就是Redis中的主從複製。
- http://mp.weixin.qq.com/s?__biz=MzU5MTc1ODA0OQ==&mid=2247484934&idx=1&sn=355f1323069e9a77453e6e063c856975&chksm=fe2b5188c95cd89e019d0cb6dac7ffd6dc1f6dfb5a46abc4d4c0a6ac6312b625250c727cc83d&scene=21#wechat_redirect
第9篇:Redis主從複製實際上就是將主Redis節點的資料,複製到其他從Redis節點去進行儲存,當主節點因為出現異常當機後,如何將從節點切換成主節點繼續提供服務呢?Redis主從切換主要分為以下兩種方式:手動切換以及哨兵模式。
- http://mp.weixin.qq.com/s?__biz=MzU5MTc1ODA0OQ==&mid=2247484940&idx=1&sn=7ce281c16661a576153090fa315403e6&chksm=fe2b5182c95cd894ddeb0bd7cf921571c901008373c8621cfc7b047e12e5463fd471a7eaeed2&scene=21#wechat_redirect
第10篇:如果沒有分片機制,Redis就被侷限於單機所支援的記憶體容量。Redis的分片機制允許資料拆分存放在不同的Redis例項上,每個Redis例項只包含所有鍵的子集。可以減輕單臺Redis的壓力,提升Redis擴充套件能力和計算能力。
- http://mp.weixin.qq.com/s?__biz=MzU5MTc1ODA0OQ==&mid=2247484945&idx=1&sn=84fb3787086b15325cf8f27acd1d8f59&chksm=fe2b519fc95cd889d0b8a7c18c6a34b500246177f93dd4964aef771ba9790bff340c5caf0c62&scene=21#wechat_redirect
對前面Reids系列文章簡單做了總結,接下來我們一起看看Reids幾道比較常見的面試題吧。
簡單介紹一下Redis
redis是一個key-value儲存系統。它支援儲存的value型別相對更多,包括string(字串)、list(連結串列)、set(集合)、zset(sorted set)和hash(雜湊型別)。這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,redis支援各種不同方式的排序。為了保證效率,資料都是快取在記憶體中。區別的是redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案,並且在此基礎上實現了主從同步。簡單來說 Redis 就是一個資料庫,不過與傳統資料庫不同的是 Redis 的資料是存在記憶體中的,所以存寫速度非常快,因此 Redis 被廣泛應用於快取方向。Redis 也經常用來做分散式鎖。Redis 提供了多種資料型別來支援不同的業務場景。除此之外,Redis 支援事務 、持久化、LUA 指令碼、LRU 驅動事件、多種叢集方案。
Redis與Memcached的區別
- Redis支援常見資料型別:Redis 不僅僅支援簡單的 key/value 型別的資料,同時還提供string(字串)、list(連結串列)、set(集合)、zset(有序集合)和hash(雜湊型別)等資料結構的儲存。而Memcache 只支援簡單的資料型別 String。
- Redis 支援資料的持久化,可以將記憶體中的資料保持在磁碟中,重啟的時候可以再次載入進行使用,而 Memecache 把資料全部存在記憶體之中。
- 叢集模式:Memcached 沒有原生的叢集模式,需要依靠客戶端來實現往叢集中分片寫入資料;但是 Redis 目前是原生支援 Cluster 模式的。
- Memcached 是多執行緒,非阻塞 IO 複用的網路模型;Redis 使用單執行緒的多路 IO 複用模型。
Redis常用五大資料型別Redis支援儲存的value型別相對更多,包括string、list、set、sorted set和hash。這些資料型別都支援push/pop、add/remove及取交集並集和差集及更豐富的操作,而且這些操作都是原子性的。在此基礎上,Redis支援各種不同方式的排序。為了保證效率,資料都是快取在記憶體中。對於這五種資料型別的具體分析可以看:細談Redis五大資料型別。
Redis的快取淘汰策略
Redis可以對儲存在快取中的資料設定過期時間。作為一個快取資料庫,這是非常實用的功能。之前寫過一篇前後端互動的文章講過,Token 或者一些登入資訊,尤其是簡訊驗證碼都是有時間限制的,按照傳統的資料庫處理方式,一般都是自己判斷過期,這樣無疑會嚴重影響專案效能。而有一個好的方案其實就是將這些驗證資訊存入Redis設定過期時間,如果設定了存活時間30分鐘,那麼半小時之後這些資料就會從Redis中進行刪除。那說到刪除,Redis是如果做到對這些資料進行刪除的呢:
- 定期刪除:Redis 預設是每隔 100ms 就隨機抽取一些設定了過期時間的 Key,檢查其是否過期,如果過期就刪除。為什麼是隨機抽取而不是檢查所有key?因為你如果設定的key成千上萬,每100毫秒都將所有存在的key檢查一遍,會給CPU帶來比較大的壓力。
- 惰性刪除 :定期刪除可能會導致很多過期 Key 到了時間並沒有被刪除掉。使用者在獲取key的時候,redis會檢查一下,這個key如果設定過期時間那麼是否過期了,如果過期就刪除這個key。
但是隻是使用定期刪除 + 惰性刪除的刪除機制還是存在一個致命問題:如果定期刪除漏掉了很多過期 Key,而且使用者長時間也沒有使用到這些過期key,就會導致這些過期key堆積在記憶體裡,導致Redis記憶體塊被消耗殆盡。所以有了Redis記憶體淘汰機制的誕生。
Redis 提供 6 種資料淘汰策略:
- volatile-lru:從已設定過期時間的資料集中挑選最近最少使用的資料淘汰。
- volatile-ttl:從已設定過期時間的資料集中挑選將要過期的資料淘汰。
- volatile-random:從已設定過期時間的資料集中任意選擇資料淘汰。
- allkeys-lru:當記憶體不足以容納新寫入資料時移除最近最少使用的key。
- allkeys-random:從資料集中任意選擇資料淘汰。
- no-enviction:當記憶體不足以容納新寫入資料時,新寫入操作會報錯。
Redis為何在記憶體中存放資料?Redis為了保證效率,資料都是快取在記憶體中。Redis會週期性的把更新的資料寫入磁碟或者把修改操作寫入追加的記錄檔案。簡單來說 Redis 就是一個資料庫,不過與傳統資料庫不同的是 Redis 的資料是存在記憶體中的,所以存寫速度非常快,因此 Redis 被廣泛應用於快取方向。Redis 也經常用來做分散式鎖。
Redis中雜湊槽的概念Redis沒有使用一致性雜湊這個概念,而是引入了雜湊槽。在Redis叢集中共有16384個雜湊槽,然後每個key通過雜湊函式crc16()將key名轉化成一個長整型數字再對16384取餘,最終決定這個key儲存的雜湊槽。而每個Redis例項負責維護一部分雜湊槽,所有例項共同維護所有的雜湊槽。使用雜湊槽最顯而易見的特點就是Redis例項的增加或者移除很方便,而不需要暫停所有Redis例項服務。
Redis分割槽方案資料分片方式一般有三種:客戶端分片、代理分片和伺服器分片。具體可以檢視文章:http://mp.weixin.qq.com/s?__biz=MzU5MTc1ODA0OQ==&mid=2247484945&idx=1&sn=84fb3787086b15325cf8f27acd1d8f59&chksm=fe2b519fc95cd889d0b8a7c18c6a34b500246177f93dd4964aef771ba9790bff340c5caf0c62&scene=21#wechat_redirect
客戶端分片
定義:客戶端自己計算key需要對映到哪一個Redis例項。
優點:客戶端分片最明顯的好處在於降低了叢集的複雜度,而伺服器之間沒有任何關聯性,資料分片由客戶端來負責實現。
缺點:客戶端實現分片則客戶端需要知道當前叢集下不同Redis例項的資訊,當新增Redis例項時需要支援動態分片,多數Redis需要重啟才能實現該功能。
代理分片
定義:客戶端將請求傳送到代理,代理通過計算得到需要對映的叢集例項資訊,然後將客戶端的請求轉發到對應的叢集例項上,然後返回響應給客戶端。
優點:降低了客戶端的複雜度,客戶端不用關心後端Redis例項的狀態資訊。
缺點:多了一箇中間分發環節,所以對效能有些取的損失。
伺服器分片
定義:客戶端可以和叢集中任意Redis例項通訊,當客戶端訪問某個例項時,伺服器進行計算key應該對映到哪個具體的Redis例項中儲存,如果對映的例項不是當前例項,則該例項主動引導客戶端去對應例項對key進行操作。這其實是一個重定向的過程。這個過程不是從當前Redis例項轉發到對應的Redis例項,而是客戶端收到伺服器通知具體對映的Redis例項重定向到對映的例項中。當前還不能完全適用於生產環境。
優點:支援高可用,任意例項都有主從,主掛了從會自動接管。
缺點:需要客戶端語言實現伺服器叢集協議,但是目前大多數語言都有其客戶端實現版本。
Redis的持久化機制
Redis持久化支援兩種不同的持久化操作。 RDB持久化是一次全量備份,備份的是記憶體資料的二進位制序列化格式。而AOF持久化是增量備份,記錄的是記憶體資料修改的指令記錄文字。所以AOF持久化生成的日誌會隨著執行時間變長而變得越來越臃腫,每次重啟Redis都需要載入AOF日誌進行指令重放,所以需要定期重寫AOF日誌進行瘦身操作。對於Redis的兩種持久化機制的選擇,主要還是得針對特定的系統討論,看是可以犧牲一定的效能使用AOF持久化換取快取一致性,還是在增刪操作頻繁時關閉備份,等到Redis空閒手動save做RDB持久化備份。所以其實最佳方案應該是採用混合持久化方案,開啟混合持久化後,AOF重寫日誌時會將RDB持久化的內容寫到AOF檔案開頭,於是在Redis重啟時,可以先載入RDB的內容,再對增量的AOF日誌進行重放,提升Redis重啟的效率。
Redis如何使用分散式鎖?
當某個機器佔有鎖並在Redis中設定key時,將value設定為隨機數,在請求處理完畢需要釋放鎖之前加上一步操作:判斷key的value值是否等於之前設定的隨機數,如果是代表這個鎖佔有者還是自己,就可以執行釋放鎖操作,否則代表鎖已經被別人佔有,不能執行釋放鎖操作。由於查詢和釋放鎖的操作非原子性的,所以就需要使用另一種方式:引入Jedis,使用Lua指令碼將查詢鎖和釋放鎖的兩部分邏輯寫成指令碼,於是Redis執行Lua指令碼時,其他機器的所有命令都必須等到Lua指令碼執行結束才能執行,所以不可能存在查詢鎖結束還未釋放就被其他機器佔領的情況。
如何使用Redis叢集?
使用主從複製將主節點的資料同步到從節點去儲存,然後使用哨兵模式實現叢集的高可用,在主節點當機則會從從節點中選擇一個進行主從切換成主節點繼續處理請求。然後當Redis記憶體不足時,使用分片機制對Redis進行分片儲存,可以減輕單臺Redis的壓力,提升Redis擴充套件能力和計算能力。
快取雪崩、快取擊穿、快取穿透的區別
- 快取擊穿:高併發的情況下,某個熱門key突然過期,導致大量請求在Redis未找到快取資料,進而全部去訪問DB請求資料,引起DB壓力瞬間增大。這就是快取擊穿。
- 快取穿透:快取穿透是指查詢快取和DB中都不存在的資料。比如通過id查詢商品資訊,id一般大於0,攻擊者會故意傳id為-1去查詢,由於快取是不命中則從DB中獲取資料,這將會導致每次快取都不命中資料導致每個請求都訪問DB,造成快取穿透。
- 快取雪崩:快取中如果大量快取在一段時間內集中過期了,這時候會發生大量的快取擊穿現象,所有的請求都落在了DB上,由於查詢資料量巨大,引起DB壓力過大甚至導致DB當機。這就叫做快取雪崩。
歡迎關注公眾號:程式猿周先森。
本文由部落格一文多發平臺 OpenWrite 釋出!