redis應用

zhusir發表於2018-08-22

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的產生




相關文章