> **Redis-常用類型操作命令 4(HyperLogLog/地理位置/位圖)**
[TOC]
## 說明 ##
**記錄以下Redis常用類型的操作命令。**
----------
##HyperLogLog##
<h5>簡單介紹</h5>
Redis 在 2.8.9 版本添加了 HyperLogLog 結構。
Redis HyperLogLog 是用來做基數統計的算法,HyperLogLog 的優點是,在輸入元素的數量或者體積非常非常大時,計算基數所需的空間總是固定 的、并且是很小的。
在 Redis 里面,每個 HyperLogLog 鍵只需要花費 12 KB 內存,就可以計算接近 2^64 個不同元素的基 數。這和計算基數時,元素越多耗費內存就越多的集合形成鮮明對比。
但是,因為 HyperLogLog 只會根據輸入元素來計算基數,而不會儲存輸入元素本身,所以 HyperLogLog 不能像集合那樣,返回輸入的各個元素。
<h5>什么是基數?</h5>
比如數據集 {1, 3, 5, 7, 5, 7, 8}, 那么這個數據集的基數集為 {1, 3, 5 ,7, 8}, 基數(不重復元素)為5。 基數估計就是在誤差可接受的范圍內,快速計算基數
<h5>PFADD(增加元素)</h5>
將任意數量的元素添加到指定的 HyperLogLog 里面。
作為這個命令的副作用, HyperLogLog 內部可能會被更新, 以便反映一個不同的唯一元素估計數量(也即是集合的基數)。
如果 HyperLogLog 估計的近似基數(approximated cardinality)在命令執行之后出現了變化, 那么命令返回 1 , 否則返回 0 。 如果命令執行時給定的鍵不存在, 那么程序將先創建一個空的 HyperLogLog 結構, 然后再執行命令。
調用 PFADD key element [element …] 命令時可以只給定鍵名而不給定元素:
如果給定鍵已經是一個 HyperLogLog , 那么這種調用不會產生任何效果;
但如果給定的鍵不存在, 那么命令會創建一個空的 HyperLogLog , 并向客戶端返回 1 。
要了解更多關于 HyperLogLog 數據結構的介紹知識, 請查閱 PFCOUNT key [key …] 命令的文檔。
返回值:整數回復: 如果 HyperLogLog 的內部儲存被修改了, 那么返回 1 , 否則返回 0 。
----------
redis> PFADD databases "Redis" "MongoDB" "MySQL"
(integer) 1
redis> PFCOUNT databases
(integer) 3
redis> PFADD databases "Redis" # Redis 已經存在,不必對估計數量進行更新
(integer) 0
redis> PFCOUNT databases # 元素估計數量沒有變化
(integer) 3
redis> PFADD databases "PostgreSQL" # 添加一個不存在的元素
(integer) 1
redis> PFCOUNT databases # 估計數量增一
4
<h5>PFCOUNT(返回近似基數)</h5>
PFCOUNT key [key …]
時間復雜度: 當命令作用于單個 HyperLogLog 時, 復雜度為 O(1) , 并且具有非常低的平均常數時間。 當命令作用于 N 個 HyperLogLog 時, 復雜度為 O(N) , 常數時間也比處理單個 HyperLogLog 時要大得多。
當 PFCOUNT key [key …] 命令作用于單個鍵時, 返回儲存在給定鍵的 HyperLogLog 的近似基數, 如果鍵不存在, 那么返回 0 。
當 PFCOUNT key [key …] 命令作用于多個鍵時, 返回所有給定 HyperLogLog 的并集的近似基數, 這個近似基數是通過將所有給定 HyperLogLog 合并至一個臨時 HyperLogLog 來計算得出的。
通過 HyperLogLog 數據結構, 用戶可以使用少量固定大小的內存, 來儲存集合中的唯一元素 (每個 HyperLogLog 只需使用 12k 字節內存,以及幾個字節的內存來儲存鍵本身)。
命令返回的可見集合(observed set)基數并不是精確值, 而是一個帶有 0.81% 標準錯誤(standard error)的近似值。
舉個例子, 為了記錄一天會執行多少次各不相同的搜索查詢, 一個程序可以在每次執行搜索查詢時調用一次 PFADD key element [element …] , 并通過調用 PFCOUNT key [key …] 命令來獲取這個記錄的近似結果。
返回值整數回復: 給定 HyperLogLog 包含的唯一元素的近似數量。
----------
redis 127.0.0.1:6379> PFADD hll foo bar zap
(integer) 1
redis 127.0.0.1:6379> PFADD hll zap zap zap
(integer) 0
redis 127.0.0.1:6379> PFADD hll foo bar
(integer) 0
redis 127.0.0.1:6379> PFCOUNT hll
(integer) 3
redis 127.0.0.1:6379> PFADD some-other-hll 1 2 3
(integer) 1
redis 127.0.0.1:6379> PFCOUNT hll some-other-hll
(integer) 6
redis>
<h5>PFMERGE(合并HyperLogLog )</h5>
將多個 HyperLogLog 合并(merge)為一個 HyperLogLog , 合并后的 HyperLogLog 的基數接近于所有輸入 HyperLogLog 的可見集合(observed set)的并集。
合并得出的 HyperLogLog 會被儲存在 destkey 鍵里面, 如果該鍵并不存在, 那么命令在執行之前, 會先為該鍵創建一個空的 HyperLogLog 。
返回值字符串回復:返回 OK 。
----------
redis> PFADD nosql "Redis" "MongoDB" "Memcached"
(integer) 1
redis> PFADD RDBMS "MySQL" "MSSQL" "PostgreSQL"
(integer) 1
redis> PFMERGE databases nosql RDBMS
OK
redis> PFCOUNT databases
(integer) 6
##地理位置##
<h5>GEOADD(添加地理元素)</h5>
將給定的空間元素(緯度、經度、名字)添加到指定的鍵里面。 這些數據會以有序集合的形式被儲存在鍵里面, 從而使得像 GEORADIUS 和 GEORADIUSBYMEMBER 這樣的命令可以在之后通過位置查詢取得這些元素。
GEOADD 命令以標準的 x,y 格式接受參數, 所以用戶必須先輸入經度, 然后再輸入緯度。 GEOADD 能夠記錄的坐標是有限的: 非常接近兩極的區域是無法被索引的。 精確的坐標限制由 EPSG:900913 / EPSG:3785 / OSGEO:41001 等坐標系統定義, 具體如下:
有效的經度介于 -180 度至 180 度之間。
有效的緯度介于 -85.05112878 度至 85.05112878 度之間。
用戶嘗試輸入一個超出范圍的經度或者緯度時, GEOADD 命令將返回一個錯誤。
返回值:新添加到鍵里面的空間元素數量, 不包括那些已經存在但是被更新的元素。
----------
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEODIST Sicily Palermo Catania
"166274.15156960039"
redis> GEORADIUS Sicily 15 37 100 km
1) "Catania"
redis> GEORADIUS Sicily 15 37 200 km
1) "Palermo"
2) "Catania"
<h5>GEOPOS(獲取元素)</h5>
從鍵里面返回所有給定位置元素的位置(經度和緯度)。
因為 GEOPOS 命令接受可變數量的位置元素作為輸入, 所以即使用戶只給定了一個位置元素, 命令也會返回數組回復。
返回值:GEOPOS 命令返回一個數組, 數組中的每個項都由兩個元素組成: 第一個元素為給定位置元素的經度, 而第二個元素則為給定位置元素的緯度。 當給定的位置元素不存在時, 對應的數組項為空值。
----------
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEOPOS Sicily Palermo Catania NonExisting
1) 1) "13.361389338970184"
2) "38.115556395496299"
2) 1) "15.087267458438873"
2) "37.50266842333162"
3) (nil)
<h5>GEODIST(返回兩個元素距離)</h5>
GEODIST key member1 member2 [unit]:返回兩個給定位置之間的距離。
如果兩個位置之間的其中一個不存在, 那么命令返回空值。
指定單位的參數 unit 必須是以下單位的其中一個:
m 表示單位為米。
km 表示單位為千米。
mi 表示單位為英里。
ft 表示單位為英尺。
如果用戶沒有顯式地指定單位參數, 那么 GEODIST 默認使用米作為單位。
GEODIST 命令在計算距離時會假設地球為完美的球形, 在極限情況下, 這一假設最大會造成 0.5% 的誤差。
返回值:計算出的距離會以雙精度浮點數的形式被返回。 如果給定的位置元素不存在, 那么命令返回空值。
----------
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEODIST Sicily Palermo Catania
"166274.15156960039"
redis> GEODIST Sicily Palermo Catania km
"166.27415156960038"
redis> GEODIST Sicily Palermo Catania mi
"103.31822459492736"
redis> GEODIST Sicily Foo Bar
(nil)
<h5>GEORADIUS(返回半徑圓內的元素)</h5>
GEORADIUS key longitude latitude radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]
以給定的經緯度為中心, 返回鍵包含的位置元素當中, 與中心的距離不超過給定最大距離的所有位置元素。
范圍可以使用以下其中一個單位:
m 表示單位為米。
km 表示單位為千米。
mi 表示單位為英里。
ft 表示單位為英尺。
在給定以下可選項時, 命令會返回額外的信息:
WITHDIST : 在返回位置元素的同時, 將位置元素與中心之間的距離也一并返回。 距離的單位和用戶給定的范圍單位保持一致。
WITHCOORD : 將位置元素的經度和維度也一并返回。
WITHHASH : 以 52 位有符號整數的形式, 返回位置元素經過原始 geohash 編碼的有序集合分值。 這個選項主要用于底層應用或者調試, 實際中的作用并不大。
命令默認返回未排序的位置元素。 通過以下兩個參數, 用戶可以指定被返回位置元素的排序方式:
ASC : 根據中心的位置, 按照從近到遠的方式返回位置元素。
DESC : 根據中心的位置, 按照從遠到近的方式返回位置元素。
在默認情況下, GEORADIUS 命令會返回所有匹配的位置元素。 雖然用戶可以使用 COUNT <count> 選項去獲取前 N 個匹配元素, 但是因為命令在內部可能會需要對所有被匹配的元素進行處理, 所以在對一個非常大的區域進行搜索時, 即使只使用 COUNT 選項去獲取少量元素, 命令的執行速度也可能會非常慢。 但是從另一方面來說, 使用 COUNT 選項去減少需要返回的元素數量, 對于減少帶寬來說仍然是非常有用的。
----------
**返回值**
GEORADIUS 命令返回一個數組, 具體來說:
在沒有給定任何 WITH 選項的情況下, 命令只會返回一個像 ["New York","Milan","Paris"] 這樣的線性(linear)列表。
在指定了 WITHCOORD 、 WITHDIST 、 WITHHASH 等選項的情況下, 命令返回一個二層嵌套數組, 內層的每個子數組就表示一個元素。
在返回嵌套數組時, 子數組的第一個元素總是位置元素的名字。 至于額外的信息, 則會作為子數組的后續元素, 按照以下順序被返回:
以浮點數格式返回的中心與位置元素之間的距離, 單位與用戶指定范圍時的單位一致。
geohash 整數。
由兩個元素組成的坐標,分別為經度和緯度。
舉個例子, GEORADIUS Sicily 15 37 200 km withcoord withdist 這樣的命令返回的每個子數組都是類似以下格式的:
["Palermo","190.4424",["13.361389338970184","38.115556395496299"]]
----------
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEORADIUS Sicily 15 37 200 km WITHDIST
1) 1) "Palermo"
2) "190.4424"
2) 1) "Catania"
2) "56.4413"
redis> GEORADIUS Sicily 15 37 200 km WITHCOORD
1) 1) "Palermo"
2) 1) "13.361389338970184"
2) "38.115556395496299"
2) 1) "Catania"
2) 1) "15.087267458438873"
2) "37.50266842333162"
redis> GEORADIUS Sicily 15 37 200 km WITHDIST WITHCOORD
1) 1) "Palermo"
2) "190.4424"
3) 1) "13.361389338970184"
2) "38.115556395496299"
2) 1) "Catania"
2) "56.4413"
3) 1) "15.087267458438873"
2) "37.50266842333162"
<h5>GEORADIUSBYMEMBER(返回半徑圓內的元素)</h5>
GEORADIUSBYMEMBER key member radius m|km|ft|mi [WITHCOORD] [WITHDIST] [WITHHASH] [ASC|DESC] [COUNT count]
這個命令和 GEORADIUS 命令一樣, 都可以找出位于指定范圍內的元素, 但是 GEORADIUSBYMEMBER 的中心點是由給定的位置元素決定的, 而不是像 GEORADIUS 那樣, 使用輸入的經度和緯度來決定中心點。
關于 GEORADIUSBYMEMBER 命令的更多信息, 請參考 GEORADIUS 命令的文檔。
返回值:一個數組, 數組中的每個項表示一個范圍之內的位置元素。
----------
redis> GEOADD Sicily 13.583333 37.316667 "Agrigento"
(integer) 1
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEORADIUSBYMEMBER Sicily Agrigento 100 km
1) "Agrigento"
2) "Palermo"
<h5>GEOHASH(GEOHASH)</h5>
GEOHASH key member [member …]返回一個或多個位置元素的 Geohash 表示。
返回值:一個數組, 數組的每個項都是一個 geohash 。 命令返回的 geohash 的位置與用戶給定的位置元素的位置一一對應。
----------
redis> GEOADD Sicily 13.361389 38.115556 "Palermo" 15.087269 37.502669 "Catania"
(integer) 2
redis> GEOHASH Sicily Palermo Catania
1) "sqc8b49rny0"
2) "sqdtr74hyu0"
##位圖##
1個字節( b ) = 8位( bit ) = 0.001 千字節( kb )
<h5>SETBIT</h5>
SETBIT key offset value 對 key 所儲存的字符串值,設置或清除指定偏移量上的位(bit)。
位的設置或清除取決于 value 參數,可以是 0 也可以是 1 。
當 key 不存在時,自動生成一個新的字符串值。
字符串會進行伸展(grown)以確保它可以將 value 保存在指定的偏移量上。當字符串值進行伸展時,空白位置以 0 填充。
offset 參數必須大于或等于 0 ,小于 2^32 (bit 映射被限制在 512 MB 之內)。
----------
Warning
對使用大的 offset 的 SETBIT 操作來說,內存分配可能造成 Redis 服務器被阻塞。具體參考 SETRANGE key offset value 命令,warning(警告)部分。
返回值:指定偏移量原來儲存的位。
----------
redis> SETBIT bit 10086 1
(integer) 0
redis> GETBIT bit 10086
(integer) 1
redis> GETBIT bit 100 # bit 默認被初始化為 0
(integer) 0
<h5>GETBIT</h5>
GETBIT key offset:對 key 所儲存的字符串值,獲取指定偏移量上的位(bit)。
當 offset 比字符串值的長度大,或者 key 不存在時,返回 0 。
返回值:字符串值指定偏移量上的位(bit)。
----------
> 對不存在的 key 或者不存在的 offset 進行 GETBIT, 返回 0
redis> EXISTS bit
(integer) 0
redis> GETBIT bit 10086
(integer) 0
# 對已存在的 offset 進行 GETBIT
redis> SETBIT bit 10086 1
(integer) 0
redis> GETBIT bit 10086
(integer) 1
<h5>BITCOUNT</h5>
BITCOUNT key [start] [end]:計算給定字符串中,被設置為 1 的比特位的數量。
一般情況下,給定的整個字符串都會被進行計數,通過指定額外的 start 或 end 參數,可以讓計數只在特定的位上進行。
start 和 end 參數的設置和 GETRANGE key start end 命令類似,都可以使用負數值: 比如 -1 表示最后一個字節, -2 表示倒數第二個字節,以此類推。
不存在的 key 被當成是空字符串來處理,因此對一個不存在的 key 進行 BITCOUNT 操作,結果為 0 。
返回值:被設置為 1 的位的數量。
----------
redis> BITCOUNT bits
(integer) 0
redis> SETBIT bits 0 1 # 0001
(integer) 0
redis> BITCOUNT bits
(integer) 1
redis> SETBIT bits 3 1 # 1001
(integer) 0
redis> BITCOUNT bits
(integer) 2
<h5>BITPOS</h5>
BITPOS key bit [start] [end]:返回位圖中第一個值為 bit 的二進制位的位置。
在默認情況下, 命令將檢測整個位圖, 但用戶也可以通過可選的 start 參數和 end 參數指定要檢測的范圍。
返回值:整數回復。
----------
127.0.0.1:6379> SETBIT bits 3 1 # 1000
(integer) 0
127.0.0.1:6379> BITPOS bits 0
(integer) 0
127.0.0.1:6379> BITPOS bits 1
(integer) 3
<h5>BITOP</h5>
BITOP operation destkey key [key …]:對一個或多個保存二進制位的字符串 key 進行位元操作,并將結果保存到 destkey 上。
operation 可以是 AND 、 OR 、 NOT 、 XOR 這四種操作中的任意一種:
BITOP AND destkey key [key ...] ,對一個或多個 key 求邏輯并,并將結果保存到 destkey 。
BITOP OR destkey key [key ...] ,對一個或多個 key 求邏輯或,并將結果保存到 destkey 。
BITOP XOR destkey key [key ...] ,對一個或多個 key 求邏輯異或,并將結果保存到 destkey 。
BITOP NOT destkey key ,對給定 key 求邏輯非,并將結果保存到 destkey 。
除了 NOT 操作之外,其他操作都可以接受一個或多個 key 作為輸入。
處理不同長度的字符串
當 BITOP 處理不同長度的字符串時,較短的那個字符串所缺少的部分會被看作 0 。
空的 key 也被看作是包含 0 的字符串序列。
返回值:保存到 destkey 的字符串的長度,和輸入 key 中最長的字符串長度相等。
Note
BITOP 的復雜度為 O(N) ,當處理大型矩陣(matrix)或者進行大數據量的統計時,最好將任務指派到附屬節點(slave)進行,避免阻塞主節點。
----------
redis> SETBIT bits-1 0 1 # bits-1 = 1001
(integer) 0
redis> SETBIT bits-1 3 1
(integer) 0
redis> SETBIT bits-2 0 1 # bits-2 = 1011
(integer) 0
redis> SETBIT bits-2 1 1
(integer) 0
redis> SETBIT bits-2 3 1
(integer) 0
redis> BITOP AND and-result bits-1 bits-2
(integer) 1
redis> GETBIT and-result 0 # and-result = 1001
(integer) 1
redis> GETBIT and-result 1
(integer) 0
redis> GETBIT and-result 2
(integer) 0
redis> GETBIT and-result 3
(integer) 1
## 結尾 ##
<p style="background-image: -webkit-linear-gradient(left, #3498db, #f47920 10%, #d71345 20%, #f7acbc 30%,#ffd400 40%, #3498db 50%, #f47920 60%, #d71345 70%, #f7acbc 80%, #ffd400 90%, #3498db);color: transparent;-webkit-text-fill-color: transparent;-webkit-background-clip: text;text-align:center;">
腹有詩書氣自華,最是書香能致遠。
</p>