1. 程式人生 > 其它 >Redis系列之-高階用法

Redis系列之-高階用法

一 慢查詢

1.1 生命週期

我們配置一個時間,如果查詢時間超過了我們設定的時間,我們就認為這是一個慢查詢.

慢查詢發生在第三階段

客戶端超時不一定慢查詢,但慢查詢是客戶端超時的一個可能因素

1.2 兩個配置

1.2.1 slowlog-max-len

慢查詢是一個先進先出的佇列

固定長度

儲存在記憶體中

1.2.2 slowlog-max-len

慢查詢閾值(單位:微秒)

slowlog-log-slower-than=0,記錄所有命令

slowlog-log-slower-than <0,不記錄任何命令

1.2.3 配置方法

1 預設配置

config get slowlog-max-len=128

Config get slowly-log-slower-than=10000

2 修改配置檔案重啟

3 動態配置

# 設定記錄所有命令
config set slowlog-log-slower-than 0
# 最多記錄100條
config set slowlog-max-len 100
# 持久化到本地配置檔案
config rewrite

'''
config set slowlog-max-len 1000
config set slowlog-log-slower-than 1000
'''

1.3 三個命令

slowlog get [n]  #獲取慢查詢佇列
'''
日誌由4個屬性組成:
1)日誌的標識id
2)發生的時間戳 3)命令耗時 4)執行的命令和引數 ''' slowlog len #獲取慢查詢佇列長度 slowlog reset #清空慢查詢佇列

1.4 經驗

1 slowlog-max-len 不要設定過大,預設10ms,通常設定1ms
2 slowlog-log-slower-than不要設定過小,通常設定1000左右
3 理解命令生命週期
4 定期持久化慢查詢

二 pipeline與事務

2.1 什麼是pipeline(管道)

Redis的pipeline(管道)功能在命令列中沒有,但redis是支援pipeline的,而且在各個語言版的client中都有相應的實現

將一批命令,批量打包,在redis服務端批量計算(執行),然後把結果批量返回

1次pipeline(n條命令)=1次網路時間+n次命令時間

pipeline期間將“獨佔”連結,此期間將不能進行非“管道”型別的其他操作,直到pipeline關閉;如果你的pipeline的指令集很龐大,為了不干擾連結中的其他操作,你可以為pipeline操作新建Client連結,讓pipeline和其他正常操作分離在2個client中。不過pipeline事實上所能容忍的操作個數,和socket-output緩衝區大小/返回結果的資料尺寸都有很大的關係;同時也意味著每個redis-server同時所能支撐的pipeline連結的個數,也是有限的,這將受限於server的實體記憶體或網路介面的緩衝能力

2.2 客戶端實現

import redis
pool = redis.ConnectionPool(host='10.211.55.4', port=6379)
r = redis.Redis(connection_pool=pool)
# pipe = r.pipeline(transaction=False)
#建立pipeline
pipe = r.pipeline(transaction=True)
#開啟事務
pipe.multi()
pipe.set('name', 'lqz')
#其他程式碼,可能出異常

pipe.set('role', 'nb')
 
pipe.execute()

2.3 與原生操作對比


通過pipeline提交的多次命令,在服務端執行的時候,可能會被拆成多次執行,而mget等操作,是一次性執行的,所以,pipeline執行的命令並非原子性的

2.4 使用建議

1 注意每次pipeline攜帶的資料量

2 pipeline每次只能作用在一個Redis的節點上

3 M(mset,mget….)操作和pipeline的區別

2.5 原生事務操作

# 1 mutil 開啟事務,放到管道中一次性執行
multi # 開啟事務
set name lqz
set age 18
exec

# 2 模擬事務
# 在開啟事務之前,先watch
wathc age
multi
decr age
exec

# 另一臺機器
mutil
decr age
exec # 先執行,上面的執行就會失敗(樂觀鎖,被wathc的事務不會執行成功)

三 釋出訂閱

3.1 角色

釋出者/訂閱者/頻道

釋出者釋出了訊息,所有的訂閱者都可以收到,就是生產者消費者模型(後訂閱了,無法獲取歷史訊息)

3.2 模型

 

 

 

3.3 API

publish channel message #釋出命令
publish souhu:tv "hello world" #在souhu:tv頻道釋出一條hello world  返回訂閱者個數

subscribe [channel] #訂閱命令,可以訂閱一個或多個
subscribe souhu:tv  #訂閱sohu:tv頻道

unsubscribe [channel] #取消訂閱一個或多個頻道
unsubscribe sohu:tv  #取消訂閱sohu:tv頻道
    
psubscribe [pattern...] #訂閱模式匹配
psubscribe c*  #訂閱以c開頭的頻道

unpsubscribe [pattern...] #按模式退訂指定頻道

pubsub channels #列出至少有一個訂閱者的頻道,列出活躍的頻道

pubsub numsub [channel...] #列出給定頻道的訂閱者數量

pubsub numpat #列出被訂閱模式的數量

3.4 釋出訂閱和訊息佇列

釋出訂閱數全收到,訊息佇列有個搶的過程,只有一個搶到

四 Bitmap點陣圖

4.1 點陣圖是什麼

下面是字串big對應的二進位制(b是98)

 

 

4.2 相關命令

set hello big #放入key位hello 值為big的字串
getbit hello 0 #取點陣圖的第0個位置,返回0
getbit hello 1 #取點陣圖的第1個位置,返回1 如上圖

##我們可以直接操縱位
setbit key offset value #給點陣圖指定索引設定值
setbit hello 7 1 #把hello的第7個位置設為1 這樣,big就變成了cig

setbit test 50 1 #test不存在,在key為test的value的第50位設為1,那其他位都以0補

bitcount key [start end] #獲取點陣圖指定範圍(start到end,單位為位元組,注意按位元組一個位元組8個bit為,如果不指定就是獲取全部)位值為1的個數

bitop op destkey key [key...] #做多個Bitmap的and(交集)/or(並集)/not(非)/xor(異或),操作並將結果儲存在destkey中 
bitop and after_lqz lqz lqz2 #把lqz和lqz2按位與操作,放到after_lqz中

bitpos key targetBit start end #計算點陣圖指定範圍(start到end,單位為位元組,如果不指定是獲取全部)第一個偏移量對應的值等於targetBit的位置
bitpos lqz 1 #big 對應點陣圖中第一個1的位置,在第二個位置上,由於從0開始返回1
bitpos lqz 0 #big 對應點陣圖中第一個0的位置,在第一個位置上,由於從0開始返回0
bitpos lqz 1 1 2 #返回9:返回從第一個位元組到第二個位元組之間 第一個1的位置,看上圖,為9

 

 

4.3 獨立使用者統計

1 使用set和Bitmap對比

2 1億使用者,5千萬獨立(1億使用者量,約5千萬人訪問,統計活躍使用者數量)

資料型別 每個userid佔用空間 需要儲存使用者量 全部記憶體量
set 32位(假設userid是整形,佔32位) 5千萬 32位*5千萬=200MB
bitmap 1位 1億 1位*1億=12.5MB

假設有10萬獨立使用者,使用點陣圖還是佔用12.5mb,使用set需要32位*1萬=4MB

4.5 總結

1 點陣圖型別是string型別,最大512M

2 使用setbit時偏移量如果過大,會有較大消耗

3 點陣圖不是絕對好用,需要合理使用

五 HyperLogLog

5.1 介紹

基於HyperLogLog演算法:極小的空間完成獨立數量統計

本質還是字串

5.2 三個命令

pfadd key element #向hyperloglog新增元素,可以同時新增多個
pfcount key #計算hyperloglog的獨立總數
pfmerge destroy sourcekey1 sourcekey2#合併多個hyperloglog,把sourcekey1和sourcekey2合併為destroy

pfadd uuids "uuid1" "uuid2" "uuid3" "uuid4" #向uuids中新增4個uuid
pfcount uuids #返回4
pfadd uuids "uuid1" "uuid5"#有一個之前存在了,其實只把uuid5添加了
pfcount uuids #返回5

pfadd uuids1 "uuid1" "uuid2" "uuid3" "uuid4"
pfadd uuids2 "uuid3" "uuid4" "uuid5" "uuid6"
pfmerge uuidsall uuids1 uuids2 #合併
pfcount uuidsall #統計個數 返回6

5.3 記憶體消耗&總結

百萬級別獨立使用者統計,百萬條資料只佔15k

錯誤率 0.81%

無法取出單條資料,只能統計個數

六 GEO

6.1 介紹

GEO(地理資訊定位):儲存經緯度,計算兩地距離,範圍等

北京:116.28,39.55

天津:117.12,39.08

可以計算天津到北京的距離,天津周圍50km的城市,外賣等

6.2 5個城市緯度

城市 經度 緯度 簡稱
北京 116.28 39.55 beijing
天津 117.12 39.08 tianjin
石家莊 114.29 38.02 shijiazhuang
唐山 118.01 39.38 tangshan
保定 115.29 38.51 baoding

6.3 相關命令

geoadd key longitude latitude member #增加地理位置資訊
geoadd cities:locations 116.28 39.55 beijing #把北京地理資訊天津到cities:locations中
geoadd cities:locations 117.12 39.08 tianjin
geoadd cities:locations 114.29 38.02 shijiazhuang
geoadd cities:locations 118.01 39.38 tangshan
geoadd cities:locations 115.29 38.51 baoding
    
geopos key member #獲取地理位置資訊
geopos cities:locations beijing #獲取北京地理資訊

geodist key member1 member2 [unit]#獲取兩個地理位置的距離 unit:m(米) km(千米) mi(英里) ft(尺)
geodist cities:locations beijing tianjin km #北京到天津的距離,89公里

georadius key logitude latitude radiusm|km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key][storedist key]

georadiusbymember key member radiusm|km|ft|mi [withcoord] [withdist] [withhash] [COUNT count] [asc|desc] [store key][storedist key]
#獲取指定位置範圍內的地理位置資訊集合
'''
withcoord:返回結果中包含經緯度
withdist:返回結果中包含距離中心節點位置
withhash:返回解僱中包含geohash
COUNT count:指定返回結果的數量
asc|desc:返回結果按照距離中心店的距離做升序/降序排列
store key:將返回結果的地理位置資訊儲存到指定鍵
storedist key:將返回結果距離中心點的距離儲存到指定鍵
'''
georadiusbymember cities:locations beijing 150 km
'''
1) "beijing"
2) "tianjin"
3) "tangshan"
4) "baoding"
'''

6.4 總結

3.2以後版本才有

geo本質時zset型別

可以使用zset的刪除,刪除指定member:zrem cities:locations beijing