Redis基礎知識(學習筆記13--BitMap、HyperLogLog 與 Geospatial的操作命令)

东山絮柳仔發表於2024-07-07

一. BitMap操作命令

1.1 BitMap 簡介

BitMap 是Redis 2.2.0 版本中引入的一種新的資料型別。該資料型別本質上就是一個僅包含0和1的二進位制字串。而其所有相關命令都是對這個字串二進位制位的操作。用於描述該字串的屬性有三個:key、offset、bitvalue。

*** key:BitMap是Redis的key-value中的一種Value的資料型別,所以該Value一定有其對應的Key。

*** offset:每個BitMap資料都是一個字串,字串中的每個字元都有其對應的索引,該索引從0開始計數。該索引就稱為每個字元在該BitMap中的偏移量offset。這個offset的值的範圍是【0,2^32 -1】,即該offset的最大值為4G-1,即4294967295,42億多。

*** bitBalue:每個BitMap資料中都是一個僅包含0和1的二進位制字串,每個offset位上的字元就稱為該位的值bitValue。bitValue的值非0即1。

1.2 setbit

setbit key offset value

為給定key的bitmap資料的offset位置設定值為value。其返回值為修改前該offset位置的bitvalue。

說明:對於原bitmap字串中不存在的offset進行賦值,字串會自動伸展以確保它可以將value儲存在指定的offset上。當字串值進行伸展時,空白位置以0填充。當然,設定的value只能是0或1。不過需要注意的是,對使用較大offset的setbit操作來說,記憶體分配過程可能造成Redis伺服器被阻塞。

1.3 getbit

GETBIT key offset

對 key 所儲存的字串值,獲取指定偏移量上的位(bit)。

說明:返回值為字串值指定偏移量上的位(bit)。當 offset 比字串值的長度大,或者 key 不存在時,返回 0 。

1.4 bitcount

BITCOUNT key [start] [end]

計算給定字串中,被設定為 1 的位元位的數量。

說明:一般情況下,給定的整個字串都會被進行計數,透過指定額外的 start 或 end 引數,可以讓計數只在特定的位上進行。start 和 end 引數的設定和 GETRANGE 命令類似,都可以使用負數值: 比如 -1 表示最後一個位元組, -2 表示倒數第二個位元組,以此類推。不存在的 key 被當成是空字串來處理,因此對一個不存在的 key 進行 BITCOUNT 操作,結果為 0 。

1.5.bitpos

bitpos key bit [start] [end]

返回key指定的bitmap中第一個值為指定值bit(非0即1)二進位制的位置。pos,即position,位置。在預設情況下,命令將檢測整個bitmap,但使用者也可以透過可選的start引數和end引數指定要檢測的範圍。

說明:start與end的意義與bitcount命令中的相同。

1.6 bitop

bitop operation destkey key [key...]

對一個或多個bitmap字串key進行二進位制位操作,並將結果儲存到destkey上。operation可以是 and、or、not、xor這四種操作中的任意一種:

*** bitop and destkey key [key...]:對一個或多個bitmap 執行 按位與 操作,並將結果儲存到destkey。

*** bitop or destkey key [key...]:對一個或多個bitmap 執行 按位或 操作,並將結果儲存到destkey。

*** bitop xor destkey key [key...]:對一個或多個bitmap 執行 按位異或 操作,並將結果儲存到destkey。

*** bitop and destkey key [key...]:對一個或多個bitmap 執行 按位非 操作,並將結果儲存到destkey。

說明:

*** 除了not操作之外,其他操作都可以接受一個或多個bitmap作為輸入。

*** 除了not操作之外,其他對一個bitmap的操作其實就是一個複製。

*** 如果參與運算的多個bitmap長度不同,較短的bitmap會以0作為補充位,和輸入 key 中最長的字串長度相等。

1.7 應用場景

由於offset的取值範圍很大,所以其一般應用於大資料量的二值性統計。例如平臺活躍使用者的統計(二值:訪問或未訪問)、支援率統計(二值:支援或不支援)、員工考勤統計(二值:上班或未上班)、影像二值化(二值:黑或白)等。

不過,對於資料量較小的二值性統計並不適合BitMap,可能使用Set更為合適。當然,具體多少資料量適合用於Set,超過多少資料量適合用於BitMap,這需要根據具體場景進行具體分析。

例如,一個平臺要統計日活躍使用者數量。如果使用Set來統計,只需上線一個使用者,就將其使用者ID寫入Set集合即可,最後只需統計出Set集合中的元素個數即可完成統計。即Set集合佔用記憶體的大小與上線使用者數量成正比。假設使用者ID為m位bit位,當前活躍使用者數量為n,則該Set集合的大小最少應該是m*n位元組。而如果使用BitMap來統計,則需要先定義出一個BitMap,其佔用的bit位至少為註冊使用者數量。只需上線一個使用者,就立即使其中一個bit位置為1,最後只需統計出BitMap中1的個數即可完成統計。即BitMap佔用記憶體的大小與註冊使用者數量成正比,與上線使用者數量無關。假設平臺具有註冊使用者數量為N,則BitMap的長度至少為N個bit位,即N/8字元。何時使用BitMap更合適?可以看各自記憶體的大小,那個佔用的記憶體少,推薦使用那個。

二. HyperLogLog 操作命令

2.1 HyperLogLog 簡介

HyperLogLog 是Redis 2.8.9 版本中引入的一種新的資料型別,其意義是HyperLog Log,超級日誌記錄。該資料型別可以簡單理解為一個set集合,集合元素為字串。但實際上HyperLogLog是一種計數機率演算法,透過該演算法可以利用極小的記憶體完成獨立總數的統計。其所有相關命令都是對這個“set集合”的操作。

2.2 pfadd

PFADD key element [element ...]

將任意數量的元素新增到指定的 HyperLogLog 裡面。如果 HyperLogLog 的內部儲存被修改了, 那麼返回 1 , 否則返回 0 。

說明:作為這個命令的副作用, HyperLogLog 內部可能會被更新, 以便反映一個不同的唯一元素估計數量(也即是集合的基數)。如果 HyperLogLog 估計的近似基數(approximated cardinality)在命令執行之後出現了變化, 那麼命令返回 1 , 否則返回 0 。 如果命令執行時給定的鍵不存在, 那麼程式將先建立一個空的 HyperLogLog 結構, 然後再執行命令。呼叫 PFADD 命令時可以只給定鍵名而不給定元素:(1)如果給定鍵已經是一個 HyperLogLog , 那麼這種呼叫不會產生任何效果;(2)但如果給定的鍵不存在, 那麼命令會建立一個空的 HyperLogLog , 並向客戶端返回 1 。

2.3 pfcount

PFCOUNT key [key ...]

當 PFCOUNT 命令作用於單個鍵時, 返回儲存在給定鍵的 HyperLogLog 的近似基數, 如果鍵不存在, 那麼返回 0 。

說明:當 PFCOUNT 命令作用於多個鍵時, 返回所有給定 HyperLogLog 的並集的近似基數, 這個近似基數是透過將所有給定 HyperLogLog 合併至一個臨時 HyperLogLog 來計算得出的。透過 HyperLogLog 資料結構, 使用者可以使用少量固定大小的記憶體, 來儲存集合中的唯一元素 (每個 HyperLogLog 只需使用 12k 位元組記憶體,以及幾個位元組的記憶體來儲存鍵本身)。命令返回的可見集合(observed set)基數並不是精確值, 而是一個帶有 0.81% 標準錯誤(standard error)的近似值。舉個例子, 為了記錄一天會執行多少次各不相同的搜尋查詢, 一個程式可以在每次執行搜尋查詢時呼叫一次 PFADD , 並透過呼叫 PFCOUNT 命令來獲取這個記錄的近似結果。

2.4 pfmerge

PFMERGE destkey sourcekey [sourcekey ...]

將多個 HyperLogLog 合併(merge)為一個 HyperLogLog , 合併後的 HyperLogLog 的基數接近於所有輸入 HyperLogLog 的可見集合(observed set)的並集。字串回覆:返回 OK 。

說明:合併得出的 HyperLogLog 會被儲存在 destkey 鍵裡面, 如果該鍵並不存在, 那麼命令在執行之前, 會先為該鍵建立一個空的 HyperLogLog 。

2.5 應用場景

HyperLogLog 可對資料量超級龐大的日誌資料做不精確的去重計數統計。當然。這個不精確的度在Redis官方給出的誤差是0.81%。這個誤差對於大多數超大資料量場景是被允許的。對於平臺上每個頁面每天的UV資料,非常適合使用HyperLogLog進行記錄。

三. Geospatial操作命令

3.1 Geospatial 簡介

Geospatial,地理空間

Redis在3.2版本中引入了Geospatial這種新的資料型別。該型別本質上仍是一種集合。只不過集合元素比較特殊,是一種由三部分構成的資料結構,這種資料結構稱為空間元素:

*** 經度:longitude。有效經度為【-180,180】.正的表示東經,負的表示西經。

*** 緯度:latitude。有效維度為【-85.05112878,85.05112878】。正的表示北緯,負的表示南緯。

*** 位置名稱:為該經緯度所標註的位置所命名的名稱,也稱為該Geospatial集合的空間元素名稱。

透過該型別可以設定、查詢某地理位置的經緯度,查詢某範圍內的空間元素,計算兩空間元素間的距離等。

3.2 geoadd

GEOADD key longitude latitude member [longitude latitude member ...]

將給定的空間元素(緯度、經度、名字)新增到指定的鍵裡面。 這些資料會以有序集合的形式被儲存在鍵裡面, 從而使得像 GEORADIUS 和 GEORADIUSBYMEMBER 這樣的命令可以在之後透過位置查詢取得這些元素。返回值:新新增到鍵裡面的空間元素數量, 不包括那些已經存在但是被更新的元素。

說明:GEOADD 命令以標準的 x,y 格式接受引數, 所以使用者必須先輸入經度, 然後再輸入緯度。 GEOADD 能夠記錄的座標是有限的: 非常接近兩極的區域是無法被索引的。當使用者嘗試輸入一個超出範圍的經度或者緯度時, GEOADD 命令將返回一個錯誤。

3.3 geopos

GEOPOS key member [member ...]

從鍵裡面返回所有給定位置元素的位置(經度和緯度)。

說明:因為 GEOPOS 命令接受可變數量的位置元素作為輸入, 所以即使使用者只給定了一個位置元素, 命令也會返回陣列回覆。GEOPOS 命令返回一個陣列, 陣列中的每個項都由兩個元素組成: 第一個元素為給定位置元素的經度, 而第二個元素則為給定位置元素的緯度。當給定的位置元素不存在時, 對應的陣列項為空值。

3.4 geodist

GEODIST key member1 member2 [unit]

返回兩個給定位置之間的距離。如果兩個位置之間的其中一個不存在, 那麼命令返回空值。

說明:指定單位的引數 unit 必須是以下單位的其中一個:m 表示單位為米;km 表示單位為千米;mi 表示單位為英里;ft 表示單位為英尺。如果使用者沒有顯式地指定單位引數, 那麼 GEODIST 預設使用米作為單位。GEODIST 命令在計算距離時會假設地球為完美的球形, 在極限情況下, 這一假設最大會造成 0.5% 的誤差。

3.5 geohash

GEOHASH key member [member ...]

返回一個或多個位置元素的 Geohash 表示。

說明:geohash是一種地址編碼方法。它能夠把二維的空間經緯度資料編碼成一個字串。該值主要用於底層應用或者除錯。實際中的作用不大。

3.6 georadius

GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]

以給定的經緯度為中心, 返回指定地理空間中鍵包含的所有位置元素當中, 與中心的距離不超過給定最大距離的所有位置元素(換句話說,不超過給定半徑的元素)。返回時還可攜帶額外的資訊:

***WITHDIST : 在返回位置元素的同時, 將位置元素與中心之間的距離也一併返回。 距離的單位和使用者給定的範圍單位保持一致。
*** WITHCOORD : 將位置元素的經度和維度也一併返回。
*** WITHHASH : 以 52 位有符號整數的形式, 返回位置元素經過原始 geohash 編碼的有序集合分值。 這個選項主要用於底層應用或者除錯, 實際中的作用並不大。

說明:(1)範圍可以使用以下其中一個單位:m 表示單位為米;km 表示單位為千米;mi 表示單位為英里;ft 表示單位為英尺。(2)命令預設返回未排序的位置元素。 透過以下兩個引數, 使用者可以指定被返回位置元素的排序方式:ASC : 根據中心的位置, 按照從近到遠的方式返回位置元素;DESC : 根據中心的位置, 按照從遠到近的方式返回位置元素。(3)在預設情況下, GEORADIUS 命令會返回所有匹配的位置元素。 雖然使用者可以使用 COUNT <count> 選項去獲取前 N 個匹配元素, 但是因為命令在內部可能會需要對所有被匹配的元素進行處理, 所以在對一個非常大的區域進行搜尋時, 即使只使用 COUNT 選項去獲取少量元素, 命令的執行速度也可能會非常慢。 但是從另一方面來說, 使用 COUNT 選項去減少需要返回的元素數量, 對於減少頻寬來說仍然是非常有用的。(4)

GEORADIUS 命令返回一個陣列, 具體來說:在沒有給定任何 WITH 選項的情況下, 命令只會返回一個像 ["New York","Milan","Paris"] 這樣的線性(linear)列表。在指定了 WITHCOORD 、 WITHDIST 、 WITHHASH 等選項的情況下, 命令返回一個二層巢狀陣列, 內層的每個子陣列就表示一個元素。
在返回巢狀陣列時, 子陣列的第一個元素總是位置元素的名字。 至於額外的資訊, 則會作為子陣列的後續元素, 按照以下順序被返回:【【以浮點數格式返回的中心與位置元素之間的距離, 單位與使用者指定範圍時的單位一致;geohash 整數;由兩個元素組成的座標,分別為經度和緯度。】】

3.7 GEORADIUSBYMEMBER

GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]

這個命令和 GEORADIUS 命令一樣, 都可以找出位於指定範圍內的元素, 但是 GEORADIUSBYMEMBER 的中心點是由給定的位置元素決定的, 而不是像 GEORADIUS 那樣, 使用輸入的經度和緯度來決定中心點。

說明,其返回值為一個陣列, 陣列中的每個項表示一個範圍之內的位置元素。

3.8 應用場景

Geospatial 的意義是地理位置,所以其主要應用地理位置相關的計算。例如,微信傳送中的“附近”功能,新增好友中“雷達加朋友”功能;QQ動態中的“附近”功能;釘釘中的“簽到”功能等。

學習參閱宣告

1.【Redis影片從入門到高階】

https://www.bilibili.com/video/BV1U24y1y7jF?p=11&vd_source=0e347fbc6c2b049143afaa5a15abfc1c】

2. 【Redis 命令參考】

https://haiyong.site/doc/redis/redis-gh-pages/hash/hscan.html

相關文章