一文看盡Redis

前沿:

要想了解一個知識,首先要了解是什麼情景需要運用這項技術,這項技術在此情景解決了什麼問題,要想要深入瞭解Redis,我們應先了解一下關於數據庫的處理數據的歷史,關鍵點就是數據不斷變多,如何處理數據


數據庫處理數據歷史


單機Mysql

小李剛剛大學畢業,開始創業,建了一個購物網站,名氣不大,偶爾有人登錄此網站點一點
在這裏插入圖片描述

特點:

  • 訪問量少,
  • 靜態頁面,前後端交互少
  • 服務器壓力小

隨着小李的努力,訪問數量急劇增加,數據庫的壓力也隨之增加,小李開始了對數據庫的本身的優化(數據結構和索引),但是,問題還是不能很好的解決

  • 數據量太大,一個服務器放不下了
  • 訪問量(讀寫混合),一個服務器承受不了
  • 數據的索引,一個服務器的內存也放不下

經過一番思所和分析,小李發現網站80%都是在讀,每次都要查數據庫的話十分麻煩,怎樣能減輕數據的壓力呢?

加入緩存(Memcached),用戶訪問時,先去緩存中(根據一定的規則,從數據庫中獲取數據存到緩存中)查,查到了則不去數據庫查,查不到在去數據庫查

加入緩存,雖然解決了一些問題,但是還是不能夠應對用戶的增長的速度,小李決定增加幾臺服務器,但是呢?又遇到一個問題,新增的服務器之間怎麼通信,怎麼能保證數據都一致呢?

Memcached(緩存)隨之出世

  • Memcached的分佈方法
    a.向Memcached添加數據,首先根據客戶端算法利用key選擇保存的服務器;
    b.服務器選定後,保存數據
    c.獲取數據時,以相同的key,相同的算法可以定位到相同的服務器位置,從而獲取數據
  • Memcached的分佈式算法
    Memcached使用的分佈式算法中,我們簡單介紹兩種:餘數哈希;一致性哈希
    A.餘數哈希
    根據服務器臺數的餘數進行哈希,求得鍵的哈希值,再處理服務器臺數,根據餘數選擇服務器,
    缺點:當添加或者移除服務器時,緩存重組的代價太大,
    當添加服務器,訪問數據,Memcached命中率下降,那麼就增加了數據庫服務器的負載.
    B.一致性哈希
    一致性哈希是將整個哈希值空間組織成一個虛擬的圓環,如假設某哈希函數H的值空間是0~(2^32 -1)(即哈希值是一個32位的無符號整型),這個哈希空間爲環
    哈希空間按順時針方向組織.爲確定每臺服務器在空間上的位置,按照服務器主機名或者IP地址對每臺服務器進行Hash尋址.然後需要使用hash算法來判斷數據應該存儲在哪個服務器:首先,將數據根據key值使用相同的函數H計算出哈希值h,根據h確定數據在環上的位置,從此位置延環順時針向下尋找,遇到的第一個服務器就是其應該存儲的服務器
    附帶一篇關於Memcached博客



Memcached(緩存)+MySQL+垂直拆分

這一模式主要解決了數據庫讀壓力
在這裏插入圖片描述
用於用戶的增多,訂單和物品的品種都隨之增加,數據庫的寫入壓力也倍增,而Memcached只能緩解數據庫的讀取壓力,讀寫集中在一個數據庫上讓數據庫不堪重負,小李靈機一動,運用主從複製,達到讀寫分離,以提高數據庫的讀寫性能和讀庫的可擴展性



MySQL主從讀寫分離

解決讀寫性能和讀庫的可擴展性—可以不斷地增加從數據庫,以減輕主數據庫的壓力,主寫從讀
在這裏插入圖片描述
小李的事業進一步發展,公司開始上市,用戶,訂單更是急劇增加,寫入壓力指數級增長,一臺服務器的寫入已然是杯水車薪,剛好市面上開始流行分表分庫來緩解寫壓力和數據增長的擴展問題,而MySQL官網也推出了MySQL集羣,爲小李這一問題給出瞭解決方案



分庫分表+水平拆分+mysql集羣

主要解決寫壓力
在這裏插入圖片描述
附帶關於分庫分表知識的博客



NoSQL的出現

首先我們要知道MySQL的瓶頸,才能更好的理解NoSQL

MySQL數據庫也經常存儲一些大文本字段,導致數據庫表非常的大,在做數據庫恢復的時候就導致非常的慢,不容易快速恢復數據庫。比如1000萬4KB大小的文本就接近40GB的大小,如果能把這些數據從MySQL省去,MySQL將變得非常的小。關係數據庫很強大,但是它並不能很好的應付所有的應用場景。MySQL的擴展性差(需要複雜的技術來實現),大數據下IO壓力大,表結構更改困難,正是當前使用MySQL的開發人員面臨的問題。
歸結三點

  • 存大文本的時候,導致數據庫表非常的大,出錯之後還不易恢復
  • 數據種類繁多,表結構難更改,擴展性能差,牽一髮而動全身(關係型,一環套一環)
  • 存在磁盤上,大數據下IO壓力大,性能低下

如何解決以上的問題呢?

  • 內存存儲:降低磁盤IO次數,越低越好—Redis,基於內存的
  • 僅存儲數據:去除數據間關係,越簡單越好—NoSQL,非關係型數據庫



NoSQL


簡介

NoSQL = Not Only SQL (不僅僅是SQL) 關係型數據庫:表格 ,行 ,列
泛指非關係型數據庫的,隨着web2.0互聯網的誕生!傳統的關係型數據庫很難對付web2.0時代!尤其 是超大規模的高併發的網站! 暴露出來很多難以克服的問題,而非關係型的數據庫則由於其本身的特點得到了非常迅速的發展。NoSQL數據庫的產生就是爲了解決大規模數據集合多重數據種類帶來的挑戰,尤其是大數據應用難題,包括超大規模數據的存儲。
很多的數據類型用戶的個人信息,社交網絡,地理位置。這些數據類型的存儲不需要一個固定的格式! 不需要多餘的操作就可以橫向擴展的 !

作用

應對基於海量用戶和海量數據前提下的數據處理

特徵

  • 可擴容,可伸縮(數據之間沒有關係,很好擴展!)
  • 大數據量下高性能
  • 靈活的數據模型(不需要事先設計數據庫!隨取隨用!)
  • 高可用(集羣)

四大分類

  • KV鍵值對:redis
  • 文檔型數據庫:MongoDB
  • 列存儲數據庫:HBase
  • 圖關係數據庫:Neo4j

應用場景

商品的附加信息,如描述,詳情,評論—MogoDB
熱點信息,如搶購,秒殺—Redis



Redis


簡介

Redis(Remote Dictionary Server ),即遠程字典服務
redis是一個開源的、使用C語言編寫的、支持網絡交互的、可基於內存也可持久化的Key-Value數據庫。
支持多種類型的數據結構:如:字符串、哈希、列表、集合、有序集合等
可用作數據庫、緩存、消息中間件

特徵

  • 數據間沒有必然的關聯關係
  • 內部採用單線程機制工作
  • 高性能:Redis 一秒寫8萬次,讀取11萬,NoSQL的緩存記錄級,是一種細粒度的緩存,性 能會比較高!
  • 多數據類型支持:string、list、hash、set、sorted_set
  • 持久化支持,可以進行數據災難恢復

應用場景

  • 爲熱點數據加速查詢,如熱點新聞,諮詢
  • 任務隊列,如秒殺,搶購
  • 即時信息查詢,如排行榜,在線人數
  • 時效性信息控制:如驗證碼控制
  • 分佈式數據共享,如分佈式集羣架構中session分離
  • 消息隊列
  • 分佈式鎖



數據類型

Redis一共支持五種數據類型:String(字符串)、hash(哈希)、list(列表)、set(集合)和zset(sorted set有序集合)

​ String(字符串):Redis最基本的數據類型,一個鍵對應一個值,一個鍵值最大存儲512MB

​ Hash(哈希):hash是一個鍵值對的集合,是一個String類型的field和value的映射表,適合用於存儲對象

​ List(列表):是redis的簡單的字符串列表,按插入順序排序

​ Set(集合):是String字符串類型的無序集合,也不可重複

​ ZSet(sorted set 有序集合)是String類型的有序集合,也不可重複。有序集合中的每個元素都需要指定一個分數,根據分數對元素進行升序排序。

附帶詳細解釋數據類型及其應用場景



事務


爲什麼要有事務

情景分析:如果用戶取錢,不止是一個操作就可以完成,需要多個操作一起完成才能完成一個取錢的操作,如用戶餘額的減少和用戶餘額的更新,這兩個操作必須是要麼一起成功,要麼一起失敗的—原子性

簡介

redis事務就是一個命令執行的隊列,將一系列預定義命令包裝程一個隊列,當執行時,一次性按照添加順序依次執行,中間不會被打斷或者干擾

特性

  • 一次性
  • 順序性
  • 排他性

附加詳細的事務和代碼博客




爲什麼有鎖

情景分析:
如多個業務員同時進行補貨的時候,那麼一名業務員補貨之後,同時操作的業務員就不可以在原來的數量上操作,應該在那一名業務員補貨之後的數量操作,
要點:

  • 多個用戶同時對一組數據進行操作,並且一旦該數據被修改後,將不適用於在繼續操作
  • 在操作之前鎖定要操作的數據,一旦發生變化,終止當前操作

樂觀鎖

開啓事務前,設置對數據的監聽(watch),EXEC時,如果發生數據發生過修改,事務會自動取消(DISCARD),事務EXEC後,無論成敗,監聽會被移除

悲觀鎖

每次去拿數據的時候都認爲別人會修改,所以每次在拿數據的時候都會上鎖。
場景:如果項目中使用了緩存且對緩存設置了超時時間。
當併發量比較大的時候,如果沒有鎖機制,那麼緩存過期的瞬間,
大量併發請求會穿透緩存直接查詢數據庫,造成雪崩效應。

附帶鎖的應用情景



持久化


爲什麼要有持久化

現實中如果遇到意外斷電的情況,放置數據的意外丟失,確保數據的安全性

什麼是持久化

利用永久性存儲介質將數據進行保存,在特定的事件將保存的數據進行恢復的工作機制稱爲持久化

兩種形式

RDB

將當前數據狀態進行保存,快照形式,存儲數據結果,存儲格式簡單,關注點在數據
在這裏插入圖片描述

AOF

將數據的操作過程進行保存,日誌形式,存儲操作過程,存儲格式複雜,關注帶你在數據的操作過程
在這裏插入圖片描述

詳細的持久化博客



過期數據


爲什麼要有過期數據

因爲內存有限,有些數據不需要一直在內存中,可以設定一些規則,將一些數據設置過期,在內存中刪除,當然也不是隨便刪除,也要考慮到CPU的繁忙與空閒,以免出現Redis各種命令執行很多,但是正好出現大量過期數據,已造成服務器宕機

刪除策略

定時刪除

創建一個定時器,當key設置有過期實踐,且過期時間到達時,由定時器任務立即執行對鍵的刪除操作

惰性刪除

數據到達過期時間,不做處理,等下次訪問該數據時進行處理,如未過期,返回數據,發現已過期,刪除,返回不存在

定時刪除

週期性輪詢redis庫中的時效性數據,採用隨機抽取的策略,利用過期數據佔用的方式控制刪除頻度

附帶詳細的過期數據博客



逐出算法


爲什麼要由逐出算法

情景分析,如果有新數據進入redis,但是數據都沒有過期,而且內存也不足,那麼這時就需要逐出算法,來騰出一些空間

逐出算法

  • 檢查易失數據(可能會過去的數據)
  1. volatile-lru:挑選最近最少使用的數據淘汰
  2. volatile-lfu:挑選最近使用次數最少的數據淘汰
  3. volatile-ttl:挑選將要過期的數據淘汰
  4. volatile-random:任意選擇數據淘汰
  • 檢查全庫數據
  1. allkeys-lru:挑選最近最少使用的數據淘汰
  2. allkeys-lfu:挑選最近使用次數最少的數據淘汰
  3. allkeys-random:任意選擇數據淘汰
  • 放棄數據驅逐
  1. no-enviction:禁止驅逐數據
    以上在redis.conf文件中修改
maxmemory-policy volatile-lru

附帶詳細逐出算法博客



集羣


爲什麼要有集羣

單個Redis存在不穩定性,當Redis服務宕機或硬盤故障,系統崩潰之後,就沒有可用的服務了,還會造成數據的丟失
單個Redis的讀寫能力也是有限的

概念

通過添加服務器的數量,提供相同的服務,從而讓服務器達到一個穩定,高效的狀態

三種模式

  • 主從模式
  • 哨兵模式
  • Cluster模式

主從模式

在這裏插入圖片描述

  • 主數據庫可以進行讀寫操作,當讀寫操作導致數據變化時會自動將數據同步給從數據庫
  • 從數據庫一般都是隻讀的,並且接收主數據庫同步過來的數據
  • 一個master可以擁有多個slave,但是一個slave只能對應一個master
  • slave掛了不影響其他slave的讀和master的讀和寫,重新啓動後會將數據從master同步過來
  • master掛了以後,不影響slave的讀,但redis不再提供寫服務,master重啓後redis將重新對外提供寫服務
  • master掛了以後,不會在slave節點中重新選一個master

哨兵模式

在這裏插入圖片描述

哨兵(sentinel)是一個分佈式系統,用於對主從結構中的每臺服務器進行監控,當出現故障時通過投票機制選擇新的master並將所有slave連接到新的master

Cluster

redis最開始使用主從模式做集羣,若master宕機需要手動配置slave轉爲master;後來爲了高可用提出來哨兵模式,該模式下有一個哨兵監視master和slave,若master宕機可自動將slave轉爲master,但它也有一個問題,就是不能動態擴充;所以在3.x提出cluster集羣模式。

在這裏插入圖片描述

redis cluster在設計的時候,就考慮到了去中心化,去中間件,也就是說,集羣中的每個節點都是平等的關係,都是對等的,每個節點都保存各自的數據和整個集羣的狀態。每個節點都和其他所有節點連接,而且這些連接保持活躍,這樣就保證了我們只需要連接集羣中的任意一個節點,就可以獲取到其他節點的數據。
那麼redis 是如何合理分配這些節點和數據的呢?
Redis 集羣沒有並使用傳統的一致性哈希來分配數據,而是採用另外一種叫做哈希槽 (hash slot)的方式來分配的。redis cluster 默認分配了 16384 個slot,當我們set一個key 時,會用CRC16算法來取模得到所屬的slot,然後將這個key 分到哈希槽區間的節點上,具體算法就是:CRC16(key) % 16384。

附帶集羣詳細博客


緩存問題


緩存預熱

  • 出現的現象:
    服務器啓動後迅速宕機
  • 原因:
    Redis中沒有數據,大量請求查的數據庫,然後重建緩存數據,對於數據庫的壓力非常大,而且系統的性能開銷也是非常巨大,不但要查出數據庫中的內容,還要寫到緩存中
  • 解決方案:
    緩存預熱就是系統啓動前,提前將相關的緩存數據直接加載到緩存系統,避免在用戶請求的時候,先查詢數據庫,然後再插入數據緩存的問題,用戶直接查詢事先被預熱的緩存數據

緩存雪崩

  • 出現的現象:
  1. 數據庫連接數激增
  2. 應用服務器無法及時處理請求
  3. 大量408,500錯誤頁面出現
  4. Redis服務器崩潰
  5. Redis集羣崩潰
  • 原因:
    短時間範圍內,大量的key集中過期

  • 解決方案:
    對數據的過期時間進行調整,避免在一定時間內大面積key過期

緩存擊穿

  • 出現的現象
  1. Redis無異常
  2. 數據庫連接量瞬間激增
  3. 數據庫崩潰
  • 原因:
    Redis中某個key過期,而正好該key訪問量巨大,多個數據請求從該服務器直接壓到Redis後,均未命中,Redis在短時間內發起了大量對數據庫中同一數據的訪問

解決方案:
預防爲主,監控訪問量,對自然流量激增的數據延長過期時間或設置爲永久性key

緩存穿透

  • 出現的現象
  1. Redis無異常
  2. 應用服務器流量歲時間增量較大
  3. 數據庫服務器壓力激增
  4. 數據庫崩潰
  • 原因:
    Redis中大面積出現未命中,出現非正常URL訪問

解決方案:
布隆過濾器

布隆過濾器是一種非常高效的數據結構,把所有數據庫的value對應的key 存儲到布隆過濾器裏,幾乎不消耗什麼空間,而且查詢也是相當的快!但是請注意,它只能判斷 key 是否存在(而且會有一定的誤差)。
詳細瞭解布隆過濾器

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章