1. 程式人生 > 其它 >04 Redis新資料型別

04 Redis新資料型別

Redis新資料型別

一、Bitmaps

1.1 簡介

現代計算機用二進位制(位) 作為資訊的基礎單位, 1個位元組等於8位, 例如“abc”字串是由3個位元組組成, 但實際在計算機儲存時將其用二進位制表示, “abc”分別對應的ASCII碼分別是97、 98、 99, 對應的二進位制分別是01100001、 01100010和01100011,

合理地使用操作位能夠有效地提高記憶體使用率和開發效率。

​ Redis提供了Bitmaps這個“資料型別”可以實現對位的操作:

(1)Bitmaps本身不是一種資料型別, 實際上它就是字串(key-value) , 但是它可以對字串的位進行操作。

(2)Bitmaps單獨提供了一套命令, 所以在Redis中使用Bitmaps和使用字串的方法不太相同。 可以把Bitmaps想象成一個以位為單位的陣列, 陣列的每個單元只能儲存0和1, 陣列的下標在Bitmaps中叫做偏移量。

1.2 命令

1、setbit

(1)格式

setbit<key><offset><value>設定Bitmaps中某個偏移量的值(0或1)

offset:偏移量從0開始

(2)例項

每個獨立使用者是否訪問過網站存放在Bitmaps中, 將訪問的使用者記做1, 沒有訪問的使用者記做0, 用偏移量作為使用者的id。

設定鍵的第offset個位的值(從0算起) , 假設現在有20個使用者,userid=1, 6, 11, 15, 19的使用者對網站進行了訪問, 那麼當前Bitmaps初始化結果如圖

注:

很多應用的使用者id以一個指定數字(例如10000) 開頭, 直接將使用者id和Bitmaps的偏移量對應勢必會造成一定的浪費, 通常的做法是每次做setbit操作時將使用者id減去這個指定數字。

在第一次初始化Bitmaps時, 假如偏移量非常大, 那麼整個初始化過程執行會比較慢, 可能會造成Redis的阻塞。

2、getbit

(1)格式

getbit<key><offset>獲取Bitmaps中某個偏移量的值

獲取鍵的第offset位的值(從0開始算)

(2)例項

獲取id=8的使用者是否在2020-11-06這天訪問過, 返回0說明沒有訪問過:

3、bitcount

統計字串被設定為1的bit數。一般情況下,給定的整個字串都會被進行計數,通過指定額外的 start 或 end 引數,可以讓計數只在特定的位上進行。start 和 end 引數的設定,都可以使用負數值:比如 -1 表示最後一個位,而 -2 表示倒數第二個位,start、end 是指bit組的位元組的下標數,二者皆包含。

舉例: K1 【01000001 01000000 00000000 00100001】,對應【0,1,2,3】

bitcount K1 1 2 : 統計下標1、2位元組組中bit=1的個數,即01000000 00000000

--》bitcount K1 1 2   --》1

bitcount K1 1 3 : 統計下標1、2位元組組中bit=1的個數,即01000000 00000000 00100001

--》bitcount K1 1 3  --》3

bitcount K0 -2 :統計下標到下標倒數第,位元組組中的個數,即01000001 01000000 00000000

--》bitcount K1 0 -2  --》3

注意:redis的setbit設定或清除的是bit位置,而bitcount計算的是byte位置。

4、bitop

(1)格式

bitop and(or/not/xor) <destkey> [key…]

bitop是一個複合操作, 它可以做多個Bitmaps的and(交集) 、 or(並集) 、 not(非) 、 xor(異或) 操作並將結果儲存在destkey中


Bitmaps與set對比

二、HyperLogLog

2.1 簡介

在工作當中,我們經常會遇到與統計相關的功能需求,比如統計網站PV(PageView頁面訪問量),可以使用Redis的incr、incrby輕鬆實現。

但像UV(UniqueVisitor,獨立訪客)、獨立IP數、搜尋記錄數等需要去重和計數的問題如何解決?這種求集合中不重複元素個數的問題稱為基數問題。

解決基數問題有很多種方案:

(1)資料儲存在MySQL表中,使用distinct count計算不重複個數

(2)使用Redis提供的hash、set、bitmaps等資料結構來處理

以上的方案結果精確,但隨著資料不斷增加,導致佔用空間越來越大,對於非常大的資料集是不切實際的。

能否能夠降低一定的精度來平衡儲存空間?Redis推出了HyperLogLog

Redis HyperLogLog 是用來做基數統計的演算法,HyperLogLog 的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定的、並且是很小的。

在 Redis 裡面,每個 HyperLogLog 鍵只需要花費 12 KB 記憶體,就可以計算接近 2^64 個不同元素的基數。這和計算基數時,元素越多耗費記憶體就越多的集合形成鮮明對比。

但是,因為 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個元素。

什麼是基數?

比如資料集 {1, 3, 5, 7, 5, 7, 8}, 那麼這個資料集的基數集為 {1, 3, 5 ,7, 8}, 基數(不重複元素)為5。 基數估計就是在誤差可接受的範圍內,快速計算基數。

2.2 命令

1、pfadd

(1)格式

pfadd <key>< element> [element ...] 新增指定元素到 HyperLogLog 中

2、pfcount

(1)格式

pfcount<key> [key ...] 計算HLL的近似基數,可以計算多個HLL,比如用HLL儲存每天的UV,計算一週的UV可以使用7天的UV合併計算即可

3、pfmerge

(1)格式

pfmerge<destkey><sourcekey> [sourcekey ...] 將一個或多個HLL合併後的結果儲存在另一個HLL中,比如每月活躍使用者可以使用每天的活躍使用者來合併計算可得

三、Geospatial

簡介

Redis 3.2 中增加了對GEO型別的支援。GEO,Geographic,地理資訊的縮寫。該型別,就是元素的2維座標,在地圖上就是經緯度。redis基於該型別,提供了經緯度設定,查詢,範圍查詢,距離查詢,經緯度Hash等常見操作。

命令

1、geoadd

(1)格式

geoadd<key>< longitude><latitude><member> [longitude latitude member...] 新增地理位置(經度,緯度,名稱)

2、geopos

(1)格式

geopos <key><member> [member...] 獲得指定地區的座標值

3、geodist

(1)格式

geodist<key><member1><member2> [m|km|ft|mi ] 獲取兩個位置之間的直線距離

4、georadius

(1)格式

georadius<key>< longitude><latitude>radius m|km|ft|mi 以給定的經緯度為中心,找出某一半徑內的元素