1. 程式人生 > >跟我一起學Redis之五種基本型別及其應用場景舉例(幹了6個小時)

跟我一起學Redis之五種基本型別及其應用場景舉例(幹了6個小時)

**前言** 來啦,老弟?來啦,上一篇就當嘮嘮嗑,接下來就開始進行實操擼命令,計劃是先整體單純說說Redis的各種用法和應用,最後再結合程式碼歸納總結。 Redis預設有16個數據庫(編號為0~15),預設使用第0個,通過命令select任意切換資料庫,和MySql切換資料庫一個道理;各資料庫之間的資料是隔離的,先啟動服務端,再啟動客戶端,然後開幹,如下演示: > Select命令,用於切換資料庫 ![img](https://i.loli.net/2020/10/09/TuaDy1I29RlhQ7O.png) 清除資料,主要是測試時使用,在生產環境是杜絕使用這個命令的,如下演示: > Flushdb清除當前庫中的資料 > > Flushall清除所有庫中的資料 ![flushdb](https://i.loli.net/2020/10/09/EQR4LMSD81cBrbK.png) Key獲取、移除、判斷是否存在,如下演示 > Keys 獲取Key > > Move 移動指定Key到指定資料庫 > > Exists 判斷Key是否存在 ![key](https://i.loli.net/2020/10/09/WqheXTbwYUjfApl.png) 檢視指定Key對應值型別,如下: > type key ![img](https://i.loli.net/2020/10/09/gUFufBIPoxLhnQE.png) 公共的命令暫時就說這麼多,接下來開始說說五種基本型別的使用及應用場景;之所以用圖片的方式把命令貼出來,主要是在不失真的情況下方便手機閱讀,同時希望小夥伴們可以動手敲敲,不要複製~~~ Redis的命令很多,接下來只是說常用的,其他的小夥伴參照文件進行實操吧,這裡還是注重實際場景的應用(綜合同事、朋友、還有學習過程中提到的場景,並非我都遇到過~~~); ![img](https://i.loli.net/2020/10/09/NOxsuRzTCtyv6D9.png) **正文** Redis中基本的五種資料結構,分別是字串string、雜湊hash、列表list、集合set、有序集合zset,儲存的資料結構大概如下圖; ![img](https://i.loli.net/2020/10/09/6bgyCSTwzFsGdHU.png) string 非常常用的型別,搞過Redis的應該都用過。著重分享以下命令: > set key value : 新增或更新字串鍵值對 > > mset key value [key1 value1 ...]:批量新增或更新鍵值對 > > setnx key value :如果key不存在就新增,否則就失敗 > > setex key seconds value:設定簡直對的時同時設定過期時間 > > get key :獲取指定key的值 > > mget key [key1 key2 ...]:獲取多個key的值 > > del key [key1 key2 ...]:刪除指定key > > expire key seconds:設定指定key過期時間,以秒為單位 > > ttl key:檢視指定key還剩餘多長時間 > > incr key:將指定key儲存的數值加1 > > decr key:將指定key儲存的數值減1 > > incrby key step:將指定key儲存的數值加上step > > decrby key step :將指定key儲存的數值減去step **結合應用場景演練\**↓↓↓\**** **單值快取:**即簡單鍵值對資料快取;有一些資料需要共享,比如在沒有統一授權中心的多個系統中,可以通過相同的演算法共享token字串進行各系統統一認證; ![img](https://i.loli.net/2020/10/09/oRk7auK9eAvwdgQ.png) **物件快取:**比如之前都喜歡用Session儲存使用者資料,然後在每個網頁中進行使用,但對於分散式或是集群系統就需要做Session共享了,一般會將使用者資訊轉為json字串進行快取; ![img](https://i.loli.net/2020/10/09/r7sIqQfEY845uAk.png) 對於簡單的物件快取,也可以用mset和mget實現,但使用相對不如上例方便,如下: ![img](https://i.loli.net/2020/10/09/nhx54sEG91Udo8N.png) 以上只是用於共享資料,但其實經常會用於快取一些高頻率訪問但不頻繁修改的資料上。比如採集裝置資料,需要實時核對裝置是否正確,當採集比較頻繁,如感測器資料時,核對的裝置資訊不可能實時從資料庫中查,需將其進行快取,減輕資料庫壓力的同時,也能提高效率。 可能看到這,有小夥伴會問key值中的冒號啥意思,其實這裡是用來分層歸類的,就比如userData:userId:userName,理解為:使用者資料中指定使用者的使用者名稱。 **計數器:**有沒有遇見一種需要遞增的資料編號,比如說訂單編號:202009290001,後四位不斷的遞增,單體程式還稍微好處理一點,但如果是分散式系統或叢集就有點意思了,所以存在Redis中進行統一遞增是不錯的選擇,針對資料量大的,還可以進行分段計數。 ![image-20201009094243726](https://i.loli.net/2020/10/09/OqhoItyZWBNrVS1.png) **文章閱讀數或網頁瀏覽數統計:**常見部落格文章或是公眾號都有閱讀數統計,或是自己開發的站點需要統計頁面訪問量,用Redis也可以輕鬆實現,換其他方式估計得費點心思。 ![img](https://i.loli.net/2020/10/09/56TMgdY1izNUFDe.png) ![img](https://i.loli.net/2020/10/09/xdkMas3CZqz4cbP.png) **分散式鎖:**單體程式,多執行緒通過執行緒鎖來控制資源搶佔,對於分散式系統用執行緒鎖就不行了,藉助於setnx(set if not exists的縮寫) 來完成,及如果沒有值就能新增成功,否則就失敗,和資源被佔就要等待原理是一樣的,當然還得考慮對應值的過期和刪除,不然一直佔用也不行。 ![img](https://i.loli.net/2020/10/09/LwPrtuIcsSj2b1T.png) **字串的常規操作**:比如擷取字串、獲取字串長度等操作。 ![img](https://i.loli.net/2020/10/09/FnEShmgjzHT3516.png) 通過以上可知,字串的功能還是很強大的,這應該就是很多人喜歡用而且只用它的原因吧。 **hash** hash的相關命令一般以h開頭,著重分享以下命令: > hset key field value : 新增或更新key對應欄位的值; > > hsetnx key field value:新增一個不存在Key的欄位值; > > hmset key field value [field value ...]:在指定Key上儲存多個欄位和值 > > hget key field:獲取指定key中指定欄位的值; > > hdel key field [field1...]:刪除指定Key值的指定欄位 > > hlen key:獲取指定key中的欄位的數量 > > hgetall key:獲取指定key中所有的欄位值 > > hincrby key field step:指定key中欄位值增加step **結合應用場景演練\**↓↓↓\**** **物件快取:**string也能做,為什麼還要用hash?,string一般用於簡單物件的快取,比如欄位不多,記錄也不多的情況,便於序列化解析。 平時專案中有配置資訊或下拉資料資訊,會用於各個頁面,這種變化頻率不高,但需頻繁的讀取的資料,將其進行快取減少資料庫訪問是不錯的選擇: ![img](https://i.loli.net/2020/10/09/zbJSgFewWklAVir.png) **當做資料庫:**有一個同學,做硬體相關係統,通常關於硬體的相關的引數配置都放在記憶體中,但由於引數過多時,維護是非常不爽的事,而且稍微一個引數的改動,就會重新發布程式。有些也採用SQLite來儲存,對於高效訪問和修改,Redis卻是相對比較優的選擇: 如:多個主機,每個主機中有不同的屬性,每個屬性有對應的值。 ![img](https://i.loli.net/2020/10/09/9wIr34QHLkPJRAg.png) **做購物車(之前學習記錄的)**:因為大型的網站,使用者很多,將每個人的購物車資訊都進行關係儲存,做以下頁面是有點難處的。所以用Redis做比較高效,至於一些明細資訊,可以通過商品ID從關係資料庫中查詢。 ![img](https://i.loli.net/2020/10/09/DWRezC1hbGwmgIn.png) 相對於string來說,對於物件儲存,不用來回進行序列化,減少記憶體和CPU的消耗,但設定過期不能到具體欄位,只能針對Key設定。 **list** 著重分享以下命令: > lpush key value [value1 ...] :在指定key的列表左邊插入一個或多個值; > > rpush key value [value1 ...] :在指定key的列表右邊插入一個或多個值; > > lpop key :從指定key的列表左邊取出第一個值; > > rpop key:從指定key的列表右邊取出第一個值; > > lrange key start end:從指定key列表中獲取指定區間內的資料; > > blpop key [key1 ...] timeout:從指定key列表中左邊取出第一個值,若列表中沒有元素就等待timeout時間,如果timeout為0就一直等待。 > > brpop key [key1 ...] timeout:從指定key列表中右邊取出第一個值,若列表中沒有元素就等待timeout時間,如果timeout為0就一直等待。 > > lset key index value:將指定下標的值更新為value, ![img](https://i.loli.net/2020/10/09/nE9X5vsSPymdgRK.png) **結合應用場景演****練↓↓↓** **用於模擬資料結構:** - 棧:先進後出,lpush+lpop 或 rpush+rpop; ![img](https://i.loli.net/2020/10/09/gTstkonWMYQahrI.png) - 佇列:先進先出,lpush+rpop 或 rpush+lpop; ![img](https://i.loli.net/2020/10/09/P1gkjMDvGmNwsZH.png) - 阻塞佇列:先進先出,如果列表沒有元素就等待,lpush+brpop或rpush+blpop; ![img](https://i.loli.net/2020/10/09/dD6jITLbzQ9Z8fB.png) **用於資料傳輸橋樑:**經常會遇見採集一些儀器相關資料的需求,但通常方式都會讓儀器生成資料檔案,供其它程式進行解析,也有用Redis中List作為橋樑傳輸資料的,減少自己生成檔案的過程,通過用List的方式,一邊塞進去,一邊定時取出,然後傳送到遠端。同樣的道理,也可以用於一些訊息的推送,比如關注了一個公眾號,要傳送給訂閱者,首先公眾號發表文章到List,有一個後臺任務程式定時進行取出發給訂閱者,這裡就是拿公眾號舉一個例,並非公眾號是這麼實現。 ![img](https://i.loli.net/2020/10/09/lJoGfTjqIw19mSE.png) **模擬訊息推送** ![img](https://i.loli.net/2020/10/09/9Rl8DVyvHo1L46j.png) 專門有一個後臺任務程式從關注者訊息列表中取出訊息,依次發給每個關注者。 **list常規操作(獲取,更新,插入):** ![img](https://i.loli.net/2020/10/09/GYwLfizBXKk8yMl.png) **set** set命令一般以s開頭,裡面元素無序且不重複,著重分享以下命令: > sadd key member [member ...]:在集合中增加一個或多個元素; > > srem key member [member ...]:從集合中刪除一個或多個元素; > > smembers key:獲取集合中的所欲元素; > > scard key:獲取集合中的元素個數; > > sismember key member:判斷指定member是否在集合中; > > srandmember key [count]:從集合中獲取count個元素,不從集合中刪除; > > spop key [count]:從集合中獲取count個元素,從集合中刪除 > > sinter key [key1 ...]:指定多個集合進行交集運算; > > sinterstore dest key [key1 ...]:指定多個集合進行交集運算,存入dest集合; > > sunion key [key1 ...]:指定多個集合進行並集運算; > > sunionstore dest key [key1 ...]:指定多個集合進行並集運算,存入dest集合; > > sdiff key [key1 ...]:指定多個集合進行差集運算; > > sdiffstore dest key [key1 ...]:指定多個集合進行差集運算,並存入dest集合; **結合應用場景演練\**↓↓↓\**** **抽獎邏輯:**抽獎小夥伴們不陌生了吧,不管是公司年會抽獎,還是公眾號參與抽獎,應該幾乎不用親手抓鬮了吧。都是通過程式,把人員都放在一起,然後隨機抽取,set很符合這種應用場景,如下: ![img](https://i.loli.net/2020/10/09/4x6hREH5SedFjZK.png) 以上是隨便找一個抽獎小程式建立的抽獎,開始命令演練: ![img](https://i.loli.net/2020/10/09/cjqENPGFlCKOmHU.png) **文章點贊**:發表文章之後,可以進行點贊、取消點贊等相關操作; ![img](https://i.loli.net/2020/10/09/sYKLprJtnwIR75F.png) **共同好友統計** ![img](https://i.loli.net/2020/10/09/lrLmKU2HD8gniY6.png) **zset** zset的命令一般以z開頭,裡面元素是有序不可重複的。和Set用法基本一樣,只是每個元素中多了一個分值,用於元素排序。 > zadd key score member [(score member)...]:往有序集合中新增帶分值的元素; > > zrem key member [member...]:從有序集合中刪除成員; > > zscore key member:返回集合中指定成員的分值; > > zcard key:統計集合中元素個數; > > zrange key start stop [withscores]:返回指定範圍的元素,withscores代表返回的元素包含對應的分值。 > > zreverange key start stop [withscores]:返回指定範圍的倒序元素,withscores代表返回的元素包含對應的分值。 > > 同set一樣也可以進行交集、並集、差集的集合運算。 **綜合應用場景\**↓↓↓\**** **用於排名**:比如考試成績的排名,新聞熱度排行榜,直播打賞排名等。 ![img](https://i.loli.net/2020/10/09/tyYrRLC3Ko6SG8P.png) **新聞熱榜:** ![img](https://i.loli.net/2020/10/09/75QtoC8gmwjeYB1.png) ![img](https://i.loli.net/2020/10/09/6NDri7RkwVZh54S.png) **總結** 以上簡單結合例項應用場景將五種基礎型別的常用命令進行分享,還有大量的命令需要小夥伴們結合實際需求進行應用。文中例項大部分是周圍專案中的使用場景,少部分是參考學習資料,總體來說,文中例項應用只作為思路參考,小夥伴可根據業務需求進行應用,對於命令的使用還需要小夥伴們多多練習實踐。下一篇聊聊三種特殊型別。 一個被程式搞醜的帥小夥,關注"Code綜藝圈",識別關注跟我一起學~~~ ![](https://i.loli.net/2020/10/09/Lesgj9HxEF7Jnvl.png) 擼文不易,莫要白瞟,三連