簡介:以上文章講述的是【資料庫性能調優知識與面試知識(詳解四服務器性能剖析)】接下來我總結一下【Redis入門知識點】,覺得我還可以的可以加群一起督促學習探討技術,QQ群:1076570504 個人學習資料庫http://www.aolanghs.com/ 微信公眾號搜索【歡少的成長之路】
- Redis是什么?為什么選擇Redis?
- 與Redis類似的系統有哪些?挑選一個你比較熟悉的簡單講解一下?
- Redis的五大資料型別應用場景都是什么?
- 以上講述了五大型別,Java里完全也可以實作,為什么非要用Redis來替代呢?
- 一直往Redis里加資料,不會溢位嗎?它又是怎么洗掉的呢?
- Redis與資料庫作互動,例如MySQL,它有事務,Redis有事務嗎?跟MySQL事務有什么區別?
- 提到Redis很多文章會提壓縮表與跳躍表,這兩個又是什么東東?
- 講述一下Redis的記憶體淘汰機制?
- 記憶體打滿或者電腦癱瘓如何保證資料的有效性?
- 應用場景中你遇到過哪些問題呢? 這些你又是怎么解決的?
- Redis集群有哪幾種模式?可以簡單介紹一下嗎?
- Redis如何解決并發的?
- Redis用在分布式的話又會遇到哪些問題呢?
TIP: 通過這篇文章你能學習到這些知識!想了解的繼續深入,不想了解的趕緊離開,我不想浪費你們的學習時間,找準自己的定位與目標,堅持下去,并且一定要高效,我跟你們一樣非常抵制垃圾文章,雷同文章,胡說八道的文章,
很多人會問,學底層多浪費時間,搞好實作功能不就好了嗎?
可以這樣想一下到了一定的作業年限技術的廣度深度都有一定的造詣了,你寫代碼就這樣了沒辦法優化了,機器配置也是最好的了,那還能優化啥?? 底層,我們都知道所有語言到最后要運行都是變成機器語言的,最后歸根究底都是要去跟機器互動的,那計算機的底層是不是最后還是要關注的東西了!
Redis
Redis是什么?
Redis相當于是一個記憶體資料庫,說到資料庫,傳統的資料庫都是存在硬碟中,redis的特點是存在記憶體中,所以讀寫速度非常的快,因此redis主要用于快取業務,redis支持事務,持久化以及多種集群方案,
Tip:redis不負責編碼作業,put進行什么型別的值,get出去的時候也就是什么型別的值,之間是有一個二進制安全的
為什么選擇Redis?
我們要根據它的特點來論述,高并發,高性能!
我們先從高性能簡單介紹一下,因為是在記憶體中操作所以它的讀寫能力非常的快,它可以比其他在磁盤上操作資料庫有更高的速度與性能,
高并發主要體現在直接操作記憶體比操作資料庫的磁盤有著更高的效率與性能,所以它在接受請求的時候往往可以承受更高的并發量,從磁盤讀寫資料都是有磁盤IO的,而記憶體的話就不需要這一點!
Memcached是什么?區別在哪?
memcached是一套分布式的快取系統,跟redis類似,和redis的區別如下,這里不過多介紹了,今天的主題是redis,
區別
- redis支持五大資料型別,Memcached支持的資料型別極少一定程度上根本完成不了業務需求
- redis支持事務
- memcached沒有原生的集群模式,需要用戶單獨撰寫,redis是支持原生cluster模式,
- Memcached是多執行緒,非阻塞IO復用的網路模型;Redis使用單執行緒的多路 IO 復用模型,

應用場景
Redis的五大資料型別應用場景都是什么?
hash:因為它的映射關系的特性,特別適合存一些存盤物件,比如用戶詳情,商品詳情,訂單詳情等,
string:是簡單的key-value結構,value不僅可以是string型別也可以是數字,比如生活中常見的關注數,粉絲數等等,
list:是一個鏈表,有序的可重復存盤,它的應用場景非常的多,比如關注串列,分析串列,訊息串列,高性能分頁(下拉資料一直不斷重繪的那種)等,這里需要著重強調一下list有單鏈表以及雙鏈表,這里的redis list實作的是雙向鏈表,所以可以支持反向查詢和遍歷,
set:無序的,不支持重復存盤,主要通過交并差集操作實作一些類似于微博的共同好友,共同粉絲,隨機事件,抽獎,選名等功能,
sorted set:比set增加了一個權重閾值,也就是參照的意思,第一新增了score分值,rank排名,主要用于一些直播系統中的實時排名資訊,包括在線用戶串列,禮物排行串列,彈幕訊息串列等功能,
Java里完全也可以實作,為什么非要用Redis來替代呢?
輕量級!
資料放入的是Redis不在本地CPU,所以不會影響當前的程式,如果放在本地資料量到了一定級別的時候有可能資料量已經消耗完了CPU的記憶體,會超過本地CPU溢位,所以分離了占用的位置,
過期策略
Redis過期是什么
redis可以自己手動設定一些值的過期時間,在我們set一個值的時候都可以規定這個值什么時候過期,這點的好處是極大的提高了資料的可用性,比如我們的短信驗證碼,token登錄資訊等功能
Redis的資料是按照什么洗掉的?
redis資料的洗掉主要分兩種,第一種是定期洗掉,第二種是惰性洗掉,
顧名思義,
定期洗掉就是每隔一段時間定期遍歷資料采用隨機洗掉的思想(如果不采用隨機洗掉的話那么大的資料量是非常影響性能的),這樣的話極大的影響了CPU的性能,
惰性洗掉是指在定期洗掉的基礎上因為采用隨機洗掉的關系所以會導致一部分資料經過定期洗掉后依然沒有被洗掉,所以就有了惰性洗掉,假如你的過期key通過定期洗掉沒有被洗掉,那么惰性洗掉要做的就是,客戶端如果再一次訪問這個過期的key,或者系統去查一下這個key才會被redis洗掉,這就是所謂的惰性洗掉,
如果定期洗掉漏掉了很多過期 key,然后你也沒及時去查, 也就沒走惰性洗掉,此時會怎么樣?如果大量過期key堆積在記憶體里,導致redis記憶體塊耗盡了,怎么解決這個問題 呢?redis 記憶體淘汰機制展開了,
記憶體淘汰機制
Redis的資料淘汰策略(暫時簡單介紹吧后續會出一份Redis底層實作的文章)
- volatile-lru:從已設定過期時間的資料集中挑選最近最少使用的資料淘汰
- volatile-ttl:從已設定過期時間的資料集中挑選將要過期的資料淘汰
- volatile-random:從已設定過期時間的資料集中任意選擇資料淘汰
- allkeys-lru:當記憶體不足以容納新寫入資料時,在鍵空間中,移除最近最少使用的key(這個是最常用的).
- allkeys-random:從資料集中任意選擇資料淘汰
- no-eviction:禁止驅逐資料,也就是說當記憶體不足以容納新寫入資料時,新寫入操作會報錯,(這個應該沒人使用吧!)
事務
概念
Redis 事務的本質是一組命令的集合,事務支持一次執行多個命令,一個事務中所有命令都會被序列化,在事務執行程序,會按照順序串行化執行佇列中的命令,其他客戶端提交的命令請求不會插入到事務執行命令序列中,
總結說:redis事務就是一次性、順序性、排他性的執行一個佇列中的一系列命令
Redis事務沒有隔離級別的概念
批量操作在發送 EXEC 命令前被放入佇列快取,并不會被實際執行,也就不存在事務內的查詢要看到事務里的更新,事務外查詢不能看到
Redis不保證原子性
Redis中,單條命令是原子性執行的,但事務不保證原子性,且沒有回滾,事務中任意命令執行失敗,其余的命令仍會被執行
Redis事務的三個階段
- 開始事務
- 命令入隊
- 執行事務
Redis事務命令操作(本篇文章介紹大概的知識點,比如常用命令自己搜watch,exec命令找案例,不過多介紹了)
- watch key1 key2 … : 監視一或多個key,如果在事務執行之前,被監視的key被其他命令改動,則事務被打斷 ( 類似樂觀鎖 )
- multi : 標記一個事務塊的開始( queued )
- exec : 執行所有事務塊的命令 ( 一旦執行exec后,之前加的監控鎖都會被取消掉 )
- discard : 取消事務,放棄事務塊中的所有命令
- unwatch : 取消watch對所有key的監控
壓縮表與跳躍表
壓縮表與跳躍表之間的關系就是 單個元素過于龐大時,轉換為跳躍表,簡單來說,也就是犧牲空間換速度的一種方案,任何一種便捷的技術都會有弊端的!
持久性
概念
持久化就是把記憶體的資料寫到磁盤中去,防止服務宕機了記憶體資料丟失,Redis 提供了兩種持久化方式:RDB(默認) 和AOF
RDB
RDB也就是快照,快照的作用就是在Redis崩掉的時候起到了恢復的作用,快照是保存當前某一個時間點范圍的資料,每個小時保存一次, 例如9點整開啟一次快照,在9點59的時候系統崩掉了,那么就損失了59分鐘的資料,這種的弊端是性能挺好,就是丟失的資料比較多一些,
AOF
AOF是追加檔案的方式,AOF實時性更好,這種方式默認是不開啟的,AOF是實時的,所以就算丟失資料頂多只會丟失一秒的資料
持久性的方案
首先利用RDB快照進行整點恢復,然后再利用AOF進行剩余部分的實時恢復,RDB的恢復速度非常快,AOF恢復速度雖然慢一點但是恢復的資料量不大因為最多只會恢復一個小時內的資料量,
還是舉以上的例子:9點鐘利用RDB進行了一次快照保存資料,9點59分的時候來了一個原子彈把服務器炸成灰了,持久化的方案就是利用RDB快斬訓復了大部分的資料,但是丟失了59分鐘的資料,因為RDB是一個小時執行一次快照所以RDB解決不了,利用AOF恢復剩下的59分的資料不需要利用AOF恢復整體的資料了,
常見問題
- 快取穿透
- 快取雪崩
- 快取預熱
- 快取降級
快取穿透以及解決方案
快取穿透:一般訪問快取的流程,如果快取中存在查詢的商品資料,那么直接回傳, 如果快取中不存在商品資料,就要訪問資料庫,由于不恰當的業務功能實作,或者外部惡意攻擊不斷地請求某些不存在的資料記憶體,由于快取中沒有保存該資料,導致所有的請求都會落到資料庫上,對資料庫可能帶來一定的壓力,甚至崩潰,

解決方案:
針對快取穿透的情況, 簡單的對策就是將不存在的資料訪問結果, 也存盤到快取中,避免快取訪問的穿透,最終不存在商品資料的訪問結果也快取下來,有效的避免快取穿透的風險
快取雪崩以及解決方案
快取雪崩:
當快取重啟或者大量的快取在某一時間段失效,這樣就導致大批流量直接訪問資料庫,對 DB 造成壓力, 從而引起 DB 故障,系統崩潰,
舉例來說, 我們在準備一項搶購的促銷運營活動,活動期間將帶來大量的商品資訊、庫存等相關資訊的查詢, 為了避免商品資料庫的壓力,將商品資料放入快取中存盤, 不巧的是,搶購活動期間,大量的熱門商品快取同時失效過期了,導致很大的查詢流量落到了資料庫之上,對于資料庫來說造成很大的壓力,
解決方案:
- 將商品根據品類熱度分類, 購買比較多的類目商品快取周期長一些, 購買相對冷門的類目
商品,快取周期短一些; - 在設定商品具體的快取生效時間的時候, 加上一個隨機的區間因子, 比如說 5~10 分鐘
之間來隨意選擇失效時間; - 提前預估 DB 能力, 如果快取掛掉,資料庫仍可以在一定程度上抗住流量的壓力
這三個策略能夠有效的避免短時間內,大批量的快取失效的問題
快取預熱以及解決方案
快取預熱就是系統上線后,將相關的快取資料直接加載到快取系統,這樣就可以避免在用戶請求的時候,先查詢資料庫,然后再將資料快取的問題,用戶直接查詢事先被預熱的快取資料,如果不進行預熱, 那么 Redis 初識狀態資料為空,系統上線初期,對于高并發的流量,都會訪問到資料庫中, 對資料庫造成流量的壓力,如圖所示:

解決方案:
- 資料量不大的時候,工程啟動的時候進行加載快取動作;
- 資料量大的時候,設定一個定時任務腳本,進行快取的重繪;
- 資料量太大的時候,優先保證熱點資料進行提前加載到快取
快取降級以及解決方案
降級的情況,就是快取失效或者快取服務掛掉的情況下,我們也不去訪問資料庫,我們直接訪問記憶體部分資料快取或者直接回傳默認資料,舉例來說:對于應用的首頁,一般是訪問量非常大的地方,首頁里面往往包含了部分推薦商品的展示資訊,這些推薦商品都會放到快取中進行存盤,同時我們為了避免快取的例外情況,對熱點商品資料也存盤到了記憶體中,同時記憶體中還保留了一些默認的商品資訊,
降級一般是有損的操作,所以盡量減少降級對于業務的影響程度,
集群
作為快取資料庫,肯定要考慮快取服務穩定性相關的保障機制
持久化機制就是保證系統崩潰的一個機制
記憶體淘汰機制就是保證系統內資料是否一直有效的一個機制
那么如果單機資料直接掛掉,電腦炸成渣了怎么辦?怎么保證資料的備份呢? 單點故障!延伸了集群!
Redis集群模式一共有三種
- 主從模式
- 哨兵模式
- cluster模式

解釋一下:
單機模式下如果資料被炸毀,也就是出現了單點故障,可以利用主從復制方式,進行多臺redis資料的全量同步,主從復制集群主要有三種分別是強一致性,弱一致性,最終一致性,強一致性可以保證redis1與redis2資料保證同步,但是真實的場景中往往影響性能,redis3與redis4無法保證資料必須一致,不出意外的話這種方式既可以解決主從復制也可以解決性能的問題所以這種方式是默認的,redis5與redis6利用黑盒最終一致性,
主從復制
顧名思義,Redis服務器分為兩類也就是主服務器(Master)與從資料庫(Slave),這是為了避免單點故障的資料丟失引出的一個方案,通常的做法就是一臺服務器的資料復制多個副本以部署在不同的服務器上,即使有一臺服務器崩掉了也不至于癱瘓整個服務,另外幾臺服務器依然可以為系統提供服務,
Redis 提供了復制功能,可以實作當一臺資料庫中的資料更新后,自動將更新的資料同步到其他資料庫上,

優點
- 一個主,可以有多個從,并以非阻塞的方式完成資料同步;
- 從服務器提供讀服務,分散主服務的壓力,實作讀寫分離;
- 從服務器之前可以彼此連接和同步請求,減少主服務同步壓力,
缺點
- 不具備容錯和恢復功能,主服務存在單點風險;
- Redis 的主從復制采用全量復制,需要服務器有足夠的空余記憶體;
- 主從模式較難支持在線擴容
哨兵模式
Redis 提供的 sentinel(哨兵)機制,通過 sentinel (哨兵)模式啟動redis后,自動監控 主Master/從Slave的運行狀態,基本原理是:心跳機制 + 投票裁決,
簡單來說,哨兵的作用就是監控 Redis 系統的運行狀況,它的功能包括以下兩個:
- 監控主資料庫和從資料庫是否正常運行;
- 主資料庫出現故障時自動將從資料庫轉換為主資料庫,
哨兵模式主要有下面幾個內容:
- 監控( Monitoring ):Sentinel 會定期檢查主從服務器是否處于正常作業狀態,
- 提醒( Notification ):當被監控的某個 Redis 服務器出現例外時,Sentinel 可以通過API 向管理員或者其他應用程式發送通知,
- 自動故障遷移(Automatic failover):當一個主服務器不能正常作業時,Sentinel 會開始一次自動故障遷移操作,它會將失效主服務器的其中一個從服務器升級為新的主服務器,并讓失效主服務器的其他從服務器改為復制新的主服務器;當客戶端試圖連接失效的主服務器時,集群也會向客戶端回傳新主服務器的地址, 使得集群可以使用新主服務器代替失效服務器,
Redis Sentinel 是一個分布式系統,你可以在一個架構中運行多個 Sentinel (哨兵)行程( progress )
優點
- 哨兵模式主從可以切換,具備基本的故障轉移能力;
- 哨兵模式具備主從模式的所有優點,
缺點
- 哨兵模式也很難支持在線擴容操作;
- 集群的配置資訊管理比較復雜
cluster模式
Redis Cluster 是一種服務器 Sharding 技術,采用無中心結構,每個節點保存資料和整個集群狀態,每個節點都和其他所有節點連接,
Cluster 集群結構特點:
- Redis Cluster 所有的物理節點都映射到 [ 0-16383 ] slot 上(不一定均勻分布),Cluster
負責維護節點、桶、值之間的關系; - 在 Redis 集群中放置一個 key-value 時,根據 CRC16(key) mod 16384 的值,從之前
劃分的 16384 個桶中選擇一個; - 所有的 Redis 節點彼此互聯(PING-PONG 機制),內部使用二進制協議優化傳輸效率;
- 超過半數的節點檢測到某個節點失效時則判定該節點失效;
- 使用端與 Redis 節點鏈接,不需要中間 proxy 層,直接可以操作,使用端不需要連接集群
所有節點,連接集群中任何一個可用節點即可,
優點
- 無中心架構,節點間資料共享,可動態調整資料分布;
- 節點可動態添加洗掉,擴展性比較靈活;
- 部分節點例外,不影響整體集群的可用性,
缺點
- 集群實作比較復雜;
- 批量操作指令( mget、mset 等)支持有限;
- 事務操作支持有限

如何解決并發?
多實體的方式
分布式的話又會遇到哪些問題呢?
redis分布式并發競爭key的問題
所謂 Redis 的并發競爭 Key 的問題也就是多個系統同時對一個 key 進行操作,但是最后執行的順序和我們期望的順序不同,這樣也就導致了結果的不同!
推薦一種方案:分布式鎖(zookeeper 和 redis 都可以實作分布式鎖),(如果不存在 Redis的并發競爭 Key 問題,不要使用分布式鎖,這樣會影響性能)
基于zookeeper臨時有序節點可以實作的分布式鎖,大致思想為:每個客戶端對某個方法加鎖時,在zookeeper上的與該方法對應的指定節點的目錄下,生成一個唯一的瞬時有序節點,判斷是否獲取鎖的方式很簡單,只需要判斷有序節點中序號最小的一個,當釋放鎖的時候,只需將這個瞬時節點洗掉即可,同時,其可以避免服務宕機導致的鎖無法釋放,而產生的死鎖問題,完成業務流程后,洗掉對應的子節點釋放鎖,在實踐中,當然是從以可靠性為主,所以首推Zookeeper,參考:https://www.jianshu.com/p/8bddd381de06
如何保證快取與資料庫雙寫時的資料一致性?
你只要用快取,就可能會涉及到快取與資料庫雙存盤雙寫,你只要是雙寫,就一定會有資料一致性的問題,那么你如 何解決一致性問題?
一般來說,就是如果你的系統不是嚴格要求快取+資料庫必須一致性的話,快取可以稍微的跟資料庫偶爾有不一致的 情況,最好不要做這個方案,讀請求和寫請求串行化,串到一個記憶體佇列里去,這樣就可以保證一定不會出現不一致 的情況串行化之后,就會導致系統的吞吐量會大幅度的降低,用比正常情況下多幾倍的機器去支撐線上的一個請求,參考https://zhuanlan.zhihu.com/p/63428500

這篇文章的描述是跟馬士兵教育視頻,敖丙,DeepInThought,問天 學習之后自己優化升級的!感謝這幾位大佬!
知道的越多,不知道的就越多,找準方向,堅持自己的定位!加油向前不斷前行,侄訓有柳暗花明的一天!
創作不易,你們的支持就是對我最大認可!
文章將持續更新,我們下期見!【下期將更新SpringCloud入門 QQ群:1076570504 微信公眾號搜索【歡少的成長之路】請多多支持!
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/259200.html
標籤:其他
上一篇:openstack創建云主機
