原文:////
理論
隨著讀多寫少場景的出現,導致需要讀取數據的時間變慢,為了提升性能,出現了數據庫緩存技術,對數據庫的讀取進行分離。web2.0時代,網民的生產力大增,存儲總量也在增加,目前還是讀多寫少模式,原有的緩存技術顯然不能滿足寫的壓力,所以,出現了分庫分表,實現讀寫分離。其中比較常用的一種緩存技術是用Redis做緩存
什么是Redis
Redis是一個基于內存且支持持久化的key-value的NoSQL數據庫,其中每個key和value都是使用對象表示的,具有以下特征:多樣數據類型、持久化、主從同步
Redis持久化機制
Redis是一個支持持久化的內存數據庫,通過持久化機制把內存中的數據同步到硬盤文件來保證數據持久化。當Redis重啟后通過把硬盤文件重新加載到內存,就能達到恢復數據的目的。
實現:單獨創建fork()一個子進程,將當前父進程的數據庫數據復制到子進程的內存中,然后由子進程寫入到臨時文件中,持久化的過程結束了,再用這個臨時文件替換上次的快照文件,然后子進程退出,內存釋放。
兩種持久化機制
兩種同時開啟時,數據恢復redis會優先選擇AOF
緩存雪崩,緩存穿透,緩存預熱等問題緩存雪崩
緩存雪崩可以理解為原有的緩存失效,新緩存未到期間,所有原本應該訪問緩存的請求都去查詢數據庫了,而對數據庫CPU和內存造成巨大壓力,嚴重的會造成數據庫宕機。從而形成一系列連鎖反應,造成整個系統崩潰
解決方法
最多的解決方案就是加鎖或者隊列的方式來保證不會有太多的線程對數據庫一次性進行讀寫,從而避免失效時大量的并發請求落到底層存儲系統上。還有一個簡單方案就時講緩存失效時間分散開
緩存穿透
緩存穿透是指用戶查詢數據,在數據庫沒有,自然在緩存中也不會有。這樣就導致了用戶查詢的時候,在緩存中查不到,每次都要去數據庫再查一遍,然后返回空,這樣請求就繞過了緩存直接查數據庫,這也是經常提的緩存命中率問題
解決方法
補充:布隆過濾器:本質上布隆過濾器是一種數據結構,比較巧妙的概率型數據結構,特點是高效地插入和查詢,可以用來告訴你 “某樣東西一定不存在或者可能存在”,布隆過濾器是一個 bit 向量或者說 bit 數組
:Bit-map就是用一個bit位來標記某個元素對應的Value, 而Key即是該元素。由于采用了Bit為單位來存儲數據,因此在存儲空間方面,可以大大節省
緩存預熱
緩存預熱就是系統上線后,將相關的緩存數據直接加載到緩存系統。這樣就可以避免在用戶請求的時候,先查詢數據庫,然后再將數據緩存的問題!用戶直接查詢事先被預熱的緩存數據
解決思路
緩存更新
除了緩存服務器自帶的緩存失效策略之外(Redis默認的有6中策略可供選擇),我們還可以根據具體的業務需求進行自定義的緩存淘汰,常見的策略有兩種
定時去清理過期的緩存
當有用戶請求過來時,再判斷這個請求所用到的緩存是否過期,過期的話就去底層系統得到新數據并更新緩存
兩者各有優劣,第一種的缺點是維護大量緩存的key是比較麻煩的,第二種的缺點就是每次用戶請求過來都要判斷緩存失效,邏輯相對比較復雜
緩存降級
當訪問量劇增、服務出現問題(如響應時間慢或不響應)或非核心服務影響到核心流程的性能時,仍然需要保證服務還是可用的,即使是有損服務。系統可以根據一些關鍵數據進行自動降級,也可以配置開關實現人工降級。
降級的最終目的是保證核心服務可用,即使是有損的。而且有些服務是無法降級的(如加入購物車、結算)
以參考日志級別設置預案:
一般:比如有些服務偶爾因為網絡抖動或者服務正在上線而超時,可以自動降級;
警告:有些服務在一段時間內成功率有波動(如在95~100%之間),可以自動降級或人工降級,并發送告警
錯誤:比如可用率低于90%,或者數據庫連接池被打爆了,或者訪問量突然猛增到系統能承受的最大閥值,此時可以根據情況自動降級或者人工降級
嚴重錯誤:比如因為特殊原因數據錯誤了,此時需要緊急人工降級
服務降級的目的,是為了防止Redis服務故障,導致數據庫跟著一起發生雪崩問題。因此,對于不重要的緩存數據,可以采取服務降級策略
熱點數據和冷數據
熱點數據,緩存才有價值緩存文件是什么意思,對于冷數據而言,大部分數據可能還沒有再次訪問到就已經被擠出內存了,不僅占用內存,而且價值不大
對于熱點數據,比如一個導航產品,將導航信息緩存以后,可能讀取數百萬次,數據更新前至少讀取兩次,緩存才有意義,這個是最基本的策略,如果緩存還沒起到作用就失效了,那就沒太大的價值了
和Redis的區別有哪些
存儲方式:把數據全部存在內存中,斷電后會掛掉,數據不能超過內存大小,Redis有部分存在硬盤上,redis可以持久化數據
數據支持類型所有的值均是簡單的字符串,redis作為代替者,支持更豐富的數據類型,提供list,set, zset,hash等數據結構的存儲
使用底層模型不同,他們之間底層實現方式以及客戶端之間的通信的應用協議不一樣,Redis直接自己構建了VM機制,因為一般的系統調用系統函數,會浪費一定的時間去移動和請求
value值大小不同,redis最大可以達到512M, 只有1M
redis的速度比快很多
Redis支持數據的備份,即-slave模式的數據備份
單線程的Redis為什么這么快
純內存操作
單線程操作,避免了頻繁的上下文切換
采用了非阻塞IO多路復用機制
redis的數據類型以及使用場景
這個其實沒啥好說的,最常規的set/get操作,value可以是也可以是數字。一般做一些復雜的計數功能的緩存。
hash
這里value存放的是結構化的對象,比較方便的就是操作其中的某個字段。博主在做單點登錄的時候,就是用這種數據結構存儲用戶信息,以作為key,設置30分鐘為緩存過期時間,能很好的模擬出類似的效果。
list
使用List的數據結構,可以做簡單的消息隊列的功能。另外還有一個就是,可以利用命令,做基于redis的分頁功能,性能極佳,用戶體驗好。本人還用一個場景,很合適—取行情信息。就也是個生產者和消費者的場景。LIST可以很好的完成排隊,先進先出的原則。
set
因為set堆放的是一堆不重復值的集合。所以可以做全局去重的功能。為什么不用JVM自帶的Set進行去重?因為我們的系統一般都是集群部署,使用JVM自帶的Set,比較麻煩,難道為了一個做一個全局去重,再起一個公共服務,太麻煩了。
另外,就是利用交集、并集、差集等操作,可以計算共同喜好,全部的喜好,自己獨有的喜好等功能。
set
set多了一個權重參數score,集合中的元素能夠按score進行排列。可以做排行榜應用,取TOP N操作。
Redis內部結構redis的過期策略以及內存淘汰機制
redis采用的是定期刪除+惰性刪除策略
為什么不用定時刪除策略
定時刪除,用一個定時器來負責監視Key,過期則自動刪除。雖然內存及時釋放,但是十分消耗CPU的資源。在大并發請求下緩存文件是什么意思,CPU要將時間應用在處理請求上,而不是刪除key,因此沒有采用這個策略
定期刪除+惰性刪除是如何工作的
定期刪除,redis默認每個100ms檢查,是否有過期的key,有過期key則刪除。需要說明的是,redis不是每個100ms將所有的key檢查一次,而是隨機抽取進行檢查(如果每隔100ms,全部key進行檢查,redis豈不是卡死)。因此,如果只采用定期刪除策略,會導致很多key到時間沒有刪除。
于是,惰性刪除派上用場。也就是說在你獲取某個key的時候,redis會檢查一下,這個key如果設置了過期時間那么是否過期了?如果過期了此時就會刪除。
內存淘汰機制設置
在redis.conf中配置
maxmemory-policy volatile-lru
Redis常見性能問題和解決方案
最好不要做任何持久化工作,如 RDB 內存快照和 AOF 日志文件
如果數據比較重要,某個 Slave 開啟 AOF 備份數據,策略設置為每秒同步一次
為了主從復制的速度和連接的穩定性, 和 Slave 最好在同一個局域網內
盡量避免在壓力很大的主庫上增加從庫
主從復制不要用圖狀結構,用單向鏈表結構更為穩定,即: …
Redis事務
Redis事務功能是通過MULTI、EXEC、和WATCH四個原語實現的
Redis會將一個事務中的所有命令序列化,然后按順序執行。
1.redis 不支持回滾“Redis 在事務失敗時不進行回滾,而是繼續執行余下的命令”, 所以 Redis 的內部可以保持簡單且快速。
2.如果在一個事務中的命令出現錯誤,那么所有的命令都不會執行;
3.如果在一個事務中出現運行錯誤,那么正確的命令會被執行。
MULTI命令用于開啟一個事務,它總是返回OK。MULTI執行之后,客戶端可以繼續向服務器發送任意多條命令,這些命令不會立即被執行,而是被放到一個隊列中,當EXEC命令被調用時,所有隊列中的命令才會被執行。
EXEC:執行所有事務塊內的命令。返回事務塊內所有命令的返回值,按命令執行的先后順序排列。當操作被打斷時,返回空值 nil 。
通過調用,客戶端可以清空事務隊列,并放棄執行事務, 并且客戶端會從事務狀態中退出。
WATCH 命令可以為 Redis 事務提供 check-and-set (CAS)行為。可以監控一個或多個鍵,一旦其中有一個鍵被修改(或刪除),之后的事務就不會執行,監控一直持續到EXEC命令。
Redis的三種集群主從復制
主從復制原理:
主從復制優缺點:
優點:
缺點:
哨兵模式
當主服務器中斷服務后,可以將一個從服務器升級為主服務器,以便繼續提供服務,但是這個過程需要人工手動來操作。為此,Redis 2.8中提供了哨兵工具來實現自動化的系統監控和故障恢復功能。
哨兵的作用就是監控Redis系統的運行狀況。它的功能包括以下兩個。
監控主服務器和從服務器是否正常運行。
主服務器出現故障時自動將從服務器轉換為主服務器。
哨兵的工作方式:
哨兵模式的優缺點
優點:
缺點:Redis較難支持在線擴容,在集群容量達到上限時在線擴容會變得很復雜。
Redis-集群
redis的哨兵模式基本已經可以實現高可用,讀寫分離 ,但是在這種模式下每臺redis服務器都存儲相同的數據,很浪費內存,所以在.0上加入了模式,實現的redis的分布式存儲,也就是說每臺redis節點上存儲不同的內容。
Redis-采用無中心結構,它的特點如下:
工作方式:在redis的每一個節點上,都有這么兩個東西,一個是插槽(slot),它的的取值范圍是:0-16383。還有一個就是,可以理解為是一個集群管理的插件。當我們的存取的key到達的時候,redis會根據crc16的算法得出一個結果,然后把結果對 16384 求余數,這樣每個 key 都會對應一個編號在 0-16383 之間的哈希槽,通過這個值,去找到對應的插槽所對應的節點,然后直接自動跳轉到這個對應的節點上進行存取操作。
為了保證高可用,redis-集群引入了主從模式,一個主節點對應一個或者多個從節點,當主節點宕機的時候,就會啟用從節點。當其它主節點ping一個主節點A時,如果半數以上的主節點與A通信超時,那么認為主節點A宕機了。如果主節點A和它的從節點A1都宕機了,那么該集群就無法再提供服務了。
·END·
如果您喜歡本文,歡迎點擊右上角,把文章分享到朋友圈~~
架構師
我們都是架構師!
關注架構師(),添加“星標”
獲取每天技術干貨,一起成為牛逼架構師
技術群請加若飛:進架構師群
投稿、合作、版權等郵箱: