redis概述:
Redis是一個開源的Key-Value存儲系統,其中Value支持String、list、set、hash、zset五種數據結構,這些數據都支持push/pop、add/remove、取交集并集、排序等豐富的操作,并且這些操作都是原子性的。
與同為NoSQL型緩存數據庫的memcached類似,Redis的數據都存在內存中,數據的運算都在內存中進行,不會發生IO,這也是Redis為什么這么快的一個原因;區別是Redis具備持久化方式,會周期性的把更新的數據寫入磁盤(RDB)或者把修改操作追加寫入記錄文件中(AOF)。
也就是說,Redis的數據存放在內存中,但Redis也支持持久化將數據存入磁盤或文件。
Redis是單線程的,但是多任務并發時可以開啟多個Redis,并且Redis支持主從同步,避免了宕機帶來的影響,以及寫時同步技術實現了數據讀寫分離(主機負責寫入、從機負責讀取)。
ps:Redis的特點是單線程+多路IO復用
Redis緩存的使用,極大的提升了應用程序的性能和效率,特別是數據查詢方面。但同時,它也帶來了一些問題。其中,最要害的問題,就是數據的一致性問題,從嚴格意義上講,這個問題無解。如果對數據的一致性要求很高,那么就不能使用緩存。
另外的一些典型問題就是,緩存穿透、緩存雪崩和緩存擊穿。目前,業界也都有比較流行的解決方案。本篇文章,來給大家講解一下Redis穿透的解決方法—布隆過濾器
緩存穿透
緩存穿透,是指查詢一個數據庫一定不存在的數據。正常的使用緩存流程大致是,數據查詢先進行緩存查詢,如果key不存在或者key已經過期,再對數據庫進行查詢,并把查詢到的對象,放進緩存。如果數據庫查詢對象為空,則不放進緩存。
代碼流程
- 參數傳入對象主鍵ID
- 根據key從緩存中獲取對象
- 如果對象不為空,直接返回
- 如果對象為空,進行數據庫查詢
- 如果從數據庫查詢出的對象不為空,則放入緩存(設定過期時間)
想象一下這個情況,如果傳入的參數為-1,會是怎么樣?這個-1,就是一定不存在的對象。就會每次都去查詢數據庫,而每次查詢都是空,每次又都不會進行緩存。假如有惡意攻擊,就可以利用這個漏洞,對數據庫造成壓力,甚至壓垮數據庫。即便是采用UUID,也是很容易找到一個不存在的KEY,進行攻擊。
布隆過濾器(Bloom Filter)
它實際上是一個很長的二進制向量和一系列隨機映射函數。布隆過濾器可以用于檢索一個元素是否在一個集合中。它的優點是空間效率和查詢時間都比一般的算法要好的多,缺點是有一定的誤識別率和刪除困難。
布隆過濾器解決方法:
將數據庫中所有的查詢條件,放入布隆過濾器中,
當一個查詢請求過來時,先經過布隆過濾器進行查,如果判斷請求查詢值存在,則繼續查;如果判斷請求查詢不存在,直接丟棄。
布隆過濾器原理
原理就是一個對一個key進行k個hash算法獲取k個值,在比特數組中將這k個值散列后設定為1,然后查的時候如果特定的這幾個位置都為1,那么布隆過濾器判斷該key存在。
布隆過濾器可能會誤判,如果它說不存在那肯定不存在,如果它說存在,那數據有可能實際不存在;
Redis的bitmap只支持2^32大小,對應到內存也就是512MB,誤判率萬分之一,可以放下2億左右的數據,性能高,空間占用率及小,省去了大量無效的數據庫連接。
因此我們可以通過布隆過濾器,將Redis緩存穿透控制在一個可容范圍內。