1. 程式人生 > >Beanstalk分散式記憶體佇列系統

Beanstalk分散式記憶體佇列系統

Beanstalk是一個高效能、輕量級的、分散式的、記憶體型的訊息佇列系統。最初設計的目的是想通過後臺非同步執行耗時的任務來降低高容量Web應用系統的頁面訪問延遲。其實Beanstalkd是典型的類Memcached設計,協議和使用方式都是同樣的風格。其基本設計思想很簡單:高效能離不開非同步,非同步離不開佇列,而內部都是生產者-消費者模式的。

背景介紹:

  現在市面上有很多訊息佇列系統了。常用的有ActiveMQ, RabbitMQ,ZeroMA,Kafka,RocketMQ。Redis之父最近又開源了一個Disque。我之前用的是apache的qpid。但是之所以各個系統都在流行,還要看其側重點。

  其中ActiveMQ可以稱之為傳統型,它們完全支援JMS和AMQP規範。

  JMS即Java訊息服務(Java Message Service)應用程式介面。它是Java平臺上有關面向訊息中介軟體(Message Oriented Middleware,縮寫為MOM)的技術規範,它便於訊息系統中的Java應用程式進行訊息交換,並且通過提供標準的產生、傳送、接收訊息的介面簡化企業應用的開發。(*我這裡說了,JMS是應用程式介面,就是API,API就意味著是和程式語言繫結的)

  JMS的體系架構由JMS提供者、JMS客戶、JMS生產者、JMS消費者、JMS訊息、JMS佇列、JMS主題組成。

  JMS物件模型包含:連線工廠、JMS連線、JMS會話、JMS目的、JMS生產者和消費者和JMS訊息。其中大家最關心的是JMS訊息的兩種模型:點對點(point to point, queue)和釋出/訂閱(publish/subscribe, topic)。這兩者之間的區別就是點對點模式是生產者傳送一條訊息到queue,一個queue可以有很多消費者,但是一個訊息只能被一個消費者接收,當沒有消費者可用時,這個訊息會被儲存直到有一個可用的消費者,所以queue實現了一個可靠的負載均衡。而釋出訂閱模式是釋出者傳送到topic的訊息,只有訂閱了topic的訂閱者才會收到訊息。topic實現了釋出和訂閱,當你釋出一個訊息,所有訂閱這個topic的服務都能得到這個訊息,所以從1到N個訂閱者都能得到這個訊息的拷貝。

  AMQP(高階訊息佇列協議),和JMS的區別在於:JMS只是java平臺的方案,AMQP是一個跨語言的協議。由於跨語言的特點,降低了企業和系統整合的開銷。所以現在的訊息佇列系統支援AMQP的多,支援JMS的少。

  AMQP的特徵是面向訊息,佇列化,訊息模型(和JMS一樣:點對點和釋出訂閱),可靠性和安全性。它提供了三種訊息傳遞保證方式:最多一次,至少一次和精確一次。  

  我們經常在使用訊息佇列的時候提到的broker是對實現了AMQP協議的服務端的稱呼。其基本結構如下圖。

 Beanstalk介紹:

  那下面開始說beanstalk了。首先說beanstalk其實並不是JMS規範的,也並不嚴格遵守AMQP協議。有人說Beanstalk之於RabbitMQ,就好比Nginx之於Apache。它更簡單,輕量級,高效能,易使用。但是相比kafka,資料處理能力還是有差距,所以我們現在其實在逐漸替代它。但它有些很易用的特殊功能,後面會講到。

  Beanstalk主要包括4個部分。

  1> job:一個需要非同步處理的任務,需要放在一個tube中。

  2> tube:一個有名的任務佇列,用來儲存統一型別的job,是producer和consumer操作的物件。

  3> producer:job的生產者,通過put命令來將一個job放到一個tube中。

  4> consumer:job的消費者,通過reserve、release、bury、delete命令來獲取job或改變job的狀態。

  剛才說Beanstalk有一些特殊的好用功能。那就是它支援任務優先順序(priority)、延時(delay)、超時重發(time-to-run)和預留(buried),能夠很好的支援分散式的後臺任務和定時任務處理。這些特性是和beanstalk工作過程密切相關。

  Beanstalk的一個job的生命週期有READY、RESERVED、DELAYED、BURIED四種。

  當producer直接put一個job時,job就是READY狀態,等待consumer來處理。如果選擇延遲put,job就先到DELAYED狀態,到指定時間再READY。consumer獲取了READY的job,此狀態就為RESERVED。這樣其他consumer不能再操作此job。當consumer完成該job後,可以選擇delete、release或者bury。

  delete之後,job不能再獲取。release的job可以重新遷移或延遲遷移回READY。bury的job可以被休眠,需要的時候再READY或者delete掉。

Beanstalk使用場景:

  用作延時佇列:比如可以用於如果使用者30分鐘內不操作,任務關閉。

  用作迴圈佇列:用release命令可以迴圈執行任務,比如可以做負載均衡任務分發。

  用作兜底機制:比如一個請求有失敗的概率,可以用Beanstalk不斷重試,設定超時時間,時間內嘗試到成功為止。

  用作定時任務:比如可以用於專門的後臺任務。

  用作非同步操作:這是所有訊息佇列都最常用的,先將任務仍進去,順序執行。