消息隊列的使用場景是怎樣的?
- 校驗用戶名等信息,如果沒問題會在數據庫中添加一個用戶記錄
- 如果是用郵箱注冊會給你發送一封注冊成功的郵件,手機注冊則會發送一條短信
- 分析用戶的個人信息,以便將來向他推薦一些志同道合的人,或向那些人推薦他
- 發送給用戶一個包含操作指南的系統通知
- 等等……
除了這些之外,比較常用的就是起到消峰時需要用到:
比如你的服務器一秒能處理100個訂單,但秒殺活動1秒進來1000個訂單,持續10秒,在后端能力無法增加的情況下,你可以用消息隊列將總共10000個請求壓在隊列里,后台consumer按原有能力處理,100秒后處理完所有請求(而不是直接宕機丟失訂單數據)。
技術都是解決問題的,消息隊列解決的是將突發大量請求轉換為后端能承受的隊列請求。
作者:很輕很安靜
鏈接:https://www.zhihu.com/question/34243607/answer/127666030
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
鏈接:https://www.zhihu.com/question/34243607/answer/58314162
來源:知乎
著作權歸作者所有。商業轉載請聯系作者獲得授權,非商業轉載請注明出處。
個人認為消息隊列的主要特點是異步處理,主要目的是減少請求響應時間和解耦。所以主要的使用場景就是將比較耗時而且不需要即時(同步)返回結果的操作作為消息放入消息隊列。同時由於使用了消息隊列,只要保證消息格式不變,消息的發送方和接收方並不需要彼此聯系,也不需要受對方的影響,即解耦和。
使用場景的話,舉個例子:假設用戶在你的軟件中注冊,服務端收到用戶的注冊請求后,它會做這些操作:
- 校驗用戶名等信息,如果沒問題會在數據庫中添加一個用戶記錄
- 如果是用郵箱注冊會給你發送一封注冊成功的郵件,手機注冊則會發送一條短信
- 分析用戶的個人信息,以便將來向他推薦一些志同道合的人,或向那些人推薦他
- 發送給用戶一個包含操作指南的系統通知
- 等等……
但是對於用戶來說,注冊功能實際只需要第一步,只要服務端將他的賬戶信息存到數據庫中他便可以登錄上去做他想做的事情了。至於其他的事情,非要在這一次請求中全部完成么?值得用戶浪費時間等你處理這些對他來說無關緊要的事情么?所以實際當第一步做完后,服務端就可以把其他的操作放入對應的消息隊列中然后馬上返回用戶結果,由消息隊列異步的進行這些操作。
或者還有一種情況,同時有大量用戶注冊你的軟件,再高並發情況下注冊請求開始出現一些問題,例如郵件接口承受不住,或是分析信息時的大量計算使cpu滿載,這將會出現雖然用戶數據記錄很快的添加到數據庫中了,但是卻卡在發郵件或分析信息時的情況,導致請求的響應時間大幅增長,甚至出現超時,這就有點不划算了。面對這種情況一般也是將這些操作放入消息隊列(生產者消費者模型),消息隊列慢慢的進行處理,同時可以很快的完成注冊請求,不會影響用戶使用其他功能。
所以在軟件的正常功能開發中,並不需要去刻意的尋找消息隊列的使用場景,而是當出現性能瓶頸時,去查看業務邏輯是否存在可以異步處理的耗時操作,如果存在的話便可以引入消息隊列來解決。否則盲目的使用消息隊列可能會增加維護和開發的成本卻無法得到可觀的性能提升,那就得不償失了。我可以舉個小例子先說明應用場景
假設你的服務器每分鍾的處理量為200個,但客戶端再峰值的時候可能一分鍾會發1000個消息給你,這時候你就可以把他做成隊列,然后按正常有序的處理,先進后出(LIFO),先進先出(FIFO)可根據自己的情況進行定奪
stack 先進后出(LIFO)--------java 對應的類 Stack
隊列 先進先出(FIFO)--------java對應的類Queue
這兩種都可用Linkedlist進行封裝和實現,下面是我自己寫的一個棧的例子
LinkedList<String> linkedList = new LinkedList<>();
- /**
- *
- * --------->>>>>>隊列的實現--------------
- */
- public class MyStack<T> {
- private LinkedList<T> storage = new LinkedList<T>();
- public synchronized void push(T e) {//需要加上同步
- storage.addFirst(e);
- }
- public T peek() {
- return storage.getFirst();
- }
- public void pop() {
- storage.removeFirst();
- }
- public boolean empty() {
- return storage.isEmpty();
- }
- @Override
- public String toString() {
- return storage.toString();
- }
- }
Java利用Redis實現消息隊列
應用場景
- 為什么要用redis?
二進制存儲、java序列化傳輸、IO連接數高、連接頻繁
一、序列化
這里編寫了一個java序列化的工具,主要是將對象轉化為byte數組,和根據byte數組反序列化成java對象; 主要是用到了ByteArrayOutputStream和ByteArrayInputStream; 注意:每個需要序列化的對象都要實現Serializable接口;
其代碼如下:
1 package Utils;
2 import java.io.*;
3 /**
4 * Created by Kinglf on 2016/10/17.
5 */
6 public class ObjectUtil {
7 /**
8 * 對象轉byte[]
9 * @param obj
10 * @return
11 * @throws IOException
12 */
13 public static byte[] object2Bytes(Object obj) throws IOException{
14 ByteArrayOutputStream bo=new ByteArrayOutputStream();
15 ObjectOutputStream oo=new ObjectOutputStream(bo);
16 oo.writeObject(obj);
17 byte[] bytes=bo.toByteArray();
18 bo.close();
19 oo.close();
20 return bytes;
21 }
22 /**
23 * byte[]轉對象
24 * @param bytes
25 * @return
26 * @throws Exception
27 */
28 public static Object bytes2Object(byte[] bytes) throws Exception{
29 ByteArrayInputStream in=new ByteArrayInputStream(bytes);
30 ObjectInputStream sIn=new ObjectInputStream(in);
31 return sIn.readObject();
32 }
33 }

