redis 二、高級用法

事務

redis的事務是一組命令的集合。事務同命令一樣都是redis的最小執行單元,一個事務中的命令要麼執行要麼都不執行。

首先需要multi命令來開始事務,用exec命令來執行事務。

複製代碼
127.0.0.1:6379> multi
OK
127.0.0.1:6379> hset user:1 name xiaoming
QUEUED
127.0.0.1:6379> hset user:1 name daxiong
QUEUED
127.0.0.1:6379> exec
1) (integer) 0
2) (integer) 0
127.0.0.1:6379> hgetall user:1
1) "name"
2) "daxiong"
3) "score"
4) "61"
複製代碼
multi代表事務的開始,返回ok表示成功;
 
exec代表事務的執行,返回各個命令的執行結果;
 
在multi和exec中間添加需要執行的命令。
 
在multi開始後,所有命令都不會執行,而是全部暫時保存起來,在執行exec命令後會按照命令保存的順序依次執行各個命令。
 
如果事務執行過程中存在失敗的情況下(某一個命令執行失敗後其他命令會繼續執行),需要開發人員自行處理後果。
 
注意:redis不支持回滾操作,導致redis的錯誤異常需要開發人員處理。

watch

watch命令可以監控一個或多個鍵值的變化,一旦其中一個鍵被改變,之後的事務就不會執行,而且監控會一直持續到exec命令。
複製代碼
127.0.0.1:6379> set key 1
OK
127.0.0.1:6379> watch key
OK
127.0.0.1:6379> set key 2
OK
127.0.0.1:6379> multi
OK
127.0.0.1:6379> set key 3
QUEUED
127.0.0.1:6379> exec
(nil)
127.0.0.1:6379> get key
"2"
複製代碼

生存時間

(1)設置key的超時時間,超時後redis會自動刪除給key值,類似於memcache中的超時時間。
 
expire     key     seconds
//設置成功返回1,失敗返回0
複製代碼
127.0.0.1:6379> set session:aabb uid1122
OK
127.0.0.1:6379> expire session:aabb 300
(integer) 1
127.0.0.1:6379> del session:aabb
(integer) 1
127.0.0.1:6379> expire session:aabb 300
(integer) 0
 
127.0.0.1:6379> expire session:aabb 300
(integer) 1
127.0.0.1:6379> ttl session:aabb 
(integer) 290
複製代碼
(2)查詢剩餘超時時間
ttl     key
127.0.0.1:6379> expire session:aabb 300
(integer) 1
127.0.0.1:6379> ttl session:aabb 
(integer) 290
(3)取消超時時間
複製代碼
127.0.0.1:6379> get session:aabb
"300"
127.0.0.1:6379> ttl session:aabb 
(integer) 280
127.0.0.1:6379> persist session:aabb
(integer) 1
127.0.0.1:6379> ttl session:aabb
(integer) -1
複製代碼
(4)如果使用設置相關的命令,會取消該鍵的超時間

緩存數據

在某些情況下,需要緩存一部分網站數據,而網站數據由需要持續的更新(假如需要兩個小時更新一次),那麼可以採用redis進行緩存這部分數據,設置數據的超時時間爲2小時,每當有請求訪問的時候首先到redis中查找該數據是否存在,如果存在直接讀取,如果不存在的話重新從數據庫中讀取該數據加載到redis中。
 
在緩存數據的時候需要考慮到被緩存數據的大小,如果緩存數據較大,會佔用過多的內存資源,有必要在配置文件中限制內存的使用大小(maxmemory)。
 
當超過maxmemory的限制後,redis會根據maxmemory-policy參數指定的策略(包括LRU等算法)來刪除不需要的鍵。

排序

sort命令支持對集合類型、類表類型、有序集合類型進行排序。
按 Ctrl+C 複製代碼
按 Ctrl+C 複製代碼
可以對有序集合的值進行排序:
複製代碼
127.0.0.1:6379> zadd set 50 2 40 3 20 1 60 5
(integer) 4
127.0.0.1:6379> sort set
1) "1"
2) "2"
3) "3"
4) "5"
複製代碼
sort命令可以添加desc來實現倒序排序
127.0.0.1:6379> sort set desc
1) "5"
2) "3"
3) "2"
4) "1"

BY參數

很多時候我們需要根據ID對應的對象的某一個屬性進行排序,那麼如何才能把多個不同的數據進行關聯查詢呢?
(1)首先,向userids中添加三個用戶id
127.0.0.1:6379> lpush userids 1 2 3
(integer) 3
(2)其次,分別對三個用戶添加分數
127.0.0.1:6379> set user_score_1 50
OK
127.0.0.1:6379> set user_score_2 30
OK
127.0.0.1:6379> set user_score_3 70
OK
(3)最後,使用sort、by命令來對對用戶按照默認情況以及分數的遞增和遞減進行排序。
複製代碼
127.0.0.1:6379> sort userids
1) "1"
2) "2"
3) "3"
127.0.0.1:6379> sort userids by user_score_*
1) "2"
2) "1"
3) "3"
127.0.0.1:6379> sort userids by user_score_* desc
1) "3"
2) "1"
3) "2"
複製代碼

GET參數

get參數並不影響排序,它的作用是使sort命令返回的結果不再是元素自身的值,而是get參數中指定的鍵值,同by參數一樣,支持字符串類型和散列類型的鍵。
複製代碼
127.0.0.1:6379> sort userids by user_score_* get user_name_*
1) "xiaoming"
2) "daxiong"
3) "xiaohong"
127.0.0.1:6379> sort userids by user_score_* desc get user_name_*
1) "xiaohong"
2) "daxiong"
3) "xiaoming"
複製代碼

STORE參數

store參數用於結果保存。
 
sort命令是redis的複雜命令之一,使用不好會造成性能的瓶頸。
 
sort命令的時間複雜度是O(n+mlog(m)),其中n是排序列表(集合和有序集合)中元素的個數,m是返回元素的個數。Redis在排序前會建立一個長度爲n的的容器來存儲待排序元素,雖然是一個臨時的過程,但是多個較大數據的排序操作則會嚴重影響系統的性能。
 
因此,在開發中需要注意:
(1)儘可能減少排序鍵中的元素個數,降低n
(2)使用Limit參數只獲取需要的數據,降低n
(3)如果要排序的數據量較大,儘可能使用store名來緩存結果。

任務隊列

任務隊列一般適用於生產者和消費者之間通信的,那麼在redis中很容易想到使用列表類型來實現任務隊列,具體方法是創建一個任務隊列,生產者主動lpush數據,而消費者去rpop數據,保持一個先進先出的循序。
但是這樣存在一個問題,消費者需要主動去請求數據,週期性的請求會造成資源的浪費,因此,redis提供了一個brpop的命令來解決這個問題。
BRPOP     key     timeout
brpop命令接收兩個參數,第一個參數key爲鍵值,第二個參數timeout爲超時時間。BRPOP命令取數據時候,如果暫時不存在數據,該命令會一直阻塞直到達到超時時間。如果timeout設置爲0,那麼就會無限等待下去。

優先級隊列

基於任務隊列,如何實現優先級隊列呢?
 
那麼可以選擇多個任務隊列,而每個任務隊列的任務優先級是不同的。
 
redis提供了下面的命令,會從左邊第一個key開始讀下去知道返回一個數據。
brpop key [key...] timetout

發佈/訂閱模式

redis提供了rabitmq類似的發佈訂閱模式,通過生產者使用下面的命令來發布消息,
PUBLISH     CHANNEL     MESSAGE
消費者通過下面的消息來訂閱消息,
SUBSCRIBE     CHANNEL     MESSAGE
生產者:
#向channel.test發佈消息
127.0.0.1:6379> publish channel.test hello
(integer) 0 #返回0表明訂閱者爲0,沒有發佈消息
127.0.0.1:6379> publish channel.test hello
(integer) 1 #返回n表明訂閱者爲n,成功發佈給1個消費者
消費者:
#訂閱channel.test消息
127.0.0.1:6379> subscribe channel.test 
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "channel.test"
3) (integer) 1
#接收到來自channel.test的消息
1) "message"
2) "channel.test"
3) "hello"

管道

redis的底層通信協議對管道提供了支持。通過管道可以一次性發送多條命令並在執行完後一次性將結果返回,當一組命令中每條命令都不依賴之前命令的執行結果時就可以將這組命令一起通過管道發出。管道通過減少客戶端與redis的通信次數來實現降低往返實驗累計值的目的。

節省空間

(1)精簡鍵名和鍵值
(2)redis爲每種數據類型提供了兩種內部編碼。例如散列類型的存儲是通過散列表來實現的,redis會根據數據的多少來選擇編碼類型,當數據較少的時候會採用緊湊但性能稍差的內部編碼方式,而數據變多時會把編碼方式改爲散列表。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章