天天看點

Redis 的作用以及怎麼用redis的詳細的分析

面試時被面試官問到 Redis 了 ,當時那分鐘就隻知道是資料緩存

我後來百度總結了一下 分享給大家 ,希望能幫到你們

什麼是Redis

Redis是一款記憶體高速緩存資料庫。Redis全稱為:Remote Dictionary Server (遠端資料服務),使用C語言編寫,Redis是一個key-value存儲系統(鍵值存儲系統),支援豐富的資料類型,如:String、list、set、zset、hash。

Redis是一種支援key-value等多種資料結構的存儲系統。可用于緩存,事件釋出或訂閱,高速隊列等場景。使用C語言編寫,支援網絡,提供字元串,哈希,清單,隊列,集合結構直接存取,基于記憶體,可持久化。

1.使用redis緩存的好處

  • 提高并發量,不需要每次都通路資料庫,提高并發量。 提高性能,redis運作在内
  • 存中,記憶體的執行效率,遠遠超過資料庫。

2.Redis的key和value的存儲大小有限制嗎?

Redis的key和value的存儲大小都是有限制的,都是512M。

3.redis存儲什麼資料類型

(1)字元串(String)

(2)字元串清單(lists)

(3)字元串集合(sets)

(4)有序字元串集合(sorted sets)

(5)哈希(hash)

4.使用redis緩存的弊端

  • 緩存穿透,大量的請求通路,查詢的是資料庫中不存在的資料,就會在緩存中無法命中,直接去通路資料庫,資料庫中也查詢不到,自然無法将結果寫入緩存,下一秒又有大量請求查詢不存在的資料,導緻資料庫最終挂掉(要麼系統出bug,要麼黑客惡意攻擊)

解決方案:

  • 在資料庫中沒有查詢到的資料,存儲一個特定值到緩存中,這樣下次惡意通路就可以去緩存中查詢到資料,不會通路到資料庫.注意的是這些特定的key,需要設定過期時間,避免黑客攻擊時,大量的無效key把redis存滿。
  • 緩存雪崩,大規模的key失效,大量的請求通過key通路到資料庫,導緻資料庫直接崩潰,然後系統直接癱瘓.
  • 解決方案:

    事前: 保證redis叢集的高可用性,redis cluster,主從機制;

    事中: hystrix(熔斷器)限流+降級,避免資料庫被打死.高并發的通路量走hystrix限流元件,讓通路量保持在資料庫最大負載範圍内,保證資料庫不被打死,系統可以繼續使用.剩餘的請求走降級元件,傳回一些預設的值或者是友情提示等

    事後: redis持久化機制,盡快回複緩存叢集,一旦重新開機,自動從磁盤上加載資料,回複記憶體中的資料

  • 緩存與資料庫不一緻,修改資料時,資料庫和緩存資料不一緻。 最初級的緩存不一緻:

    出現場景:

    先修改資料庫,再删除緩存,如果修改緩存失敗,就會導緻資料庫中式新資料,緩存中是舊資料,資料不一緻 解決思路:

    先删除緩存,再修改資料庫,如果删除緩存成功,修改資料庫失敗,那麼資料庫中是舊資料,緩存中是空的,讀的時候緩存中沒有,去資料庫中讀舊資料,然後更新到緩存中去

  • 高并發場景下資料庫與緩存的資料不一緻:

    出現場景:

    讀寫并發請求,導緻資料庫和緩存中的資料不一緻,在寫請求删除緩存,修改資料庫庫存還未成功時,查詢庫存的請求就發來,先去緩存中查詢,發現是空,然後去資料庫中查,然後将結果放入緩存中,然後修改庫存的操作成功,導緻資料庫中是新資料,緩存中是舊資料

  • 解決思路:

    相同的商品id,進行哈希取值,再加上對記憶體隊列的數量進行取模,每個商品都可以路由到某一個記憶體隊列中,然後将去請求和寫請求串行化,這樣就可保證一定不會出現不一緻的情況,但是會導緻系統的吞吐量會大幅降低

  • 緩存并發競争,同一時間,多個線程來執行,操作同一個key。 解決思路:

    方式一:分布式鎖,(zookeeper分布式鎖),確定同一時間,隻能由一個系統執行個體在操作某個key,别的執行個體不被允許讀和寫

    方式二:樂觀鎖 ,每次要寫之前,先判斷這個value的時間戳是否比緩存裡的更新,如果新就允許寫.

5.為什麼redis是單線程的但是還可以支撐高并發?

  • redis線程模型:redis裡有個處理器叫做檔案事件處理器(file event handler),這個檔案事件處理器是單線程的執行的,redis是以是單線程的模型。

執行流程:

  • redis啟動初始化時,redis會将連接配接應答器和AE_READABLE事件關聯
  • 用戶端跟redis連接配接,會在serverSocket産生一個AE_READABLE事件,然後由IO多路複用程式監聽到事件,将serverSocket壓入隊列,然後連接配接應答處理器來處理事件,和用戶端建立連接配接,建立對應的socket,同時将這個socket的AE_READABLE事件跟指令請求處理器關聯起來
  • 用戶端向redis發起請求時,首先會在socket中産生一個AE_READABLE事件,然後被監聽,被壓入隊列,然後由對應的指令請求處理器來處理
  • redis準備好給用戶端響應資料之後,就會将socket的AE_WRITABLE指令跟回複處理器關聯起來,當用戶端準備好讀取響應資料時,就會在socket上産生一個AE_WRITABLE事件,會由對應的指令回複處理器來處理
  • 指令回複處理器處理完之後,就會删除這個socket的AE_WRITABLE事件和指令回複處理器的關聯關系

6.Redis為什麼效率高?

  • 核心是基于非阻塞的IO多路複用機制,由監聽程式輪詢等待的事件,然後壓入隊列,可以達到一個線程同時處理多個io請求的目的
  • 純記憶體操作
  • 單線程避免了多線程的頻繁切換問題

7.Redis由哪些資料類型,分别在哪些場景下使用?

  • String,存儲基本的類型
  • List,有序清單,比如之前項目中的廣告緩存,用的就是list集合進行緩存的,它可以用于比如存儲粉絲清單,文章的評論清單等等
  • Set,無序清單,它最主要的特點就是去重,比如微網誌上查詢兩個明星的共同粉絲,就可以用set進行去重
  • SortSet,它主要是在set的基礎上加上了排序功能
  • Hash,類似map的集合,一般可以用來存儲對象,我們系統中的購物車對象就是以hash類型存儲在redis中,key就是使用者的id,value就是購物車對象

8.Redis過期政策

  • 定期删除配合惰性删除
  • 定期删除,指的是redis預設每個100ms就抽取一些設定了過期事件的key,檢查是否過期,如果過期就删除.如果太多的key都設定了過期時間,每隔幾百毫秒,就全部檢查删除,cpu的負載會很高.實際上redis是每隔100ms随機抽取一些key來檢查和删除.
  • 惰性删除,就是當你擷取key時,redis就會檢查一下,如果key過期了,就删除,不會傳回,如果沒過期就傳回
  • 因為redis的過期政策會導緻你設定了過期key,過期了很多過期key沒有被删除,還堆積在記憶體中,此時就要設定記憶體淘汰機制來解決了
  • 記憶體淘汰機制
  • noevication:當記憶體不足以容納寫入新資料時,新寫入操作就會報錯
  • allkeys-lru:當記憶體不足以容納新寫入資料時,在鍵空間中,移除最近最少使用的key
  • allkeys-random:在鍵空間中,随機移除某個key
  • volatile-lru:在設定了過期時間的鍵空間中,移除最近最少使用的key
  • volatile-random:在設定了過期時間的鍵空間中,随機移除某個key
  • volatile-ttl:在設定了過期時間的鍵空間中,由更早過期時間的key優先移除

9.怎樣做redis支撐高并發(讀多寫少用緩存,讀少寫多用隊列)

  • 搭建redis叢集,做成主從架構,一主多從,通過redis replication機制實作讀寫分離,主負責寫,并且将資料同步複制到其他slave(從)節點上,從節點負責讀,所有的讀請求走從節點.好處,可支援水準擴容的讀高并發架構
  • redis replication的核心機制
  • redis采用異步方式複制資料都slave節點上,slave節點會周期性的确認自己每次複制的資料量
  • 一個master(主)節點可以配置多了slave節點
  • slave節點也可以連接配接其他slave節點
  • slave節點做複制的時候,也不會阻塞對自己的查詢操作,它會用舊資料向外提供服務;複制完後,它就删除舊資料,加載新資料,這個時候向外停止服務(毫秒級别)
  • slave節點主要用來橫向擴容,做讀寫分離,提高吞吐量

Master(主節點)持久化對于主從架構的安全保障的意義

  • 如果僅僅用slave節點作為master節點的資料熱備份,當master節點當機後重新開機,資料清空,本地沒有資料可以恢複,它會任為自己的資料就是空的,然後同步到slave節點上,就會導緻資料百分百丢失
  • 其次,如果開啟了哨兵機制,在master節點挂掉之後,會迅速推選出一個slave節點去做master節點,但是當哨兵還沒檢測到master節點挂掉,master節點就自動重新開機了,還是會出現上面的情況

redis主從架構的核心原理

  • 當啟動一個slave節點時,會發送一個PSYNC指令給master節點
  • 如果這個slave節點第一次連接配接master節點,就會出發full resynchronization
  • 開始full resynchronization的時候,master會開啟一個背景線程,開始生成一份rdb快照檔案,同時還還會繼續接收用戶端的寫指令,存在記憶體中.RDB檔案生成完畢後,master會将這個RDB發送給slave,slave先将RDB寫入本地自盤,然後再加載到記憶體.然後master會将記憶體中緩存的寫指令發送給slave,slave同步這些資料

redis的高可用

  • 不可用: 雖然主從架構,讀寫分離可以保證緩存應對高并發場景,但是如果master節點挂掉,整個緩存架構就會挂掉,大量的流量湧入資料庫,超過資料庫的最大承載壓力,資料庫挂掉,整個系統就會挂掉不可用
  • 高可用: 故障轉移,主備切換,當master故障時,自動檢測(通過sentinal node 哨兵),将某個slave自動切換成master的過程交主備切換.這個機制實作了redis主從架構下的高可用性

10.redis的持久化

  • 如果沒有持久化,遇到災難性故障時,就會丢失所有資料,如果開啟持久化到磁盤,定期備份到雲服務上,就能保證遇到災難性故障,就不會丢失全部資料
  • RDB
  • 當redis需要做持久化時,redis會fork一個子程序,将資料寫到磁盤寫上一個臨時RDB檔案中,當子程序完成寫臨時檔案後,将原來的RDB換掉
  • 優勢:

    适合做冷備份,在最壞的情況下,恢複資料要比AOF快

    對redis對外提供讀寫服務,影響服務非常小

    RDB資料快照檔案更少

  • AOF
  • 可以做到更精細的持久化,redis每執行一個修改資料的指令,都會将它添加到os cache中,一般會每個一秒執行一次fsync操作,保證将os cache中的資料寫入磁盤中AOF日志檔案中,AOF日志檔案以append-only模式寫入,檔案不容易破損,在AOF日志過大時,就會出現背景重寫
  • 優勢:

    AOF可以更好的保護資料不丢失,丢失的資料更少

    AOF日志檔案以append-only模式寫入,沒有磁盤尋址的開銷,寫入性能非常高

    AOF日志過大時,也不會影響用戶端的讀寫

  • RDB和AOF到底如何抉擇
  • 綜合使用兩種持久化機制,用AOF保證資料不丢失,作為資料恢複的第一選擇,用RDB來做不同程度的冷備份,在AOF檔案丢失或者損壞不可用的情況下,用RDB來進行快速的資料回複

11.redis怎麼設定緩存大小

打開redis配置檔案

示例:maxmemory 100mb

機關:mb,gb。

預設為0,沒有指定最大緩存,如果有新的資料添加,超過最大記憶體,則會使redis崩潰,是以一點要設定。

設定maxmemory之後,配合的要設定緩存資料回收政策, 可以通過設定LRU算法來删除部分key,釋放空間(LRU是Least Recently Used 近期最少使用算法。)。

就可以修改緩存大小為16gb.

12.redis叢集主從資料如何同步

答1:

Redis主從同步有兩種方式:全同步和部分同步。主從剛剛連接配接的時候,進行全量同步;全同步結束後,進行增量同步。

答2:

(1)全量同步:

Redis全量複制一般發生在S-ave初始化階段,這時S-ave需要将Master上的所有資料都複制一份。具體步驟如下:

  1)從伺服器連接配接主伺服器,發送SYNC指令;

  2)主伺服器接收到SYNC命名後,開始執行BGSAVE指令生成RDB檔案并使用緩沖區記錄此後執行的所有寫指令;

  3)主伺服器BGSAVE執行完後,向所有從伺服器發送快照檔案,并在發送期間繼續記錄被執行的寫指令;

  4)從伺服器收到快照檔案後丢棄所有舊資料,載入收到的快照;

  5)主伺服器快照發送完畢後開始向從伺服器發送緩沖區中的寫指令;

  6)從伺服器完成對快照的載入,開始接收指令請求,并執行來自主伺服器緩沖區的寫指令;

  

(2)增量同步:

Redis增量複制是指S-ave初始化後開始正常工作時主伺服器發生的寫操作同步到從伺服器的過程。

增量複制的過程主要是主伺服器每執行一個寫指令就會向從伺服器發送相同的寫指令,從伺服器接收并執行收到的寫指令

(3)Redis主從同步政策:

主從剛剛連接配接的時候,進行全量同步;全同步結束後,進行增量同步。當然,如果有需要,s-ave 在任何時候都可以發起全量同步。redis 政策是,無論如何,首先會嘗試進行增量同步,如不成功,要求從機進行全量同步。

13.Redis緩存穿透和redis雪崩處理

(1)緩存穿透

​ 一般的緩存系統,都是按照key去緩存查詢,如果不存在對應的value,應該去後端系統查詢(比如資料庫)。如果key對應的value不存在,并且對key并發請求量很大,就會對後端系統造成很大的壓力。這就叫做緩存穿透。

解決方案(晦澀)

對所有可能查詢的參數以hash形式存儲,在控制層先進行校驗,不符合則丢棄。還有最常見的則是采用布隆過濾器,将所有可能存在的資料哈希到一個足夠大的bitmap中,一個一定不存在的資料會被這個bitmap攔截掉,進而避免了對底層存儲系統的查詢壓力。

也可以采用一個更為簡單粗暴的方法,如果一個查詢傳回的資料為空(不管是數 據不存在,還是系統故障),我們仍然把這個空結果進行緩存,但它的過期時間會很短,最長不超過五分鐘。

(2)緩存雪崩

​ 當緩存伺服器重新開機或者大量緩存集中在某一個時間段失效,這樣在失效的時候,也會給後端系統(比如資料庫)帶來很大的壓力。

​ 緩存雪崩是指在我們設定緩存是采用了相同的過期時間,導緻緩存在某一時期同時失效,請求全部轉發到DB,DB瞬間壓力過大雪崩。

​ 解決方案:

​ 把緩存時間分散開,比如在原來的時間基礎上增加一個随機值,比如1~5分鐘随機,這樣每一個緩存的過期時間的重複率就會降低,就很難引發集體失效的事件。

繼續閱讀