關於Redis的記憶

1.Redis是什麼

  • Redis是C語言開發的一個開源的高性能鍵值對(key-value)的內存數據庫,與傳統數據庫不一樣的是,Redis是非關係型數據庫,數據是存儲在內存中,讀寫性能很是高,因此Redis經常做爲緩存在系統中存在。
  • Redis還能夠用來作分佈式鎖。
  • Redis提供了多種數據類型來支持不一樣的業務場景。
  • Redis支持事務、持久化、多種集羣方案

2.爲何要用Redis

2.1 提升系統性能

若是碰到須要執行耗時特別久,且結果不頻繁變更的 SQL,就特別適合將運行結果放入緩存。這樣,後面的請求就去緩存中讀取,使得請求可以迅速響應 。redis

2.2 提升系統併發

在大併發的狀況下,全部的請求直接訪問數據庫,數據庫會出現鏈接異常。這個時候,就須要使用 Redis作一個緩衝操做,用緩存預熱將一部分數據提早 加載到Redis中,讓請求先訪問到 Redis,而不是直接訪問數據庫算法

3.Redis和Memcached的區別

  • Redis支持更加豐富的數據類型,好比String、List、Set、Hash、SortedSet等,而Memcached只支持簡單的String類型
  • Redis支持數據的持久化,能夠將內存中的數據保存在磁盤中,重啓的時候能夠再次加載進行使用;而Memcached把全部的數據都在內存中存儲着。
  • Redis3.0以上是原生支持cluster模式的,memcached沒有原生的集羣模式,須要依靠客戶端來實現集中分片寫入數據
  • Memcached是多線程的;Redis是單線程的

4.Redis的數據類型以及應用場景

  • String
    String類型就是簡單的key-value類型,value能夠是String,也能夠是數字,。主要用來簡單的key-value緩存,好比存儲用戶的粉絲數之類的;數據庫

  • hash
    hash是一個field和value的映射表,適合用於存儲對象,好比存儲用戶基本信息,咱們要修改用戶的姓名的時候,就能夠直接修改具體的字段;設計模式

  • List
    Redis list就是鏈表,在項目中應用的也比較多,好比微博的關注列表,粉絲列表等;Redis list能夠經過 lrange 命令,就是從某個元素開始讀取多少個元素,能夠基於 list 實現分頁查詢,這個很棒的一個功能,基於 redis 實現簡單的高性能分頁,能夠作相似微博那種下拉不斷分頁的東西(一頁一頁的往下走),性能高。緩存

  • Set
    set和list相似,也是一個列表功能,可是set是能夠自動去重的,set提供了判斷成員是否在一個set集合內的重要接口;基於set能夠很好的實現交集、並集、差集等。
    好比:在微博應用中,能夠將一個用戶全部的關注人存在一個集合中,將其全部粉絲存在一個集合。Redis能夠很是方便的實現如共同關注、共同粉絲、共同喜愛等功能。服務器

  • Sorted Set
    和set相比,sorted set增長了一個權重參數score,使得集合中的元素可以按score進行有序排列
    舉例: 在直播系統中,實時排行信息包含直播間在線用戶列表,各類禮物排行榜,彈幕消息(能夠理解爲按消息維度的消息排行榜)等信息,適合使用 Redis 中的 Sorted Set 結構進行存儲。網絡

5.Redis的線程模型

反應器設計模式(Reactor pattern) 是一種爲處理併發服務請求,並將請求提交到一個或者多個服務處理程序的事件設計模式。 當客戶端請求抵達後,服務處理程序使用多路分配策略,由一個非阻塞的線程來接收全部的請求,而後派發這些請求至相關的工做線程進行處理。 簡單說,就是如何處理多個客戶端的併發請求的解決模式。多線程

咱們都知道Redis是單線程模型,從內部結構來看,之因此Redis是單線程的,是由於Redis基於Reactor模式開發了本身的網絡事件處理器,這個處理器被稱爲文件事件處理器,而這個文件事件處理器是單線程的,因此Redis纔是單線程模型。文件事件處理器主要包含IO多路複用程序、socket隊列、文件事件分派器、事件處理器。如圖架構

6.Redis的過時策略

咱們都知道Redis是基於內存來存儲的,因此咱們在設置key的時候須要去設置key的過時時間,經過這個過時時間咱們能夠指定這個key在內存中的存活時長,那麼Redis是怎麼來刪除這些過時的key的呢?併發

按期刪除+惰性刪除:

  • 按期刪除:Redis默認是每隔100ms隨機抽取一些設置了過時時間的key進行檢查,判斷key是否過時,若是過時了那就刪除。可是,這樣便會致使不少到了過時時間的key沒有被刪除。
  • 惰性刪除:針對上面的問題,惰性刪除就出現了,惰性刪除是指程序主動去查詢key,再查詢的時候若是過時了那麼就刪除。

可是這樣就有一個問題,若是按期刪除沒有刪除,而後程序也沒有主動去查詢,那麼會致使在內存中存在大量的過時key,進而會致使redis的內存耗盡,因此Redis提供了內存淘汰機制。

7.Redis的內存淘汰機制

Redis提供了六種淘汰機制

  • noeviction:當內存不足以容納新寫入數據時,新寫入操做會報錯
  • allkeys-lru:當內存不足以容納新寫入數據時,在鍵空間中,移除最近最少使用的key(經常使用)
  • allkeys-random:當內存不足以容納新寫入數據時,在鍵空間中,隨機移除某個key
  • volatile-lru:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,移除最近最少使用的key
  • volatile-random:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,隨機移除某個key
  • volatile-ttl:當內存不足以容納新寫入數據時,在設置了過時時間的鍵空間中,有更早過時時間的key優先移除

MySQL裏有2000w數據,Redis中只存20w的數據,如何保證Redis中的數據都是熱點數據?
經過內存淘汰機制咱們能夠淘汰冷數據,將熱數據加載到內存中;計算一下20W數據須要的內存,而後設置Redis的內存限制就行

8. Redis的持久化方式

Redis的持久化方式有兩種:

8.1 RDB方式

  • RDB
    Redis能夠經過建立快照來得到存儲在內存裏面的數據在某個時間點上的副本。Redis建立快照以後,能夠對快照進行備份,能夠將快照複製到其餘服務器從而建立具備相同數據的服務器副本(Redis主從結構,主要用來提升Redis性能),還能夠在便重啓服務器的時候使用。Redis默認使用的是RDB持久化方式。
  • RDB原理
    默認Redis會以快照的形式將數據持久化到磁盤中,是一個二進制文件,dump.rdb;當Redis須要作持久化的時候,Redis會fork一個子進程,子進程負責將數據寫到磁盤的一個臨時rdb文件中,當子進程寫完臨時文件的時候,會直接將原來的RDB文件替換掉。
  • RDB的優勢
    RDB持久化的文件很是適合用於備份,好比說,你能夠在最近的 24 小時內,每小時備份一次 RDB 文件,而且在每月的每一天,也備份一個 RDB 文件。 這樣的話,即便趕上問題,也能夠隨時將數據集還原到不一樣的版本。RDB 很是適用於災難恢復。
  • RDB的缺點
    若是須要儘可能避免在服務器故障時丟失數據,RDB方式就不適合。 雖然 Redis 容許設置不一樣的保存點(save point)來控制保存 RDB 文件的頻率,可是由於RDB 文件須要保存整個數據集的狀態, 因此它並非一個輕鬆的操做。 所以咱們可能會至少 5 分鐘才保存一次 RDB 文件。在這種狀況下 一旦發生故障停機,就可能會丟失好幾分鐘的數據。

8.2 AOF方式

把全部的對Redis的服務器進行修改的命令都存到一個文件裏,命令的集合。

  • AOF
    使用AOF作持久化,每個命令都會被追加到appendonly.aof中
  • AOF優勢
    AOF的默認策略爲每秒鐘 fsync 一次,固然了也能夠設置每一次命令執行一次,在默認配置下,Redis 仍然能夠保持良好的性能,而且就算髮生故障停機,也最多隻會丟失一秒鐘的數據( fsync 會在後臺線程執行,因此主線程能夠繼續努力地處理命令請求)。

Redis4.0支持同時開啓 RDB 和 AOF,系統重啓後,Redis 會優先使用 AOF 來恢復數據,這樣丟失的數據會最少。

9.緩存雪崩、緩存穿透、緩存擊穿問題及解決方案

9.1 緩存雪崩

  • 問題描述
    在同一時間緩存中的key出現大面積的失效,會致使全部的請求所有落在數據庫上,短期內數據庫沒法承擔這麼多請求可能會崩掉
  • 解決方案
    在設置key的時候過時時間加上一個隨機值;對於熱點數據能夠設置永不過時

9.2 緩存穿透

  • 問題描述
    通常是黑客故意去請求緩存中不存在的數據,致使全部的請求都落到數據庫上,形成數據庫短期內承受大量請求而崩掉。
  • 解決方案
    有不少種方法能夠有效地解決緩存穿透問題,最多見的則是採用布隆過濾器,將全部可能存在的數據哈希到一個足夠大的bitmap中,一個必定不存在的數據會被 這個bitmap攔截掉,從而避免了對底層存儲系統的查詢壓力。另外也有一個更爲簡單粗暴的方法,若是一個查詢返回的數據爲空(不論是數 據不存在,仍是系統故障),咱們仍然把這個空結果進行緩存,但它的過時時間會很短,最長不超過五分鐘。

9.3 緩存擊穿

  • 問題描述 緩存擊穿與緩存雪崩不一樣的是緩存擊穿是指一個Key很是熱點,在不停地扛着大量的請求,大併發集中對這一個點進行訪問,當這個Key在失效的瞬間,持續的大併發直接落到了數據庫上,就在這個Key的點上擊穿了緩存
  • 解決方案
    1.熱點key設置永不過時;
    2.獲取加上互斥鎖,若是緩存中爲空,在獲取數據的緩存接口加上互斥鎖,經過遞歸來查詢數據,當拿到鎖的線程從數據庫中查詢出數據更新到緩存中,其餘的線程也能夠獲取到

10 Redis的架構模式

10.1 單機版

單個節點redis,通常生產環境中不會使用

10.2 主從架構

經過持久化功能,Redis保證了即便在服務器重啓的狀況下也不會損失(或少許損失)數據,由於持久化會把內存中數據保存到硬盤上,重啓會從硬盤上加載數據。 。可是因爲數據是存儲在一臺服務器上的,若是這臺服務器出現硬盤故障等問題,也會致使數據丟失。爲了不單點故障,一般的作法是將數據庫複製多個副本以部署在不一樣的服務器上,這樣即便有一臺服務器出現故障,其餘服務器依然能夠繼續提供服務。爲此, Redis 提供了複製(replication)功能,能夠實現當一臺數據庫中的數據更新後,自動將更新的數據同步到其餘數據庫上。

在複製的概念中,數據庫分爲兩類,一類是主數據庫(master),另外一類是從數據庫(slave)。主數據庫能夠進行讀寫操做,當寫操做致使數據變化時會自動將數據同步給從數據庫。而從數據庫通常是隻讀的,並接受主數據庫同步過來的數據。一個主數據庫能夠擁有多個從數據庫,而一個從數據庫只能擁有一個主數據庫。

redis的普通主從模式,能較好地避免單獨故障問題,以及提出了讀寫分離,下降了Master節點的壓力。互聯網上大多數的對redis讀寫分離的教程,都是基於這一模式或架構下進行的。但實際上這一架構並不是是目前最好的redis高可用架構。

10.3 哨兵模式

當主數據庫遇到異常中斷服務後,開發者能夠經過手動的方式選擇一個從數據庫來升格爲主數據庫,以使得系統可以繼續提供服務。然而整個過程相對麻煩且須要人工介入,難以實現自動化。 爲此,Redis 2.8開始提供了哨兵工具來實現自動化的系統監控和故障恢復功能。 哨兵的做用就是監控redis主、從數據庫是否正常運行,主出現故障自動將從數據庫轉換爲主數據庫。

顧名思義,哨兵的做用就是監控Redis系統的運行情況。它的功能包括如下兩個。

(1)監控主數據庫和從數據庫是否正常運行。
(2)主數據庫出現故障時自動將從數據庫轉換爲主數據庫。

10.4 redis-cluster羣集高可用架構

即便使用哨兵,redis每一個實例也是全量存儲,每一個redis存儲的內容都是完整的數據,浪費內存且有木桶效應。爲了最大化利用內存,能夠採用cluster羣集,就是分佈式存儲。即每臺redis存儲不一樣的內容。 採用redis-cluster架構正是知足這種分佈式存儲要求的集羣的一種體現。redis-cluster架構中,被設計成共有16384個hash slot。每一個master分得一部分slot,其算法爲:hash_slot = crc16(key) mod 16384 ,這就找到對應slot。採用hash slot的算法,其實是解決了redis-cluster架構下,有多個master節點的時候,數據如何分佈到這些節點上去。

在redis-cluster架構中,redis-master節點通常用於接收讀寫,而redis-slave節點則通常只用於備份,其與對應的master擁有相同的slot集合,若某個redis-master意外失效,則再將其對應的slave進行升級爲臨時redis-master。在redis的官方文檔中,對redis-cluster架構上,有這樣的說明:在cluster架構下,默認的,通常redis-master用於接收讀寫,而redis-slave則用於備份,當有請求是在向slave發起時,會直接重定向到對應key所在的master來處理。但若是不介意讀取的是redis-cluster中有可能過時的數據而且對寫請求不感興趣時,則亦可經過readonly命令,將slave設置成可讀,而後經過slave獲取相關的key,達到讀寫分離

參考文檔:

Redis線程模型
Redis持久化RDB和AOF
redis架構演變與redis-cluster羣集讀寫方案
一文看懂Redis的持久化原理
簡明的圖解Redis RDB持久化、AOF持久化

相關文章
相關標籤/搜索