SquirrelMQ消息隊列介紹
代碼量不算多,非常適合學習(socket,poll,memory方面都不錯)
SquirrelMQ是一個快速的消息隊列。
SquirrelMQ特性:
1. SquirrelMQ使用Slab內存分配算法來降低內存碎片,使用epoll來解決高并發問題。效率比redis要高,使用簡單。
2. 另外SquirrelMQ支持持久化,在down機的情況下也不用擔心數據丟失。
3. SquirrelMQ支持lua腳本,你可以制定自己的處理隊列程序,只要在cron/main.lua中編寫代碼即可。
一,SquirrelMQ使用
下面,我們介紹使用SquirrelMQ消息隊列來完成上面所說的應用吧。1) 安裝Lua。
2) 首先下載編譯SquirrelMQ:
#> wget http://squirrel-message-queue.googlecode.com/files/squirrel-with-lua-v1.2.zip
#> tar –zxvf squirrel-with-lua-v1.2.zip
#> cd squirrel-with-lua-v1.2
#> make
3) 修改SquirrelMQ配置(squirrel.conf文件):
# 偵聽端口 listingPort 6061 # 最大可以使用內存數(單位:字節) memoryLimitUsed 524288000 # 多長時間進行存儲數據到硬盤(防止down機時數據丟失,單位為秒) secondsToSaveDisk 30 # 多少次數據變化才進行存儲數據到硬盤(防止寫數據過于頻繁) chagesToSaveDisk 30 # 客戶端連接多長時間不操作自動關閉(單位為秒) clientExpiredTime 60 # 多長時間運行一次cron(單位為毫秒) cronLoops 5000 # 是否需要密碼認證 enableAuth 0 # 認證密碼(在enableAuth為1時才需要) authPwd xn2k@*%bse!@ # lua腳本的路徑 luaFilePath /var/squirrelmq/main.lua # 提供給SquirrelMQ調用的函數 luaMainFunction __main__ # 是否使用守護進程模式運行 daemonize 0
我們根據自己的需求來修改配置,特別說明一下的是,當開啟Lua處理線程時,我們可以編寫Lua腳本來處理隊列(在cron/main.lua)。這樣就可以讓服務器本身來處理消息隊列的數據,而不用另外寫一個cron程序來處理。下面我們會介紹。
4) 運行SquirrelMQ:
#> ./squirrel –c squirrel.conf
二,使用客戶端API
SquirrelMQ提供一個PHP訪問的API,在php/squirrel.class.php。我們可以使用這個API文件輕松地訪問SquirrelMQ。這個API文件把所有訪問SquirrelMQ的操作封裝成一個類,叫Squirrel,在使用時直接new一個Squirrel的對象即可,如下:
<?php include("squirrel.class.php"); $smq = new Squirrel('127.0.0.1', 6061); $smq->push_tail("INSERT INTO mytable(uid, username, password)VALUES(NULL, 'liexusong', '123456');"); ?>
這樣,我們就可以把一條消息插入到消息隊列了。我們可以使用size()方法來獲取SquirrelMQ的消息條數:
<?php include("squirrel.class.php"); $smq = new Squirrel('127.0.0.1', 6061); $size = $smq->size(); echo "The SquirrelMQ size: $size"; ?>
SquirrelMQ支持的API有:
1)插入到隊列的頭部: $smq->push_head($message); 2)插入到隊列的尾部: $smq->push_tail($message); 3)取得隊列的第一條消息,并從隊列中刪除: $message = $smq->pop_head(); 4)取得隊列的最后一條消息,并從隊列中刪除: $message = $smq->pop_tail(); 5)取得隊列的第n條消息,并且從隊列中刪除: $message = $smq->pop_index($index); 6)取得隊列的第一條消息,但不從隊列中刪除: $message = $smq->get_head(); 7)取得隊列的最后一條消息,但不從隊列中刪除: $message = $smq->get_tail(); 8)取得隊列的第n條消息,但不從隊列中刪除: $message = $smq->get_index($index); 9)取得隊列的大小: $size = $smq->size(); 10)取得隊列的狀態: $stat = $smq->stat();
三,使用Lua處理隊列
SquirrelMQ的一個令人興奮的特性就是支持使用Lua處理隊列中的消息,下面我們來介紹一下這個功能。要開啟Lua處理線程,需要在配置文件中把enableLuaThread設置為1。這樣SquirrelMQ就會開啟Lua處理線程。我們可以在 cron/main.lua文件中編寫我們的Lua代碼來處理隊列中的消息。在cron/main.lua文件中,必須編寫一個main的函數,SquirrelMQ就是以這個函數作為入口,如:
function __main__() ...... end
在main函數中,我們可以使用一些SquirrelMQ提供的API函數取得隊列中的消息,如smq_pop_head()和smq_pop_tail()等。main函數可以這樣寫:
require "luasql.mysql" function __main__() env = luasql.mysql() con = env:connect("database", "username", "password", "127.0.0.1", 3306) while true do local ok, sql = smq_pop_head() if ok then res = con:execute(sql) end end con:close() env:close() end
記住,SquirrelMQ提供的API都是阻塞的,也就是說,當隊列為空時,API會阻塞知道隊列有消息可以獲取為止,這樣做的目的是為了盡量減少Lua線程的運行時間。
在上面例子中,我們使用smq_pop_head()來取得隊列的第一條消息,然后執行此消息(con:execute(sql))。
SquirrelMQ提供給Lua線程使用的API有:
ok, item = smq_pop_head() ok, item = smq_pop_tail() ok, item = smq_pop_index() ok, item = smq_get_head() ok, item = smq_get_tail() ok, item = smq_get_index() size = smq_queue_size() ok = smq_push_head(item) ok = smq_push_tail(item)
上面的API對應PHP客戶端的API。