摘要:分布式緩存應用和緩存分離,緩存多帶帶作為一個系統多帶帶部署,多個應用可以共享的訪問緩存。通過靜態變量一次獲取所有的數據緩存起來避免頻繁的讀取。類似的分布式緩存實現方案還有的集群方案,其實現思想和的實現思想大相徑庭。
0x01 前言
提到緩存,那么緩存是什么,為什么需要緩存?
如果知道一點點計算機方面的知識就會知道,計算機的構造也是由多級緩存->硬盤一起來構造計算機的數據存儲。當然這里不是來撥開計算機的神秘面紗來看透緩存的本質設計的,此篇想來講講我們在軟件構造的過程中為了讓系統能提高數據的讀寫效率,同時減少網絡/IO延遲而進行的緩存設計。
0x02 緩存特征命中率--緩存中取到數據的請求/總的數據請求次數
緩存空間--既然是緩存肯定緩存的數據存儲量不夠實際的存儲系統(文件系統、數據庫等)那么大,如何定義緩存的存儲上限。
淘汰策略--既然緩存有命中率、最大數據存儲空間,那就不可避免的引入了當存儲空間接近最大存儲空間的時候如何將一些緩存數據從緩存中清除出去,采用什么樣的策略。
FIFO 先進來的優先淘汰。應用場景:時效性要求比較高的場景,優先保障最新的數據能被緩存命中。
LFU(least frequently used) 最近最少頻次使用的數據被優先淘汰。應用場景:在保障高頻數據可用的場景可以選用這類策略。
LRU(least recently used) 最近最少使用的數據優先淘汰。應用場景:熱點數據使用場景
0x03 緩存分類 存儲介質分類從硬件角度進行區分:內存、硬盤
從技術實現上進行區分:內存、硬盤文件、數據庫
緩存實現分類緩存從大類上可以分為本地緩存和分布式緩存。
本地緩存:本地緩存和應用在同一個進程里面,數據請求沒有額外的網絡開銷,能快速得到響應,對于單應用沒有集群支持的系統或者擁有集群的情況下但是集群中各個節點的緩存無需互通的場景下比較合適。缺點:應用進程和本地緩存是強綁定在一起的,對于多應用的情況下,每個應用程序都要維護一套多帶帶的緩存,無法共享各自的緩存對內存資源是一種浪費。
分布式緩存:應用和緩存分離,緩存多帶帶作為一個系統多帶帶部署,多個應用可以共享的訪問緩存。
本地緩存相信大家在進行編程的過程中會經常使用到。非常簡單的場景下會直接通過Map結構在局部對象中直接構建緩存存儲結構,局部變量實現緩存。
private ConcurrentHashMaplocalCache = new ConcurrentHashMap ();
這種局部緩存只能在類自身的作用域中能訪問到,而且這種簡單的緩存數據結構無需關注存取、淘汰緩存等策略。
應用場景:在一次請求的過程中緩存此次請求中的重復數據請求,避免過多的無用請求、序列化反序列話對CPU造成的壓力,請求結束后清空緩存。
靜態變量實現緩存,基本實現思路和上面的局部緩存一樣的原理,主要是將其可見度擴大到了本應用程序,在本引用程序都是可見的。通過靜態變量一次獲取所有的數據緩存起來避免頻繁的I/O讀取。
應用場景:一次緩存所有的數據,如應用配置信息、一些數據量不大但是應用需要頻繁使用到的一些數據,通過開關推送的方式來refresh內存。
這里通過redis作為緩存實現來探討下分布式緩存。
根據應用對緩存的數據存儲量的需求,可以通過redis單機或者集群的方式來實現緩存。下面我們主要是來聊聊通過redis集群的方式來實現分布式緩存:
統一接入層暴露統一的操作緩存的API,客戶端通過API像和使用單機緩存一樣透明的使用分布式緩存集群。
類似的分布式緩存實現方案還有memcache的集群方案,其實現思想和redis的實現思想大相徑庭。memcache主要是通過客戶端的的一致性Hash算法來實現集群實例選址操作。
0x04 Redis簡介 持久化方案Redis是一個內存存儲系統,通常情況下都是被使用作為緩存系統,但是它本身是支持對內存中的數據進行持久化的操作的,其支持兩種持久化的方式:
snapshot--save/bgsave兩個命令可以對其進行持久化操作。save是主進程進行的操作會將所有的對外服務操作全部block掉;bgsave采用子線程寫時復制技術進行持久化,主進程繼續對外提供服務,但是寫時復制技術在寫入請求達到一個量級的過程中可能會出現內存瞬間翻倍的情況,所以在一般情況下Redis的內存使用量不能操作物理內存的二分之一,不然會存在潛在的數據丟失的風險。同時在進行持久化得過程中也會有大量的I/O操作會對系統造成負載壓力大。
aof--在文件末尾追加對內存的修改操作。這也會存在個嚴重的問題:當count++循環100次的時候是不是在aof文件末尾追加了100條同樣的+1的操作,其實可以用一個語句count+=100來進行替換。所以像這種情況下aof文件中的語句會出現逐漸龐大的情況,需要定期去rewrite aof文件。在rewrite aof文件的過程中,對內存的修改語句沒法寫入到aof文件,所以Redis會將rewrite期間對內存修改的命令寫入緩存,最后統一寫入aof文件中。
Redis的持久化方案使用了buffer I/O,即會使用物理內存的page cache。計算機在發現page cache不足的時候會對cache和硬盤進行swap的操作,在持久化的同時可能會導致系統的不穩定或者崩潰的現象,所以Redis需要實時針對內存的使用量進行監控告警。大多數的數據庫存儲系統會使用Direct I/O來繞過page cache并自行維護一個數據的cache。
主備同步方式Redis主從同步方式中包含全量/增量數據同步。第3步ACK之前都是同步snapshot文件,通過snapshot文件快速構建一個和Master一直的內存數據,后面增量同步的過程中按照追加到aof文件中的內存修改命令進行同步修改Slave中的內存數據。
Key淘汰策略Redis中會多帶帶針對帶有過期時間的Key進行統一存儲,針對這些帶有過期時間的Key有三種淘汰策略。
被動刪除。對Key進行訪問時,檢查超時時間,如果超時則刪除K-V。
主動刪除。定期調用清理過期Key的方法。
a) 隨機抽取100個Key
b) 刪除過期Key
c) 若刪除過期key數量>25則重復a)
整個主動刪除是有時間限制限制的,否則時間太長會影響緩存對外服務的吞吐量。
內存空間達到Maxmemory時進行清理。阻塞服務對Key進行過期刪除操作,直到低于Maxmemory值,否則服務一直阻塞。
0x05 后記spring提供了注解緩存的實現方案,目前還沒有實踐過,后面對spring進行深入學習其注解緩存實現方案后更新。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/70028.html
閱讀 1123·2021-11-24 09:39
閱讀 3623·2021-09-02 15:21
閱讀 2161·2021-08-24 10:01
閱讀 722·2021-08-19 10:55
閱讀 2447·2019-08-30 15:55
閱讀 1212·2019-08-30 14:16
閱讀 2992·2019-08-29 15:17
閱讀 3235·2019-08-29 13:53