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)日誌的標識id2)發生的時間戳 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