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
以給定的經緯度為中心,找出某一半徑內的元素