redis常見的一些問題

1.Redis支持的數據類型?
2.什么是Redis持久化?Redis有哪幾種持久化方式?優缺點是什么?
3.Redis 有哪些架構模式?講講各自的特點
4.使用過Redis分布式鎖么,它是怎么實現的?
5.使用過Redis做異步隊列么,你是怎么用的?有什么缺點?
6.什么是緩存穿透?如何避免?什么是緩存雪崩?何如避免?
7.為什么Redis 單線程卻能支撐高并發?
8.說說Redis的內存淘汰策略
9.Redis的并發競爭問題如何解決?

1.Redis支持的數據類型?

Redis支持五種數據類型:string(字符串),hash(哈希),list(列表),set(集合)及zset(sorted set:有序集合)。

2.什么是Redis持久化?Redis有哪幾種持久化方式?優缺點是什么?

由于Redis的數據都存放在內存中,如果沒有配置持久化,redis重啟后數據就全丟失了,于是需要開啟redis的持久化功能,將數據保存到磁盤上,當redis重啟后,可以從磁盤中恢復數據。
Redis提供兩種持久化方式,RDB和AOF,AOF可以完整記錄整個數據庫,RDB只是數據庫某一時刻的快照
1.RDB
配置方式 ** # save 60 1000 **
(bgsave命令執行過程中,只有fork子進程時會阻塞服務器;而對于save命令,整個過程都會阻塞服務器;因此save已基本被廢棄,線上環境要杜絕save的使用 )
RDB是一個緊湊壓縮的二進制文件 ,表示在n秒內,如果redis發生了M次的修改,則redis的數據會被存儲到內存中。不難看出這是一個周期性的持久化
缺點:
(1).因為是周期性的,那么當系統一旦在定時持久化之前出現宕機現象,此前沒有來得及寫入磁盤的數據都將丟失。
優點:
(1)對 redis 對外提供的讀寫服務,影響非常小,可以讓 redis 保持高性能,
(2) 相對于 AOF 持久化機制來說,直接基于 RDB 數據文件來重啟和恢復 redis 進程,更加快速。
2.AOF
配置 方式:
appendfsync always #每次有數據修改發生時都會寫入AOF文件。
appendfsync everysec #每秒鐘同步一次,該策略為AOF的缺省策略。
appendfsync no #從不同步。高效但是數據不會被持久化。

以日志的形式記錄服務器所處理的每一個寫、刪除操作,查詢操作不會記錄,以文本的方式記錄,可以打開文件看到詳細的操作記錄。 在恢復數據時,可以直接讀取該文件進行數據恢復
Redis中提供了3中同步策略,即每秒同步、每修改同步和不同步。事實上,每秒同步也是異步完成的,其效率也是非常高的,所差的是一旦系統出現宕機現象,那么這一秒鐘之內修改的數據將會丟失。而每修改同步,我們可以將其視為同步持久化,即每次發生的數據變化都會被立即記錄到磁盤中。可以預見,這種方式在效率上是最低的。
缺點:
(1)由于AOF一般每秒都在存儲,可能對于相同數量的數據集而言,AOF文件通常要大于RDB文件。RDB 在恢復大數據集時的速度比 AOF 的恢復速度要快
優點:
(1)保存的數據額更加完整,能夠更好的通過文件完成數據的重建
AOF更加傾向于數據的完整性,而RDB系統的性能會比AOF好一點
3.混合持久化 Redis4.0
配置方式 # aof-use-rdb-preamble yes
如果開啟了混合持久化,AOF在重寫時,不再是單純將內存數據轉換為RESP命令寫入AOF文件,而是將重寫這一刻之前的內存做RDB快照處理,并且將RDB快照內容和增量的AOF修改內存數據的命令存在一起,都寫入新的AOF文件,新的文件一開始不叫appendonly.aof,等到重寫完新的AOF文件才會進行改名,原子的覆蓋原有的AOF文件,完成新舊兩個AOF文件的替換。于是在 Redis 重啟的時候,可以先加載 RDB 的內容,然后再重放增量 AOF 日志就可以完全替代之前的AOF 全量文件重放,因此重啟效率大幅得到提升。

3.Redis 有哪些架構模式?講講各自的特點

Redis主要有四種架構模式,單機模式,主從模式,哨兵模式,集群模式。每種模式都有其特定的特點和適用場景。以下是詳細的介紹:
單機模式(Standalone)
Redis作為一個獨立的服務運行在單個服務器上,所有讀寫操作都在同一個Redis實例中進行。
優點:部署簡單,啟動方便,沒有網絡延遲,適合快速開發和測試。同時,在單機模式下,Redis能提供毫秒級別的訪問速度,非常適合小規模的緩存、會話存儲等場景。
缺點:沒有高可用性,存在單點故障的風險。一旦服務器出現故障,服務將不可用。此外,單機模式還受限于單機的存儲和處理能力,無法擴展到更大規模。
主從模式(Master-Slave Replication)
有一個主節點(Master)負責處理寫操作,一個或多個從節點(Slave)復制主節點的數據,只負責讀操作。
優點:實現了讀寫分離,可以提高讀操作的性能。同時,通過從節點提供數據副本(備份),提高了數據的可用性。這種架構為高并發讀取提供了更好的支持,同時通過冗余數據的方式增強了可用性。
缺點:主節點仍然是單點故障源,如果主節點出現故障,整個系統將失去寫入能力,雖然從節點可以提供只讀服務,但故障轉移需要手動進行,這會影響系統的可用性和穩定性。
哨兵模式(Sentinel Mode)
哨兵模式是在主從模式的基礎上增加了哨兵(Sentinel)進程,用于監控Redis主從節點的狀態,并在主節點故障時自動進行故障轉移。
優點:提供了自動故障轉移功能,當主節點出現故障時,哨兵會自動選擇一個從節點提升為主節點,并通知其他從節點重新同步數據,從而保證了系統的持續可用性。同時,哨兵還可以監控多個Redis節點的健康狀態,及時發現并處理故障。
缺點:配置相對復雜,需要設置哨兵節點的數量、監控的主從節點信息、故障轉移的策略等。此外,在故障轉移過程中可能會有短暫的服務中斷和數據不一致的風險。
集群模式(Cluster Mode)
Redis集群模式是一種分布式部署方式,數據被分割成多個片段(slots),分布在不同的節點上。每個節點既可以是主節點也可以是從節點,節點之間相互協調,共同提供服務。
優點:實現了真正的分布式存儲,提高了存儲容量和處理能力。同時,集群模式還支持自動進行故障轉移和動態擴容,進一步提高了系統的可用性和穩定性。此外,集群模式還支持跨節點的數據訪問和負載均衡,提高了系統的性能和可擴展性。
缺點:配置和運維相對復雜,需要設置節點的數量、分片規則、故障轉移策略等。同時,集群模式不支持跨節點的事務和某些復雜操作,這可能會限制一些應用場景的使用。
綜上所述,Redis的四種架構模式各有優缺點和適用場景。在選擇合適的架構模式時,需要根據具體的業務需求、數據規模、可用性要求和運維能力來決定。

5.使用過Redis做異步隊列么,你是怎么用的?有什么缺點?

Redis是一個高性能的鍵值存儲數據庫,支持多種數據類型,如字符串、列表、集合、哈希表和有序集合等。利用其List數據類型、Pub/Sub功能或Sorted Set數據類型,我們可以很方便地實現異步隊列。
在實際應用中,通常會將需要異步處理的任務(如發送郵件、短信通知、數據同步等)放入Redis隊列中,然后由后臺的消費者進程從隊列中取出任務并執行。Redis異步隊列的優點在于其高性能和靈活性,能夠很好地滿足大多數異步任務處理的需求。

然而,Redis做異步隊列也存在一些缺點,具體如下:
寫入和讀取性能瓶頸:由于Redis隊列存儲在內存中,如果消息積壓過多,應用程序的性能可能會急劇下降。當生產者向隊列中寫入大量消息時,可能會因為內存限制而導致寫入速度變慢;同樣,當消費者從隊列中讀取大量消息時,也可能會因為處理不過來而導致讀取速度變慢。
缺乏ack保證:Redis的消息隊列不是專業的消息隊列,它沒有ack(acknowledgement,確認字符)保證機制。這意味著消費者在處理完消息后,如果因為某種原因(如程序崩潰、網絡問題等)沒有向隊列發送確認消息,那么這條消息可能會被其他消費者重復處理,或者丟失(如果隊列采用了某種形式的自動刪除機制)。
高可用性問題:Redis隊列只能在單個實例上實現最高可用性。如果Redis服務器發生故障,消息隊列中的數據將會丟失,應用程序將處于不可控狀態。雖然可以通過主從復制、哨兵(Sentinel)和集群(Cluster)等機制來提高Redis的高可用性,但這些機制并不能完全解決消息丟失的問題。
缺乏安全措施:Redis隊列缺乏完整的安全功能,如訪問控制、數據加密和審計日志等。如果應用程序數據具有較高的敏感性,Redis隊列可能不適合作為常規消息隊列的安全性方案。
因此,在使用Redis做異步隊列時,需要充分評估應用程序的可伸縮性和可靠性要求,以及消息的敏感性和安全性需求。如果Redis無法滿足這些要求,可能需要考慮使用其他更專業、更可靠的消息隊列系統

6.什么是緩存穿透?如何避免?什么是緩存雪崩?何如避免?

緩存穿透

緩存穿透是指查詢一個緩存和數據庫中都不存在的數據,導致每次查詢都直接打到數據庫,給數據庫帶來壓力。

為了避免緩存穿透,可以采取以下幾種方法
布隆過濾器:布隆過濾器是一種空間效率很高的概率型數據結構,用于判斷一個元素是否在一個集合中。它允許存在一定的誤判率,但不會漏判。在數據放入緩存之前,先使用布隆過濾器進行判斷,如果該數據不存在于布隆過濾器中,則直接返回,不進行數據庫查詢。布隆過濾器可以顯著減少緩存穿透攻擊。
緩存空值或默認值:當數據庫查詢結果為空時,也將這個空結果(或默認值)緩存起來,并設置一個較短的過期時間。這樣,當再次查詢這個不存在的數據時,可以直接從緩存中返回空結果,而不會再次查詢數據庫。但這種方法需要合理設置過期時間,避免緩存中長時間存儲大量無用的空值或默認值。
使用更復雜的key:對于某些場景,可以通過改變查詢的key來避免緩存穿透。比如,對用戶的查詢加上用戶ID作為前綴,或者對查詢的參數進行加密、哈希等處理,確保每個查詢的key都是唯一的,從而避免惡意構造不存在的key進行攻擊。
限制訪問頻率:通過IP地址、用戶ID等維度對訪問頻率進行限制。當某個IP或用戶查詢不存在數據的次數達到閾值時,暫時禁止其繼續查詢,從而保護系統不被過度請求壓垮。
數據合法性校驗:在查詢之前,先對數據的合法性進行校驗,比如檢查用戶ID、商品ID等是否合法。對于不合法的查詢,直接返回錯誤,不進行后續處理。

緩存雪崩

緩存雪崩是指在某一時刻,大量緩存同時失效導致所有請求都去查詢數據庫,導致數據庫壓力過大甚至崩潰的情況。

為了避免緩存雪崩,可以采取以下幾種方法
緩存存儲高可用:使用如Redis集群等分布式緩存系統,防止某臺緩存服務器掛掉之后所有緩存丟失導致的雪崩問題。
緩存失效時間設計:為不同的數據設置不同的有效期,盡量保證不要在同一時間失效。可以統一規劃有效期,讓失效時間分布均勻。
熱門數據持續讀取:對于持續被讀取的熱門數據,可以采取定時更新的方式來刷新緩存,避免自動失效。
服務限流和接口限流:通過限流機制控制請求的總量,使系統能夠在緩存全部失效時仍然保持響應,不至于掛掉或影響整個系統。
加鎖控制:在從數據庫獲取緩存需要的數據時加鎖控制,可以使用本地鎖或者分布式鎖。這樣可以保證在緩存失效時,只有少量請求能夠穿透到數據庫進行查詢,從而減輕數據庫的壓力。

緩存擊穿

緩存擊穿是指在高并發訪問下,某個熱點數據失效后,大量請求同時涌入后端存儲(通常是數據庫),導致后端存儲負載增大、響應時間變慢,甚至癱瘓。

為了避免緩存擊穿,可以采取以下幾種方法
互斥鎖:在訪問熱點數據時,使用互斥鎖或分布式鎖來控制并發請求。當一個請求獲取到鎖后,可以查詢數據庫并更新緩存;其他請求則需要等待鎖釋放后才能繼續。這樣可以保證在熱點數據失效時,只有一個請求能夠穿透到數據庫進行查詢。
熱點數據預加載:在系統啟動或緩存數據失效之前,提前將熱點數據預先加載到緩存中。這樣可以確保在大量請求進入系統時,熱點數據已經在緩存中可用,從而避免緩存擊穿。
自動刷新機制:為熱點數據設置自動刷新機制,在緩存失效前主動從數據庫中獲取新數據并更新緩存。這樣可以確保緩存中的數據始終是最新的,并減少因數據失效而導致的緩存擊穿風險。
綜上所述,緩存穿透、緩存雪崩和緩存擊穿都是緩存使用過程中可能遇到的問題。通過合理的策略和方法,可以有效地避免這些問題對系統性能和數據庫穩定性的影響。

7.為什么Redis 單線程卻能支撐高并發?

Redis雖然是單線程的,但它能夠支持高并發業務,這主要歸因于以下幾個關鍵因素:

非阻塞I/O:Redis使用了非阻塞的I/O處理方式。在執行輸入輸出操作時,Redis會向操作系統發出非阻塞式的系統調用(如epoll或kqueue),這樣可以在等待數據準備就緒的同時,繼續處理其他請求,從而提高了系統的并發處理能力。
基于內存的數據存儲:Redis的數據存儲在內存中,這使得其讀寫速度非常快,遠遠超過了基于磁盤的數據庫系統。內存中的數據訪問速度比磁盤快得多,因此在單線程模型下,Redis也能快速地處理大量的讀寫請求。
避免了線程切換開銷:與多線程模型相比,Redis的單線程模型避免了線程切換帶來的開銷,如上下文切換、鎖競爭等。這些開銷在高并發場景下尤為顯著,而Redis通過單線程模型有效地避免了這些問題。
高效的數據結構和算法:Redis內置了豐富的數據結構和高效的算法,如哈希表、跳表等,這使得在處理數據時效率極高。這些高效的數據結構和算法進一步提升了Redis在高并發場景下的性能。
多路復用技術:通過多路復用技術(如select、poll、epoll等),Redis能夠同時監聽多個文件描述符(sockets),從而實現對多個客戶端的并發響應。這種技術使得Redis能夠高效地處理多個并發連接,進一步提升了其并發處理能力。
綜上所述,Redis通過非阻塞I/O、基于內存的數據存儲、避免線程切換開銷、高效的數據結構和算法以及多路復用技術等因素,實現了在單線程模型下支持高并發業務的能力。這些因素共同作用,使得Redis在高并發場景下仍能保持出色的性能表現。

8.說說Redis的內存淘汰策略

Redis的內存淘汰策略是指在Redis的內存達到最大限制時,為了繼續存儲新的數據而采取的一種機制,用于選擇并刪除一些已存在的數據以釋放內存空間。Redis提供了多種內存淘汰策略,以適應不同的應用場景和需求,以下是對這些策略的詳細解釋:
針對設置了過期時間的鍵的策略
volatile-lru:使用LRU(Least Recently Used,最近最少使用)算法從設置了過期時間的鍵中淘汰最久未使用的鍵。
volatile-lfu:使用LFU(Least Frequently Used,最少使用)算法從設置了過期時間的鍵中淘汰最不常使用的鍵。LFU算法會追蹤鍵值對的訪問頻率,并淘汰訪問頻率最低的鍵值對。
volatile-random:隨機從設置了過期時間的鍵中淘汰一個鍵值對。
volatile-ttl:根據鍵的剩余過期時間(TTL)進行淘汰,剩余生存時間越短的鍵越優先被淘汰。這種方式適用于對數據時效性要求較高的場景,如緩存實時數據,可以及時清理過期的數據。
針對所有鍵的策略
allkeys-lru:使用LRU算法從所有鍵中淘汰最久未使用的鍵。
allkeys-lfu:使用LFU算法從所有鍵中淘汰最不常使用的鍵。
allkeys-random:隨機從所有鍵中淘汰一個鍵值對。
不淘汰策略
noeviction:當內存不足以容納新寫入數據時,不會淘汰任何鍵值對,而是直接返回錯誤(DEL請求和部分特殊請求除外)。這是Redis的默認行為(在Redis 3.0及之后版本),旨在保護數據不被意外刪除。
策略選擇與應用
在選擇內存淘汰策略時,需要根據應用程序的訪問模式、數據的重要性和對性能的要求來綜合考慮。例如:
如果應用程序的數據訪問模式符合LRU特性(即最近使用的數據更有可能再次被訪問),那么選擇volatile-lru或allkeys-lru可能是一個好的選擇。
如果希望避免誤淘汰重要數據,并且對數據的時效性有一定要求,那么volatile-ttl可能更適合。
如果不確定數據訪問模式或希望簡單隨機淘汰數據,那么可以選擇volatile-random或allkeys-random策略。
此外,Redis允許在運行時動態修改內存淘汰策略,并使用Redis的info命令輸出來監控緩存未命中和命中的數量,以便根據實際情況調整策略設置。

綜上所述,Redis的內存淘汰策略是一種靈活且強大的機制,能夠幫助開發者在內存受限的情況下有效地管理數據,確保系統的正常運行。

9.Redis的并發競爭問題如何解決?

Redis的并發競爭問題是指在多線程或多進程并發讀寫Redis時可能出現的數據競爭和競爭條件問題,具體表現為多個線程或進程同時對同一個Redis實例進行讀寫操作,導致數據不一致或邏輯錯誤的情況。為了解決Redis的并發競爭問題,可以采取以下幾種方法:

使用事務
Redis支持事務操作,通過MULTI和EXEC命令可以將一系列操作作為一個原子操作執行,從而避免了并發競爭。在事務執行期間,其他客戶端對鍵的讀寫會被阻塞,直到事務完成。事務塊中的所有命令都是原子執行的,要么全部執行成功,要么全部失敗。

使用樂觀鎖
樂觀鎖是一種輕量級的鎖機制,它通過比較版本號或時間戳的方式來實現并發控制。在Redis中,樂觀鎖一般使用WATCH命令和CAS(Compare and Set)操作來實現。客戶端發送WATCH命令來監視一個或多個鍵,如果在事務執行之前這些鍵被其他客戶端修改,則事務執行時會失敗,客戶端可以根據返回的結果進行重試或其他操作。

使用分布式鎖
分布式鎖是一種通過加鎖機制來保護共享資源的方法。在Redis中,可以使用SETNX命令或Redlock算法來實現分布式鎖。SETNX命令用于設置鍵的值,如果鍵不存在則設置成功并返回1,如果鍵已存在則設置失敗并返回0。通過SETNX命令,可以在寫操作前鎖定該資源,從而避免并發競爭。Redlock算法則是一種更復雜的分布式鎖實現,它提供了更高的可靠性和容錯性。

優化連接管理
在高并發場景下,連接競爭也可能導致性能問題。為了優化連接管理,可以使用連接池來管理Redis連接。連接池可以預先創建并維護一定數量的連接,供客戶端在需要時獲取和釋放。這樣可以避免頻繁地創建和關閉連接,從而減少連接競爭并提高性能。

數據分割與增加節點
如果單個Redis實例無法滿足高并發需求,可以考慮將數據分割成多個小的Redis實例,并將并發訪問分散到多個實例上。這樣可以減輕單個實例的負擔并提高并發性能。另外,也可以通過增加Redis實例和節點的方式來提升并發性能和容量。

綜上所述,解決Redis的并發競爭問題需要綜合考慮多個方面的因素,并根據具體的應用場景和需求選擇合適的解決方案。在實際操作中,可以根據系統的性能監控和測試結果來不斷調整和優化這些策略,以確保Redis在高并發場景下的穩定性和可靠性。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 金九銀十即將到來,整理了20道經典Redis面試題,希望對大家有幫助。 1. 什么是Redis?它主要用來什么的?...
    學編程的小屁孩閱讀 1,578評論 0 1
  • 什么是Redis? Redis 是一個開源(BSD許可)的,內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息...
    零一間閱讀 159評論 0 1
  • 什么是Redis? Redis 是一個開源(BSD許可)的,內存中的數據結構存儲系統,它可以用作數據庫、緩存和消息...
    零一間閱讀 488評論 0 0
  • 本文的面試題如下: Redis 持久化機制 緩存雪崩、緩存穿透、緩存預熱、緩存更新、緩存降級等問題 熱點數據和冷數...
    不怕天黑_0819閱讀 1,453評論 1 21
  • 1. Redis有哪些數據結構? 2. 使用過Redis分布式鎖么,它是什么回事? 3. 假如Redis里面有1億...
    xuxw閱讀 104評論 0 0