應用場景數據庫
有不少業務, 客戶端和內網都要進行數據傳輸和交換, 現有架構中, 客戶端不能直接訪問內網, 緩存
那麼客戶端只能: 先把數據保存到外網服務器, 而後內網服務器再拉回來處理. 這種方式能夠保證數據服務器
都能被處理, 但實效性不夠.網絡
一般, 外網服務器只起到一個暫時保存數據的做用, 保存客戶端報上來的數據, 而後等待內網來拉走,架構
把客戶端看作producer, 內網看作consumer, 這正是消息隊列的用武之地.併發
客戶端先把數據寫入外網服務器的消息隊列, 而後內網服務器再從消息隊列取走數據, 消息隊列須知足:高併發
(1) 支持高併發的入隊和出隊操做, 容許不少客戶端同時插入數據, 並且容許內網服務器高頻率地取走性能
數據測試
(2) 支持數據的持久化, 爲保證速度, 消息隊列緩存在內存中, 若是內存不夠用了, 則寫入磁盤.網站
(3) 支持一次性插入多條記錄, 以及一次性取走多條數據, 這樣能夠提升傳輸效率
二 技術選型
1 存儲方案: Tokyo Cabinet
Tokyo Cabinet數據庫是日本最大的社交網站mixi開發的一款Key-Value數據庫,之因此選擇Tokyo Cabinet,
而不是MySQL, Redis或者Memcached, 這是由於:
(1) Tokyo Cabinet的讀寫速度很是快, 比MySQL快不少, 和Memcached差很少, 比Redis固然慢一截,
有測試數據爲證:
寫入100萬條:tcbtest write test.tcb 1000000
時間: 0.994秒 速度:100,6036條/秒
寫入200萬條:tcbtest write test.tcb 2000000
時間: 2.028秒 速度: 98,6193條/秒
寫入500萬條:tcbtest write test.tcb 5000000
時間: 5.276秒 速度: 94,7687條/
(2) Tokyo Cabinet佔用內存不大, 並且支持數據的持久化, 用戶能夠設定內存緩存的大小, 緩存不夠用
的時候, 就把數據持久化到磁盤
2 網絡接口: Libevent
Tokyo Cabinet只是一個數據存儲層面的東西, 它沒有提供網絡接口, 因此得寫一個http服務器爲用戶
提供服務.對於高併發的服務器來講, 基於事件驅動的libevent網絡庫是很是好的選擇. 事實上, libevent
自帶了一個簡單高效的http服務器實現, 對於消息隊列服務器來講足夠使用了. 代碼不足400行.
三 如何使用
用戶使用http的get請求來操做消息隊列. 參數以下
o: 操做參數, 取值爲{get|set|status}, set表示入隊,get表示出隊, status查看隊列的狀態
m: 消息數據.
p: 密碼參數或者校驗參數
n: 一次入隊n條消息, 或者出隊n條消息
1 入隊
http://localhost:3333/dsr?o=set&d=foobar|hello|world
把foobar, hello, world三條消息插入隊列,消息之間用"|"號隔開,若成功入隊, 服務端返回0#0
2 出隊
http://localhost:3333/dsr?o=get&n=10
從隊列中取出10條消息, 每條消息以換行符隔開.
3 狀態
http://localhost:3333/dsr?o=status
查看隊列的狀態,顯示隊列的容量, 當前消息數量, 隊列頭指針, 隊列尾指針:
四 壓力測試
測試環境 : 8核CPU
1 入隊操做
1000併發量, 插入10萬條消息, 每條消息512字節
* 使用keep-alive
測試結果:21246 qps, 佔用磁盤空間: 51M
* 不使用keep-alive
測試結果:12768 qps, 佔用磁盤空間: 51M
2 出隊操做
1000併發量, 每次取走一條消息, 取10萬次
* 使用keep-alive
測試結果: 27709 qps
* 不使用keep-alive
測試結果: 11461 qps
從測試結果來看, 消息隊列的讀寫性能都很是不錯, 應該可以知足不少應用的需求