導航:首頁 > 凈水問答 > redis如何實現商品過濾

redis如何實現商品過濾

發布時間:2023-04-17 16:28:35

❶ redis布隆過濾器數據存到那

redis布隆過濾器數據存到那查詢資料庫一定不存在的數據,那麼此類的圓旦查詢一般惡意的查詢,緩存一不存在該類數據,大量的查詢會導致資料庫負荷

緩存擊穿
針對某個熱點數據訪問量極高,某個時點熱點數據緩存失效,就會導致大量的請求查詢數據

緩存殲指雪崩
某個時間點緩存集體失效

不同的問題有不同的解決方案,針對緩存穿透,普遍的解決方案是採用布隆過濾器

什麼是布隆過濾器
布隆過濾器,由一串很長的二進制向量組成,可以看作二進制數組,裡面存的值 0 或者 1 ,實現的原理,當向資料庫添加數據時,通過多個 hash 函數,計算

出不同的值,在二進制數組中對應的未知將值置為 1 ,以此類推

如何判斷數據是否存在
通過添加的hash 函數再次計算值橘改擾對應的位置,判斷這些位置中的值是否存在 0 (注意:這里判斷不是全為1 )

如果存在至少一個0 ,則數據一定不存在於資料庫

如果全部的值為 1 ,則無法判斷數據是否存在

由於布隆過濾器的存儲特性,當數據被刪除時,無法重置對應位置的值為0(多個數據互相影響)

Redis 實現布隆過濾器 bigmaps
計算機底層存儲的基礎單位是位元組,一個位元組8位,將

❷ 數據需要按條件篩選 怎麼設計redis緩存數據表

應用Redis實現數據的讀寫,同時利用隊列處理器定時將數據寫入mysql。同並物鍵時要注意避免沖突,在redis啟動時去mysql讀取所有表鍵值存入redis中,往redis寫數據時,對redis主鍵自增並螞隱進行讀取,若mysql更新失敗,則需要及時清除緩存及同步redis主鍵。這樣處理,主要是實時讀寫redis,而mysql數據則通過隊列非同步處理,緩解mysql壓力,不過這種方法應用場景主要基於高並發,而且redis的高可用集群架構相對更復雜絕巧,一般不是很推薦。

❸ Redis - 布隆過濾器

當一個元素加入布隆過濾器中的時候,會進行如下操作:

當我們需要判斷一個元素是否存在於布隆過濾器的時候,會進行如下操作:

舉個簡單的例子:

查詢某個變數的時候我們只要看看這些點是不是都是 1 就可以大概率知道集合中有沒有它了

pom.xml引入依賴:

Guava 提供的布隆過濾器的實現還是很不錯的(想要詳細了解的可以看一下它的源碼實現),仔橡但是它有一個重大的缺陷就是只能單機使用(另外,容量擴展也不容易),而現在互聯網一般都是分布式的場景。為了解決這個問題,我們就需要用到 Redis 中的布隆過濾器了。

Redis v4.0 之猛戚鋒後有了 Mole(模塊/插件) 功能,Redis Moles 讓 Redis 可以使用外部模塊擴展其功能 。布隆過濾器就是其中的 Mole。詳情可以查看 Redis 官方對 Redis Moles 的介紹 : https://redis.io/moles。
在已安裝 Redis 的前提下,安裝 RedisBloom,有兩種方式:

簡單介紹一下每個參數的具體含義:
1. key:布隆過濾器的名稱
2. error_rate :誤報的期望概率。這應該是介枝晌於0到1之間的十進制值。例如,對於期望的誤報率0.1%(1000中為1),error_rate應該設置為0.001。該數字越接近零,則每個項目的內存消耗越大,並且每個操作的CPU使用率越高。
3. capacity: 過濾器的容量。當實際存儲的元素個數超過這個值之後,性能將開始下降。實際的降級將取決於超出限制的程度。隨著過濾器元素數量呈指數增長,性能將線性下降。

可選參數:
1. expansion:如果創建了一個新的子過濾器,則其大小將是當前過濾器的大小乘以expansion。默認擴展值為2。這意味著每個後續子過濾器將是前一個子過濾器的兩倍。

————————————————————
坐標帝都,白天上班族,晚上是知識的分享者
如果讀完覺得有收獲的話,歡迎點贊加關注

❹ 搜索引擎 Redisearch 入門實戰

簡介

Redisearch在Redis上面實現了一個搜索引擎,但與其他Redis搜索庫不同,它不使用內部數據結構,如排序集。
這也可以實現更高級的功能,如文本查詢的完全片語匹配和數字過濾,這對傳統的redis搜索幾乎是不可能或高效的。

本機 Mac
伺服器 CentOS 7.3

1、安裝 Redis, 最新版本 ->

2、配置 Redis,編輯 redis.conf,修改渣派三處

3、安裝 Redisearch,在 redis-4.0.1 同級目錄下執行, 官網 ->隱梁州

4、啟動 Redis

1、使用 Maven 安裝最新的 Jedis,方便依灶蔽賴

2、使用 Maven 安裝最新的 JRedisearch,方便依賴

1、在 IDEA 中新建 Maven 工程,添加如下依賴

2、編寫測試程序 Application.java

3、執行結果

速度快,但是對中文搜索支持不好,如上所示,搜索「視頻」時,field4中有「視頻項目」卻沒有出現在結果中,需要將「視頻項目」隔開成「視頻 項目」才行。

❺ Redis的內存優化

一. redisObject對象
二. 縮減鍵值對象
三. 共享對象池
四. 字元串優化
五. 編碼優化
六. 控制key的數量

Redis存儲的所有值對象在內部定義為redisObject結構體,內部結構如下圖所示。

表示當前對象使用的數據類型,Redis主要支持5種數據類型:string,hash,list,set,zset。可以使用type {key}命令查純茄答看對象所屬類型,type命令返回的是值對象類型,鍵都是string類型。

表示Redis內部編碼類型,encoding在Redis內部使用,代表當前對象內部採用哪種數據結構實現。理解Redis內部編碼方式對於優化內存非常重要 ,同一個對象採用不同的編碼實現內存佔用存在明顯差異,具體細節見之後編碼優化部分。

記錄對象最後一次被訪問的時間,當配置了 maxmemory和maxmemory-policy=volatile-lru | allkeys-lru 時, 用於輔助LRU演算法刪除鍵數據。可以使用object idletime {key}命令在不更新lru欄位情況下查看當前鍵的空閑時間。

記錄當前對象被引用的次數,用於通過引用次數回收內存,當refcount=0時,可以安全回收當前對象空間。使用object refcount {key}獲取當前對象引用。當對象為整數且范圍在[0-9999]時,Redis可以使用共享對象的方式來節省內存。具體細節見之後共享對象池部分。

與對象的數據內容相關,如果是整數直接存儲數據,否則表示指向數據的指針。Redis在3.0之後對值對象是字元納爛串且長度<=39位元組的數據,內部編碼為embstr類型,字元串sds和redisObject一起分配,從而只要一次內存操作。

降低Redis內存使用最直接的方式就是縮減鍵(key)和值(value)的長度。

其中java-built-in-serializer表示JAVA內置序列化方式,更多數據見jvm-serializers項目: https://github.com/eishay/jvm-serializers/wiki,其它語言也有各自對應的高效序列化工具。

值對象除了存儲二進制數據之外,通常還會使用通用格式存儲數據比如:json,xml等作為字元串存儲在Redis中。這種方式優點是方便調試和跨語言,但是同樣的數據相比位元組數組所需的空間更大,在內存緊張的情況下,可以使用通用壓縮演算法壓縮json,xml後再存入Redis,從而降低內存佔用,例如使用GZIP壓縮後的json可降低約60%的空間。

對象共享池指Redis內部維護[0-9999]的整數對象池。創建大量的整數類型redisObject存在內存開銷,每個redisObject內部結構至少佔16位元組,甚至超過了整數自身空間消耗。所以Redis內存維護一個[0-9999]的整數對象池,用於節約內存。 除了整數值對象,其他類型如list,hash,set,zset內部元素也可以使用整數對象池。因此開發中在滿足需求的前提下,盡量使用整數對象以節省內存。
整數對象池在Redis中通過變數REDIS_SHARED_INTEGERS定義,不能通過配置修改。可以通過object refcount 命令查看對象引用數驗證是否啟用整數對象池技術,如下:

設置鍵foo等於100時,直接使用共享池內整數對象,因此引用數是2,再設置鍵bar等於100時,引用數又變為3,如下圖所示。

使用整數對象池究竟做慧能降低多少內存?讓我們通過測試來對比對象池的內存優化效果,如下表所示。

使用共享對象池後,相同的數據內存使用降低30%以上。可見當數據大量使用[0-9999]的整數時,共享對象池可以節約大量內存。需要注意的是對象池並不是只要存儲[0-9999]的整數就可以工作。當設置maxmemory並啟用LRU相關淘汰策略如:volatile-lru,allkeys-lru時,Redis禁止使用共享對象池,測試命令如下:

LRU演算法需要獲取對象最後被訪問時間,以便淘汰最長未訪問數據,每個對象最後訪問時間存儲在redisObject對象的lru欄位。對象共享意味著多個引用共享同一個redisObject,這時lru欄位也會被共享,導致無法獲取每個對象的最後訪問時間。如果沒有設置maxmemory,直到內存被用盡Redis也不會觸發內存回收,所以共享對象池可以正常工作。

綜上所述,共享對象池與maxmemory+LRU策略沖突,使用時需要注意。 對於ziplist編碼的值對象,即使內部數據為整數也無法使用共享對象池,因為ziplist使用壓縮且內存連續的結構,對象共享判斷成本過高,ziplist編碼細節後面內容詳細說明。

首先整數對象池復用的幾率最大,其次對象共享的一個關鍵操作就是判斷相等性,Redis之所以只有整數對象池,是因為整數比較演算法時間復雜度為O(1),只保留一萬個整數為了防止對象池浪費。如果是字元串判斷相等性,時間復雜度變為O(n),特別是長字元串更消耗性能(浮點數在Redis內部使用字元串存儲)。對於更復雜的數據結構如hash,list等,相等性判斷需要O(n2)。對於單線程的Redis來說,這樣的開銷顯然不合理,因此Redis只保留整數共享對象池。

字元串對象是Redis內部最常用的數據類型。所有的鍵都是字元串類型, 值對象數據除了整數之外都使用字元串存儲。比如執行命令:lpush cache:type 「redis」 「memcache」 「tair」 「levelDB」 ,Redis首先創建」cache:type」鍵字元串,然後創建鏈表對象,鏈表對象內再包含四個字元串對象,排除Redis內部用到的字元串對象之外至少創建5個字元串對象。可見字元串對象在Redis內部使用非常廣泛,因此深刻理解Redis字元串對於內存優化非常有幫助:

Redis沒有採用原生C語言的字元串類型而是自己實現了字元串結構,內部簡單動態字元串(simple dynamic string),簡稱SDS。結構下圖所示。

Redis自身實現的字元串結構有如下特點:

因為字元串(SDS)存在預分配機制,日常開發中要小心預分配帶來的內存浪費,例如下表的測試用例。

從測試數據可以看出,同樣的數據追加後內存消耗非常嚴重,下面我們結合圖來分析這一現象。階段1每個字元串對象空間佔用如下圖所示。

階段1插入新的字元串後,free欄位保留空間為0,總佔用空間=實際佔用空間+1位元組,最後1位元組保存『\0』標示結尾,這里忽略int類型len和free欄位消耗的8位元組。在階段1原有字元串上追加60位元組數據空間佔用如下圖所示。

追加操作後字元串對象預分配了一倍容量作為預留空間,而且大量追加操作需要內存重新分配,造成內存碎片率(mem_fragmentation_ratio)上升。直接插入與階段2相同數據的空間佔用,如下圖所示。

階段3直接插入同等數據後,相比階段2節省了每個字元串對象預分配的空間,同時降低了碎片率。
字元串之所以採用預分配的方式是防止修改操作需要不斷重分配內存和位元組數據拷貝。但同樣也會造成內存的浪費。字元串預分配每次並不都是翻倍擴容,空間預分配規則如下:

字元串重構:指不一定把每份數據作為字元串整體存儲,像json這樣的數據可以使用hash結構,使用二級結構存儲也能幫我們節省內存。同時可以使用hmget,hmset命令支持欄位的部分讀取修改,而不用每次整體存取。例如下面的json數據:

分別使用字元串和hash結構測試內存表現,如下表所示。

根據測試結構,第一次默認配置下使用hash類型,內存消耗不但沒有降低反而比字元串存儲多出2倍,而調整hash-max-ziplist-value=66之後內存降低為535.60M。因為json的videoAlbumPic屬性長度是65,而hash-max-ziplist-value默認值是64,Redis採用hashtable編碼方式,反而消耗了大量內存。調整配置後hash類型內部編碼方式變為ziplist,相比字元串更省內存且支持屬性的部分操作。下一節將具體介紹ziplist編碼優化細節。

Redis對外提供了string,list,hash,set,zet等類型,但是Redis內部針對不同類型存在編碼的概念,所謂編碼就是具體使用哪種底層數據結構來實現。編碼不同將直接影響數據的內存佔用和讀寫效率。使用object encoding {key}命令獲取編碼類型。如下:

Redis針對每種數據類型(type)可以採用至少兩種編碼方式來實現,下表表示type和encoding的對應關系。

了解編碼和類型對應關系之後,我們不禁疑惑Redis為什麼需要對一種數據結構實現多種編碼方式?
主要原因是Redis作者想通過不同編碼實現效率和空間的平衡。比如當我們的存儲只有10個元素的列表,當使用雙向鏈表數據結構時,必然需要維護大量的內部欄位如每個元素需要:前置指針,後置指針,數據指針等,造成空間浪費,如果採用連續內存結構的壓縮列表(ziplist),將會節省大量內存,而由於數據長度較小,存取操作時間復雜度即使為O(n2)性能也可滿足需求。

Redis內存優化

編碼類型轉換在Redis寫入數據時自動完成,這個轉換過程是不可逆的,轉換規則只能從小內存編碼向大內存編碼轉換。例如:

以上命令體現了list類型編碼的轉換過程,其中Redis之所以不支持編碼回退,主要是數據增刪頻繁時,數據向壓縮編碼轉換非常消耗CPU,得不償失。以上示例用到了list-max-ziplist-entries參數,這個參數用來決定列表長度在多少范圍內使用ziplist編碼。當然還有其它參數控制各種數據類型的編碼,如下表所示:

掌握編碼轉換機制,對我們通過編碼來優化內存使用非常有幫助。下面以hash類型為例,介紹編碼轉換的運行流程,如下圖所示。

理解編碼轉換流程和相關配置之後,可以使用config set命令設置編碼相關參數來滿足使用壓縮編碼的條件。對於已經採用非壓縮編碼類型的數據如hashtable,linkedlist等,設置參數後即使數據滿足壓縮編碼條件,Redis也不會做轉換,需要重啟Redis重新載入數據才能完成轉換。

ziplist編碼主要目的是為了節約內存,因此所有數據都是採用線性連續的內存結構。ziplist編碼是應用范圍最廣的一種,可以分別作為hash、list、zset類型的底層數據結構實現。首先從ziplist編碼結構開始分析,它的內部結構類似這樣:<….>。一個ziplist可以包含多個entry(元素),每個entry保存具體的數據(整數或者位元組數組),內部結構如下圖所示。

ziplist結構欄位含義:

根據以上對ziplist欄位說明,可以分析出該數據結構特點如下:

下面通過測試展示ziplist編碼在不同類型中內存和速度的表現,如下表所示。

測試數據採用100W個36位元組數據,劃分為1000個鍵,每個類型長度統一為1000。從測試結果可以看出:

intset編碼是集合(set)類型編碼的一種,內部表現為存儲有序,不重復的整數集。當集合只包含整數且長度不超過set-max-intset-entries配置時被啟用。執行以下命令查看intset表現:

以上命令可以看出intset對寫入整數進行排序,通過O(log(n))時間復雜度實現查找和去重操作,intset編碼結構如下圖所示。

intset的欄位結構含義:

根據以上測試結果發現intset表現非常好,同樣的數據內存佔用只有不到hashtable編碼的十分之一。intset數據結構插入命令復雜度為O(n),查詢命令為O(log(n)),由於整數佔用空間非常小,所以在集合長度可控的基礎上,寫入命令執行速度也會非常快,因此當使用整數集合時盡量使用intset編碼。上表測試第三行把ziplist-hash類型也放入其中,主要因為intset編碼必須存儲整數,當集合內保存非整數數據時,無法使用intset實現內存優化。這時可以使用ziplist-hash類型對象模擬集合類型,hash的field當作集合中的元素,value設置為1位元組佔位符即可。使用ziplist編碼的hash類型依然比使用hashtable編碼的集合節省大量內存。

當使用Redis存儲大量數據時,通常會存在大量鍵,過多的鍵同樣會消耗大量內存。Redis本質是一個數據結構伺服器,它為我們提供多種數據結構,如hash,list,set,zset 等結構。使用Redis時不要進入一個誤區,大量使用get/set這樣的API,把Redis當成Memcached使用。對於存儲相同的數據內容利用Redis的數據結構降低外層鍵的數量,也可以節省大量內存。如下圖所示,通過在客戶端預估鍵規模,把大量鍵分組映射到多個hash結構中降低鍵的數量。

hash結構降低鍵數量分析:

通過這個測試數據,可以說明:

關於hash鍵和field鍵的設計:

使用hash結構控制鍵的規模雖然可以大幅降低內存,但同樣會帶來問題,需要提前做好規避處理。如下:

本文主要講解Redis內存優化技巧,Redis的數據特性是」ALL IN MEMORY」,優化內存將變得非常重要。對於內存優化建議讀者先要掌握Redis內存存儲的特性比如字元串,壓縮編碼,整數集合等,再根據數據規模和所用命令需求去調整,從而達到空間和效率的最佳平衡。建議使用Redis存儲大量數據時,把內存優化環節加入到前期設計階段,否則數據大幅增長後,開發人員需要面對重新優化內存所帶來開發和數據遷移的雙重成本。當Redis內存不足時,首先考慮的問題不是加機器做水平擴展,應該先嘗試做內存優化。當遇到瓶頸時,再去考慮水平擴展。即使對於集群化方案,垂直層面優化也同樣重要,避免不必要的資源浪費和集群化後的管理成本。

❻ Redis使用bitmap、zset、hash、list等結構完成騷操作

當同時滿足以下條件時,使用ziplist編碼:

SpringBoot—實現n秒內出現x個異常報警

思路:
藉助Redis的zSet集合,score存儲的是異常時的時間戳,獲取一定時間范圍內的set集合。判斷set個數是否滿足條件,若滿足條件則觸發報指清警;

注意點:

相關API:

Redis實現延遲隊列方法介紹
基於Redis實現DelayQueue延遲隊列設計方案

相關API:

SpringBoot2.x—使用Redis的bitmap實現布隆過濾器(Guava中BF演算法)

布隆過濾器: 是專門用來檢測集合中是否存在特定元素的數據結構。
存在誤差率: 即將不在集合的元素誤判在集合中。

所以布隆過濾器適合查詢准確度要求沒這么苛刻,但是對時間、空間效率比較高的場景。

實現方式:Redis實現布隆過濾器——借鑒Guava的BF演算法:

SpringBoot2.x中使用Redis的bitmap結構(工具類)

注意:bitmap使用存在風險,若僅僅計算hash值,會導致bitmap佔用空間過大。一般需要對簡空hash值進行取余處理。

根據Redis是否存在key,判斷鎖是否被獲取;

鎖應該是一個對象,記錄持有鎖的線程信息、當前重入次數。所以應該使用Redis的Hash結構來存儲鎖對象。

3.1 網路波動造成釋放鎖失敗怎麼解決?

需要為鎖加上超時時間;

3.2 任務未執行完畢時,鎖由於超時時間被釋放?

線程一旦加鎖成功,可以啟動一個後台線程,每隔多少秒檢查一次,如果線程還持有鎖,可以不斷延長鎖的生存時間。

主從切換時,從伺服器上沒有加鎖信息,導致多個客戶端同時加鎖。

list結構底層是ziplist/quicklist(可看著一個雙端隊列)。常用命令:

使用list作為對象的緩存池。通過rpush放入對象,通過lpop取出對象。

若是阻塞取,可以使用blpop命令實現。

Redis和Lua腳本(實現令牌桶限流)

數據結構選擇hash。
hash裡面維護:最後放入令牌時間、當前桶內令牌量、桶內最大數量、令牌放置速度(元數據)。

被動式維護:

命令:incr原子累加;

對一段固定時間窗口內的請求進行計數,如果請求數超過了閾值,則舍棄該請求;如果沒有達到設定的閾值,則接受該請求,且計數加1。當窗口時間結束,重置計數器為0。

優點:實現簡單,容易理解;
缺點:流量曲線可能不夠平滑,有「突刺現象」。

1. 一段時間內(不超過時間窗口)系統服務不可用。 比如窗口大小1s,限流為100,恰好某個窗口第1ms來了100個請求,然後2ms-999ms請求都會被拒絕。這段時間用戶會感覺系統服務不可用(即不夠平滑)。

2. 窗口切換時可能會出現兩倍於閾值流量的請求。 比如窗口大小1s,限流大小100,攔逗瞎然後在某個窗口的第999ms有100個請求,窗口前期沒有請求。所以這100個請求都會通過。然後下一個窗口的第1ms又來100個請求,然後全部通過。其實也是1ms內通過的200個請求。

命令:Redis的incr命令

是對固定窗口計數器的優化,解決的是切換窗口兩倍閾值流量的場景。

具體解決方案是:將限流窗口分為多個小的限流窗口,各個限流窗口分別計數。當前時間大於窗口最大時間時,將頭部的小窗口數據舍棄,尾部新增小窗口來處理新請求。

優點:本質上是對固定窗口的優化

❼ redis布隆過濾器拆分長度

布隆過濾器是一種類似set的數據結構。

Redis布隆過濾器的基本使用

在Redis中,布隆過濾器有兩個基本命令,分別是:

bf.add:添加元素到布隆過濾器中,類似於集合的sadd命令,不過bf.add命令只能一次添加一個元素,如果想一次添加多個元素,可以使用bf.madd命令。

bf.exists:判斷某個元素是否在過濾器中,類似於集合的sismember命令,不過bf.exists命令只能一次查詢一個元素,如果想一次查詢多個元素,可以使用bf.mexists命令。

布隆過濾器的高級使用

上面的例子中使用的布隆過濾器只是默認參數的布隆過濾器,它在我們第一次使用 bf.add 命令時自動創建的。Redis還提供了自定義參數的布隆過濾器,想要盡量減少布隆過濾器的誤判,就要設置合理的參數。
在使用 bf.add 命令添加元素之前,使用 bf.reserve 命令創建一個自定義的布隆過濾器。bf.reserve命令有三個參數,分別是:

key:鍵

error_rate:期望錯誤率,期望錯誤率越低,需要的空間就越大。

capacity:初始容量,當實際元素的數量超過這個初始化容量時,誤判率上升。

如果對應的key已經存在時,在執行bf.reserve命令就會報錯。如果不使用bf.reserve命令創建,而是使用Redis自動創建的布隆過濾器,默認的error_rate是0.01,capacity是 100。

布隆過濾器的 error_rate 越小,需要的存儲空間就越大,對於不需要過於精確的場景,error_rate設置稍大一點也可以。布隆過濾器的capacity設置的過大,會浪費存儲空間,設置的過小,就會影響准確率,所以在使用之前一定要盡可能地精確估計好元素數量,還需要加上一定的冗餘空間以避免實際元素可能會意外高出設置值很多。總之,error_rate和 capacity都需要設置一個合適的數值。

❽ 藉助Redis Bitmap實現簡單的布隆過濾器

在之前的 一篇文章 中,我們已經深入理解了布隆過濾器的基本原理,並且了解到它在緩存系統中有較多的應用。Redis提供的Bitmap正好能夠作為布隆過濾器所需要的位數組的基礎,本文先簡要介紹Bitmap,然後給出基於它的布隆過濾器實現。

Bitmap在Redis中並不是一個單獨的數據類型,而是由字元串類型(Redis內部稱Simple Dynamic String,SDS)之上定義的與比特相關的操作實現的,此時SDS就被當做位數組了。下面是在redis-cli中使用getbit和setbit指令的操作示例。

Redis的Bitmap是自動擴容的,亦即get/set到高位時,就會主動填充0。此外,還有bitcount指令用於計算特定位元組范圍內1的個數,bitop指令用來執行位運算(支持and、or、xor和not)。相應的用法可以查詢Redis官方文檔等。

下面我們基於Redis(Codis)實現布隆過濾器RedisBloomFilter。根據之前講解布隆過濾器的文章,要初始化一個布隆過濾器的話,需要兩個參數:預估的元素數量,以及可接受的最大誤差(即假陽性率)。另外,我們也需要傳入Jodis的連接池實例JedisResourcePool,以方便在Redis上操作。RedisBloomFilter類的成員和構造方法如下所示。

為了區分出布隆過濾器對應的Key,在原始Key的前面都加上"bf:"前綴。Bitmap長度bitmapLength和哈希函數個數numHashFunctions則利用Guava版實現中的方法來計算。

然後,我們需要計算一個元素被k個哈希函數散列後,對應到Bitmap的哪些比特上。這里仍然借鑒了Guava的BloomFilterStrategies實現,採用MurmurHash和雙重哈希進行散列。為了應用簡單,假設所有元素固定為字元串類型,不用泛型。

然後我們就可以通過Jedis的setbit()和getbit()方法來實現向布隆過濾器中插入元素與查詢元素是否存在的邏輯了。一個元素會對應多個比特,為了提高效率,流水線就派上用場了。另外,setbit指令不會重置對應Key的過期時間戳。

完畢,寫個簡單的單元測試吧。假設現在用布隆過濾器來存儲已讀帖子的ID,Key中包含用戶ID和時間。每天預估的每用戶最大閱讀量是3000篇,最大誤差3%。

觀察輸出。

❾ Redis pipeline以及批量優化

Redis基於Request/Response 協議。通常情滾租況下一次請求的步驟如下

1 客戶端通過tcp 協議發送指令到服務端,等待redis服務端返回結果

2 redis服務端執行命令,返回響應到客戶端。

客戶端發送請求到接受到服務端返回的響應被稱為一次RTT(Round Trip Time). 在不考慮redis 服務端處理耗時的情況下,數據傳輸的耗時是最要的開銷。且redis client 必須等待上一次響應結果才能發送下一個指令,會長時間處於阻塞的狀態。

為解決提升reids服務端的吞吐量,redis提供了如下幾種解決方案。

redis實現了HMGET/HMSET/MSET/MGET等一系列批量指令。區別與普通指大旦兆令如GET, MGET可以一次性發送key數組,然後redis服務端一次性返回結果數組。

很明顯這種方式可以使用一次RTT處理完多個指令。這種方式的在性能上是最好的,缺點在於

1. 指令類型必須一致,批量指令依賴於Redis的實現,有些指令如setbit 沒有批量實現的,就無法使用這種方案。

2. 不能混合指令發送,需要發送的指令必須在一次請求中確定。靈活性比pipeline差。

pipelining 是Request/遲敬Reponse協議的一種實現方式。客戶端連續發送請求,而不用等待上一次的response返回。最終通過一次讀取之前所有的Response。Redis服務支持這種實現方式。

我們通過redis-benchmark對比下普通cs模型和pipleline的性能。

從上面測試結果可以看出pipleline的性能遠高於普通的請求方式。

1. pipeline的RTT交互次數,從而減少延遲,在網路延遲比較大的環境下。吞吐量提高會特別明顯。

2. redis客戶端/服務端減少了sys_call調用次數,減少了用戶態到內核態的切換開銷。

3. redis客戶端發送無需等待上一次response請求結果,減少了阻塞時間。

Pipelining is not just a way in order to rece the latency cost e to the round trip time, it actually improves by a huge amount the total operations you can perform per second in a given Redis server. This is the result of the fact that, without using pipelining, serving each command is very cheap from the point of view of accessing the data structures and procing the reply, but it is very costly from the point of view of doing the socket I/O. This involves calling the read() and write() syscall, that means going from user land to kernel land. The context switch is a huge speed penalty.

Redis-Bloomfilter在1.0.0版本時,操作redis是基於標準的request/response模式, 但是Bloomfilter 在精度和預計插入數量大的情況,需要做多次hash操作。這樣一次bloomfilter操作需要進行幾十次redis setbit/getbit。這種情況下會嚴重影響Bloomfilter的吞吐量。由於setbit/getbit 不支持批量操作,所以採用pipeline來優化redis的性能開銷。具體可以參考 https://github.com/ttting/redis-bloomfilter 的實現方式。 另外增加對於基於redistemplate的支持。

閱讀全文

與redis如何實現商品過濾相關的資料

熱點內容
水溫在多少度最容易形成水垢 瀏覽:761
清洗浴室水垢 瀏覽:546
方太是什麼時候做凈水的 瀏覽:366
聊城反滲透膜清洗 瀏覽:58
保山礦井污水處理設備多少錢 瀏覽:734
空氣過濾減壓閥怎樣 瀏覽:606
斗山回油濾芯上面裝的小碗是什麼 瀏覽:187
蒸餾裝置中的前餾分是什麼 瀏覽:275
污水用日語怎麼說 瀏覽:507
大眾2016polo換空氣濾芯怎麼換 瀏覽:697
water是什麼牌子的凈水器 瀏覽:560
雷沃鏟車液壓油箱怎麼換濾芯 瀏覽:897
蒸餾裝置中如何正確安裝溫度計 瀏覽:381
車用液壓機油濾芯怎麼清洗 瀏覽:437
納米水性環氧樹脂 瀏覽:296
凈化器定時h是什麼意思 瀏覽:313
一體式濾芯買什麼牌子的好 瀏覽:314
釀造酒與蒸餾酒成分比較 瀏覽:140
電熱水器排污水開關壞 瀏覽:177
污水廠排放量計算 瀏覽:325