再談快取和Redis

2022-01-16 09:01:42 字數 2239 閱讀 9860

自從上次分享《redis到底該如何利用?》已經有1年多了,這1年經歷了不少。從碼了我們**的第一行開始到現在,我們的快取模組也不斷在公升級,這之中確實略有心得,最近也有朋友**快取,覺得可以總結下分享下拙見,期待能有更深入的研究。

快取是什麼?

我時常在群裡或者在社群裡看到有人對快取有諸多疑問,搞不清快取的用途,分不清.net redis各驅動、中介軟體的區別和選擇。快取其實並不是什麼看起來很深奧或者很難駕馭的東西,它一般是用來儲存一些常用的資料到記憶體,以加快資料讀取,減少直接訪問db流量以降低db壓力。比較常用的場景比如:

靜態的維錶類資料,比如位址庫,單位之類。

使用者session

一些實時性高,訪問頻率高的計算資料,比如使用者訪問次數,文章閱讀量,使用者黑名單之類。

傳統的架構裡,快取純粹是db資料的乙份copy,就像上面所說是為了程式能更快的讀取資料的。既然是copy,其實就不必關心丟失,甚至微小的誤差。一定是最先保證db,然後才是考慮快取。另外現在分布式大行其道,集群比比皆是,快取的應有就分成了多級,從單機記憶體到集中式快取最後穿透的db

最近遇到一次很有意思的討論,說到使用者黑名單功能的設計。有朋友db依賴性超強,上來就是使用者表裡加字段呀?讀取太慢?加索引啊之類之類。我覺得這個挺有意思的,以前我也是想當然的這樣想。為什麼?一開始做專案都是設計資料庫開始,建模就是er圖,上來就是db 三正規化。以至於其實現在我都很難改變這樣的思維。導致學習oo,ddd之類建模思想始終繞不過db first的思維。如果繞開db,思考快取去設計這樣的功能,可行性和效能都能提高不少。

.net下的快取應用

針對單機應用,記憶體快取(system.runtime.caching)就足夠,集群環境應該上集中式快取,比較常用的是memcached和redis,這兩者的區別倒是可以好好說到說到。

memcached更加的像記憶體快取,功能單一,只能做普通的快取操作(put/get/remove...)

redis功能更加豐富一些,也支援更多的資料結構,更多的計算命令,因此例如session等快取模組更加的適合memcached,而帶實時計算性質的更加適合redis。不過同時用上兩種服務,也只有大公司能幹了,一般人像我,還是比較喜歡redis,畢竟功能豐富。

關於redis的驅動,我也經常看到sevicestack.redis/stackexchange.redis搞得大家不知道取捨。

兩個我都用,因為servicestack本來是開源免費後來為了支撐發展吧,人家順便就在v4之後開始加入限制,開始收錢了。不過v3依然免費,使用的時候需要注意所有的依賴都要用v3以下哦。v3版本很遺憾,很多功能並不能很好的支援,比如pub/sub.

stackexchange.redis源自鼎鼎大名的stackoverflow,他們有**的收入,自然熱衷開源免費。不過質量還是非常靠譜的,新功能支援的很好。

以上在github上一搜便有。

另外乙個開源專案cachemanager.net最近也是很火,戳這裡。很多人搞不懂它是什麼樣的定位,它實際上是乙個中介軟體,本身並不直接提供與快取(redis\mem)的對接api,當前的版本它是使用了stackexchange.redis來作為驅動的,裡已經有了很詳細的介紹(這裡)。它致力於遮蔽各種快取服務的複雜度,提供簡單一致的api,讓開發者能夠用一套**,只要稍加配置就能使用memroycache/集中式快取(redis/mem)。最強大的是它提供了多層快取的方案(基於redis pub/sub),只要簡單的配置就達到了多層之間的快取同步。(內部的原理是,通過redis pub/sub,每當快取變動就通知sub們自動remove掉響應的快取)。我們公司最近的一次更新也切換到了cachemanager.net,不得不說它真的很好用。

合理設計快取

1. 合理設計key

快取最重要的特點的是其key-value形式,即使redis的多樣資料結構也是。key-value是保證其快速的根本原因,所以合理的key,會讓搜尋更方便。

這也會讓乙份資料根據場景被設計成多分不同的key-value,例如:我之前的文章中提到的模糊匹配功能,就會把name設計進key,而如果是簡單的根據userid取使用者資訊,則會把userid設計進key。從這裡也可以看出快取並不介意儲存很多一樣的資料。

2. 合理的使用快取失效時間

上面提到快取是可以丟失的,的確如果是記憶體快取,它會隨著應用的程序的終止而釋放。除了這樣的釋放,快取還可以被設定過期時間。為什麼要如此設計呢?試想機器記憶體一定不會比硬碟大呀,空間有效,珍貴的資源自然是要儲存盡可能常用的資料(熱資料)。所以合理的設計失效時間會保持資料始終是最活躍的那一部分。當然失效時間也會引起,快取雪崩等一系列問題,這裡有一篇深入的文章值得去看看(戳這裡)

Redis快取穿透和雪崩

快取的目的是什麼?提高效能,快取查詢的速度比去資料庫查詢要快。快取會分擔部分請求,減少併發壓力。那麼快取穿透是什麼?怎麼解決快取穿透呢?一般快取系統,按key去查詢value,如果不存在相應的key,那麼就會去資料庫查詢,如果key對應的value是一定不存在的,並且對key的併發查詢很高,那麼每次...

redis 快取設計和優化

加速讀寫 降低後端負載 資料不一致 維護成本更高 多了一層快取邏輯 運維成本 redis cluster 降低後端負載 對高消耗的運算結果進行快取 加速請求響應 i 0 大量寫合併為批量寫 先累計在db持久化 lru lfu fifo演算法剔除 maxmemory policy 超時剔除 expir...

redis快取穿透和擊穿

專案裡為了提高查詢效能,常使用redis做快取,可高併發下又出現新的問題,如快取穿透 快取擊穿。乙個存在redis的專案,一般乙個查詢請求過來首先會從快取中查詢,快取中沒有則從資料庫裡查詢。快取穿透 當某個key對應的資料在資料來源並不存在,每次針對此key的請求從快取獲取不到,請求都會到資料來源,...