1. 程式人生 > >Redis 基礎命令--進階篇

Redis 基礎命令--進階篇

今天又掃了一章《Redis入門指南》第4章 進階,被 sort 指令卡了好久,所以我會重點講解 sort 指令。

第一個知識點--事務

這個在關係型資料庫裡經常聽見--一組命令的集合,其中的命令要不全部執行,要不全部不執行,在 redis 裡面也有這樣的操作命令。

基本語法:

multi

redis commands

exec

在 multi 與 exec 之間的命令直到使用者輸入 exec 之前是不會執行的,所以沒有辦法判斷你的輸入邏輯上是否有錯誤,只能判斷語法上是否有錯。如下面這個例子:

multi
set string value
hset string field value
exec
第一個 set 將 string 儲存成字串型別,接下來又將 string 儲存成雜湊型別,但是由於 set string field value 這條命令本身的語法沒有出錯,所以不會出現錯誤提醒。

再來補充一個命令 

watch key
這個命令可以監視一個 key,也就是在執行 watch key 之後,如果 key 改變的話,接下來針對該 key 的全部事務全部不會執行,例:
set key 1
watch key 
set key 2
multi 
set key 3
exec
最後的結果為 2,因為在 watch key 之後又執行了 set key 2,改變了 key 的值,所以接下來的事務沒有執行,即 set key 3 這條命令沒有執行。有點像關係型資料庫中的鎖,但是鎖能保證在被鎖期間不會被除自己之外的程序修改,這裡的 watch 卻只能監視該資料是否做出修改,無法阻止。

可以使用 unwatch 解除監視。

第二個知識點--過期時間

可以設定一個 key 的存活時間(TTL time to live),現在這裡介紹幾個英文單詞,因為我英文不怎麼好,省的下次又要去查字典

expire  檔案、協議(因到期而)失效

persist 繼續存在

msec   毫秒

基本語法:

expire key seconds

pexpire key msec

ttl key // 檢視還有多久時間才過期

persist key // 將該 key 轉變成永久儲存模式

注意點

1、如果在這是了一個 key 的過期時間之後再對該 key 執行 set 和 get 操作的話,那麼跟執行 persist key 的作用是一樣的,該 key 都會變成永久儲存模式

2、如果在為一個 key 設定過 expire key seconds 之後再執行一遍 expire key seconds 則會重新開始計時

3、ttl key 的返回值是有含義的,正常情況就不說了,當返回 -1 時表示該 key 沒有設定過過期時間,-2 表示該 key 不存在,0 的話,你能掐的那麼準嗎?偷笑

第三個知識點--排序

先補充一下萬用字元的介紹,下面要用到:

?	匹配任意一個字元
*	匹配任意數量字元
[]  匹配在 [] 中的任意一個字元
\	轉義

在關係型資料庫中我們常用 order by 來進行排序,在 redis 中使用 sort by,為了理解,我先列了這麼一條公式:

sort 集合、有序集合、列表 by 雜湊*->field get 雜湊*->field [limit offset count] [desc] [alpha]

這是我個人感覺排序的用法,因為我在 windows 系統上安裝的 redis 不是 redis 官方支援的 redis,是 windows 自己移植過來的,書上的程式碼我執行是會報錯的,不知道是我自己理解錯誤還是怎麼會是,我嘗試了很久,總結出了上面的那條公式,為便於理解,我舉下面這個例子:

使用集合儲存一個班學生的 id 號,這裡我們簡化一下只有3名同學,id 分別為1、2、3

sadd id 1 2 3
之後我們採用散列表的形式來儲存學生的個人資訊,包括數學課成績、體育課成績。
hset student:1 name yang math 80 pe 50
hset student:2 name hao math 90 pe 95
hset student:3 name wang math 80 pe 80 
這裡 student: 後面的數字表示學生的 id

接著我想按照數學成績來對這3名同學進行排列,應該怎麼寫 redis 的命令呢?

sort id by student:*->math get student:*->name desc
這句話本質上做了什麼呢?

其實他只是對 id 中的1、2、3進行了一個排序,排序的規則是按照 student:* 篩選出來的散列表的 math 欄位進行排列的,最後再返回 student:* 散列表的 name 欄位的值,順便使用 desc 進行從大到小的排序,預設的排序是從小到大的。那麼 math 成績一樣的 yang 和 wang呢?則按照 student:* 中的 * 來排序。所以最後的結果是:

hao 

wang

yang

sort by 的重點在哪裡呢?就在 by 後面的參考點的篩選上,如果沒有 student:* 的表,即 student:1、student:2、student:3,那麼針對 id 進行排序沒有任何意義,正是因為 student:* 匹配到了 student:1、student:2、student:3,才賦予了 id 排序的含義。具體的使用場景肯定不止我上面講的這一種,還是自己去嘗試一下比較好,現在只是掌握了基礎的語法,到具體的應用還有一段差距的。

還有幾個關鍵字

limit offset count 

作用跟關係資料庫中是一樣的,限制返回的數量,offset 偏移量,count 返回的數量。

還可以使用關鍵字 store 儲存最後的排列結果。

順便再加一句 * 要在 -> 前面使用才有用。

第四個知識點--訊息通知

這個知識點可以結合上一篇的列表知識來理解,是列表的升級版。

基本語法:

brpop key1 timeout1 key2 timeout2 key3 timeout3

blpop key1 timeout1 key2 timeout2 key3 timeout3


brpop 與 rpop 一樣,是從列表型別的 key 中從右邊取出第一個資料,不同的是,rpop 噹噹前列表為空時就會返回 nil (no list),但是 brpop 則會等待 timeout 秒的時間,如果在 timeout 之前有資料存入則會自動取出顯示,blpop 也是一樣的。當設定多個 timeout 時,以最大的 timeout 作為超時時間,當其中一個有資料輸出則停止全部的等待。

例:

在 redis-cli.exe 中輸入以下內容:

brpop key1 10 key2 60

在大約20多秒的時候再開啟一個 redis-cli.exe 輸入以下內容:

rpush key1 100

在最開始開啟的 redis-cli.exe 中就會顯示以下內容,並且退出 brpop 的等待時間:

key1
100
(20.96s)

可以看到上面設定的 key1 的 timeout 是10,可是10s 後還是有效的,這就說明是以最長過期時間為準的,如果想要永久有效,要不直接不寫,或者寫0.

最後的結果:


這個有什麼用呢?書上的例子是說用來處理以下情況的:

當一個博主發表一篇文章後,都發一封郵件給訂閱他部落格的人,通知他們訂閱的部落格更新了,所以資料庫會儲存這些訂閱者的郵箱,但是為了驗證該郵箱的有效性,所以在使用者輸入完一個郵箱之後都會發送一封確認郵件到使用者的指定郵箱,使用者需要點選郵箱中的連結地址才能完成驗證,但是問題就來了,一定是拿列表來儲存這些需要驗證的郵箱,但是如果採用一般的 rpop 或者 lpop,每次都需要判斷一下該佇列是否為空,不為空的話就執行 rpop,那麼意味著我們在控制器端需要一直監視這個佇列的情況。但是採用 brpop 之後,如果佇列為空的話,就會一直等待,直到新增如資料,並把資料取出,這些都可以交由 redis 內部去執行,而不需要我們額外使用第三方程式碼實現。

除了上面的內容,還有一個釋出/訂閱的模式:

基本語法2:

publish channel message

subscribe channel1 channel2 channel3

publish     釋出

subscribe 訂閱

一個執行緒呼叫 subscribe channel1 channel2 channel3
一個執行緒呼叫 publish channel message
如果 subscribe 的 channel1、channel2、channel3 與 publish 的 channel 一致就會接收到 message,否則就沒有
可以嘗試以下下面的程式碼就懂了


注意,subscribe 可以一次性訂閱多個 channel,但是 publish 每次卻只能往一個 channel 中傳送資料。

但是這樣就會存在問題,當一次訂閱多個 channel 時就要每個輸入一遍,可以使用萬用字元來解決這個問題
psubscribe pattern 
例:
psubscribe channel1.?* 
這樣就可以同時訂閱例如 channel1.1、channel1.100、channel1.40等,萬用字元的含義在字串型別中講解過了。

第五個知識點--管道

就是將多條命令儲存在一起,從客戶端,也就是--redis-cli.exe 中傳入到 redis 一起進行處理,再將結果返回,有點像事務,但是不像事務一定要每條命令都i執行完畢,本質上管道就是把多條互不相連的命令一起傳送給 redis,然後再統一將處理結果傳送回來而已。這個是通過第三方程式語言來實現的,不是 redis 本身的命令。

感覺越到越後面越想說一句,碼字好幸苦。快哭了