redis核心原理及應用
資料結構
1.string(字串)
key-value形式
常用命令(可以批量操作):set(批量用mset)
key value; get(mget) key;
exists key;
del key;
expire key設定過期時間;
setnx key:如果key不存在就建立,否則執行失敗,是原子操作
2.list(連結串列)
類似於java當中的LinkedList
右邊進,左邊出(佇列)
rpush name values:右邊進
lpop name:左邊出一個元素
llen name:得到name 的長度
右邊進,右邊出(棧)
rpush lists values:右邊進
rpop lists :右邊出一個元素
lindex lists i:返回i位置的元素,需要遍歷整個llist
lrange list 0 -1:獲取所有元素
ltrim lists start end:返回start 和end之間的元素,其他的會被刪掉,慎用
3.hash(字典)
類似於java中的hashMap,底層也是連結串列+陣列(一維陣列,二維連結串列)
4.set (集合)
Redis 的集合相當於 Java 語言裡面的 HashSet,它內部的鍵值對是無序的唯一的。它的內部實現相當於一個特殊的字典,字典中所有的 value 都是一個值NULL。
set有去重的功能
相關命令:sadd sets value; smembers books:檢視所有成員,結果是無序的:
sismember sets value:檢視某個value是否存在; scard sets:獲取長度
spop:彈出一個
5.zset(面試常問)
一方面它是一個 set,保證了內部 value 的唯一性,另一方面它可以給每個 value 賦予一個 score,代表這個 value 的排序權重。
應用場景:
1.延時佇列
2.布隆過濾器
3.geohash演算法(附近的人)
常用命令:以學生成績排序為例
zadd zsets score value:score是學生分數,value是學生ID
zrange zsets 0 -1:按照score排序輸出,區間為排名範圍
zrevrange zsets 0 -1:逆序輸出
zscore zsets value:獲取指定value的score
zcard zsets # 相當於 count()
zrank zsets value: 獲取value對應的排名
zrem zsets value:刪除value
過期時間
Redis 所有的資料結構都可以設定過期時間,時間到了,Redis 會自動刪除相應的物件。需要注意的是過期是以物件為單位,比如一個 hash 結構的過期是整個 hash 物件的過期,而不是其中的某個子 key。
還有一個需要特別注意的地方是如果一個字串已經設定了過期時間,然後你呼叫了 set 方法修改了它,它的過期時間會消失。(會把過期時間改為-1)
應用場景
1.分散式鎖
(1)普通分散式鎖:
1. 用setnx()命令加鎖,del()刪除鎖
問題:在執行期間出現異常,del沒有執行導致鎖沒釋放,會導致死鎖
2.在setnx()之後設定expire,超過過期時間自動釋放鎖
問題:setnx()和expire之間不是原子操作,之間如果出錯也不會設定expire,所以還是會死鎖
(2)解決辦法:
redis2.8版本後,官方將setnx()+expire合併為一個原子命令:setex();(原來那個專案redis版本較老,所以用value的設定時間來判斷是否del)
2. 延時佇列
對於那些只有一組消費者的訊息佇列,使用 Redis 就可以非常輕鬆的搞定,沒有ACK保證,對可靠性較高的系統不推薦使用
資料結構:list
使用rpush/lpush操作入佇列,使用lpop 和 rpop來出佇列。
阻塞讀在佇列沒有資料的時候,會立即進入休眠狀態,一旦資料到來,則立刻醒過來。訊息的延遲幾乎為零。用blpop/brpop替代前面的lpop/rpop,解決了佇列延遲的問題
延時佇列的實現:通過zset資料結構實現
3. HyperLogLog--記錄pv,uv(用來解決很多精度不高的統計需求)
如果統計 PV 那非常好辦,給每個網頁一個獨立的 Redis 計數器就可以了,這個計數器的 key 字尾加上當天的日期。這樣來一個請求,incrby 一次,最終就可以統計出所有的 PV 資料。但是uv不一樣,他需要去重。
HyperLogLog 提供了兩個指令 pfadd 和 pfcount,根據字面意義很好理解,一個是增加計數,一個是獲取計數。pfacount返回的事數量。
但是注意, HyperLogLog是有誤差的,在0.81%左右,不過對於統計PV,UV來說可以忽略不計。
4.布隆過濾器(Bloom Filter)
應用場景:
新聞客戶端推送訊息時去重,即已經推送了的不在推送。
爬蟲系統中對url去重,已經爬過的不會再爬
部分nosql資料庫中有類似布隆過濾器的結構
垃圾郵件過濾系統中也用到
類似於不太精確的set結構(因為可能會誤判),需要redis4.0以上
命令:bf.add 新增元素,bf.exists 查詢元素是否存在
5.漏斗限流
Redis 4.0 提供了一個限流 Redis 模組,它叫 redis-cell。該模組也使用了漏斗演算法,並提供了原子的限流指令。
該模組只有1條指令cl.throttle
6.GeoHash演算法(地理位置距離排序演算法)
應用場景:可以使用 Redis 來實現摩拜單車「附近的 Mobike」、美團和餓了麼「附近的餐館」這樣的功能。
結構:zset
7.scan
在平時的業務開發中要儘量避免大key的產生
應用場景:用來代替keys命令獲取正則匹配的key,當資料較多時,使用keys命令會將所有的key暴力的輸出,時間複雜度是o(n),但是redis是單執行緒模式,勢必會造成其他命令卡頓,所以用scan命令
命令:scan 0 match key99* count 1000
scan 引數提供了三個引數,第一個是 cursor 整數值,第二個是 key 的正則模式,第三個是遍歷的 limit hint。
zsan命令不僅可以對key進行遍歷,也可以對資料集合進行遍歷,如對hash結構進行遍歷:hscan,zscan遍歷zset
大key掃描:key較大時需要擴容會申請另一塊記憶體,會導致卡頓,釋放時也會導致卡頓,所以在平時的業務開發中要儘量避免大key的產生