文章目錄
- BLPOP key1 [key2 ...] timeout
redis提供比較豐富的資料結構, 如string, list, set, sorted set, hashs. 其中幾個較複雜的資料結構, 如list,
set, sorted, hashs, 內部都是存放的string. 這裡的string其實可以理解為一個帶長度的byte數組,
在實際使用可以存放或轉換為自己需要的資料類型, 比如可以用於放一張圖片, 一段視頻…
list是複雜資料結構中最常用的一種, redis的list實際上一個雙向鏈表, 內部存放的元素是string. 可以看看redis的原始碼,
使用git下載原始碼:
git clone git://github.com/antirez/redis.git
redis-master
完成後, 在redis-master目錄中的src目錄, 有adlist.h與adlist.c源檔案.
開啟adlist.h, 可以看到list的定義是:
而listNode的定義是:
從代碼中可以看到, 每一個list使用len成員存放了元素的個數, 因而使用redis提供的llen命令取列表長度的時間複雜度是O(1).
list還記錄了隊列的頭與尾, 因而針對隊列頭與尾的push, pop系列的命令, 它們的時間複雜度也是O(1).
redis提供了一系列的命令操作list, 詳細的說明見:
http://www.redis.io/commands#list
其中最有意思的是由b開頭的三個命令: BLPOP, BRPOP, BRPOPLPUSH, 這三個命令是涉及到從隊列中彈出元素的阻塞版本,
當隊列中沒有元素時, 調用這三個命令會一直等待, 直到有元素進入到隊列中, 或者達到逾時條件. 阻塞版本的POP命令可以避免對資料庫的輪詢操作,
從而減少一些壓力.
BLPOP, BRPOP, BRPOPLPUSH三個命令的格式比較相似, 以BLPOP為例, 其格式是:
BLPOP key1 [key2 ...] timeout
timeout用於指定這個命令的逾時時間, 以秒為單位, 當這個值指定為0時, 表示無限阻塞, 直到有元素返回為止.
key1, key2, … 是指本命令可以同時查看多個key是否有元素, 查看的方式從前往後按順序, 首先查看key1是否有元素, 有則返回,
沒有則查看key2, 以此類推, 如果指定了key的所有隊列都是空的, 則進入阻塞模式, 在阻塞的過程中, 任何一個list有內容, 將馬上返回.
由於BLPOP可以指定多個key, 因而命令在返回時, 需要說明返回的是那個key的元素. 這個命令的傳回值有兩個, 當有元素返回時,
第1個值表示list的key名稱, 第2值存放了元素的內容; 當使用逾時模式, 沒有元素返回時, 第1個值是nil, 第二值是阻塞的時間.
有了阻塞版本的POP命令, 我們可以使用redis來實現生產者-消費者的模式. 生產者往redis資料庫中特定的隊列存放資料, 消費者從隊列中取出資料,
當資料為空白時, 消費者進入阻塞狀態.
下面的例子, 使用兩個lua程式類比一個網購網站的訂單系統, 在執行時可以在兩個終端中分別執行, 下面是終端1執行生產者的:
下面終端2執行消費者的:
相應的代碼, 生產者:
-- producer.lua
require "redis"
local myclient = Redis.connect()
assert( myclient)
local orderId = 0
while true do
print("Please Input Order ID:")
orderId =
io.read( "*number")
if orderId == nil or orderId < 0 then
break
else
myclient:rpush( "orders", orderId)
--往orders隊列放訂單ID
print( "Order Sucess.")
end
end
消費者:
-- consumer.lua
require "redis"
myclient = Redis.connect()
assert( myclient)
while true do
orderIds = myclient:blpop( "orders", 0)
if
orderIds[1] ~= nil then
print( "Pop a value form ", orderIds[1])
print( "/tProcessing Order, ID: ", orderIds[2])
end
end