Java消息队列_为什么使用消息队列

原文:https://www.cnblogs.com/panxuejun/p/7765705.htmlhtml

消息队列的使用场景是怎样的?

常常听到诸如rebbitmq,activemq,请教一下各位前辈消息队列的使用场景是怎样的,何时会用到它java

 

  1. 校验用户名等信息,若是没问题会在数据库中添加一个用户记录
  2. 若是是用邮箱注册会给你发送一封注册成功的邮件,手机注册则会发送一条短信
  3. 分析用户的我的信息,以便未来向他推荐一些志同道合的人,或向那些人推荐他
  4. 发送给用户一个包含操做指南的系统通知
  5. 等等……


除了这些以外,比较经常使用的就是起到消峰时须要用到:
好比你的服务器一秒能处理100个订单,但秒杀活动1秒进来1000个订单,持续10秒,在后端能力没法增长的状况下,你能够用消息队列将总共10000个请求压在队列里,后台consumer按原有能力处理,100秒后处理完全部请求(而不是直接宕机丢失订单数据)。
技术都是解决问题的,消息队列解决的是将突发大量请求转换为后端能承受的队列请求。

做者:很轻很安静
连接:https://www.zhihu.com/question/34243607/answer/127666030
来源:知乎
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。redis

 

做者:ScienJus
连接:https://www.zhihu.com/question/34243607/answer/58314162
来源:知乎
著做权归做者全部。商业转载请联系做者得到受权,非商业转载请注明出处。数据库

 

我的认为消息队列的主要特色是异步处理,主要目的是减小请求响应时间和解耦。因此主要的使用场景就是将比较耗时并且不须要即时(同步)返回结果的操做做为消息放入消息队列。同时因为使用了消息队列,只要保证消息格式不变,消息的发送方和接收方并不须要彼此联系,也不须要受对方的影响,即解耦和。后端

使用场景的话,举个例子:
假设用户在你的软件中注册,服务端收到用户的注册请求后,它会作这些操做:数组

  1. 校验用户名等信息,若是没问题会在数据库中添加一个用户记录
  2. 若是是用邮箱注册会给你发送一封注册成功的邮件,手机注册则会发送一条短信
  3. 分析用户的我的信息,以便未来向他推荐一些志同道合的人,或向那些人推荐他
  4. 发送给用户一个包含操做指南的系统通知
  5. 等等……

可是对于用户来讲,注册功能实际只须要第一步,只要服务端将他的帐户信息存到数据库中他即可以登陆上去作他想作的事情了。至于其余的事情,非要在这一次请求中所有完成么?值得用户浪费时间等你处理这些对他来讲可有可无的事情么?因此实际当第一步作完后,服务端就能够把其余的操做放入对应的消息队列中而后立刻返回用户结果,由消息队列异步的进行这些操做。服务器

或者还有一种状况,同时有大量用户注册你的软件,再高并发状况下注册请求开始出现一些问题,例如邮件接口承受不住,或是分析信息时的大量计算使cpu满载,这将会出现虽然用户数据记录很快的添加到数据库中了,可是却卡在发邮件或分析信息时的状况,致使请求的响应时间大幅增加,甚至出现超时,这就有点不划算了。面对这种状况通常也是将这些操做放入消息队列(生产者消费者模型),消息队列慢慢的进行处理,同时能够很快的完成注册请求,不会影响用户使用其余功能。并发

因此在软件的正常功能开发中,并不须要去刻意的寻找消息队列的使用场景,而是当出现性能瓶颈时,去查看业务逻辑是否存在能够异步处理的耗时操做,若是存在的话即可以引入消息队列来解决。不然盲目的使用消息队列可能会增长维护和开发的成本却没法获得可观的性能提高,那就得不偿失了。异步

 

 

 

我能够举个小例子先说明应用场景ide

假设你的服务器每分钟的处理量为200个,但客户端再峰值的时候可能一分钟会发1000个消息给你,这时候你就能够把他作成队列,而后按正常有序的处理,先进后出(LIFO),先进先出(FIFO)可根据本身的状况进行定夺

stack  先进后出(LIFO)--------java 对应的类 Stack

队列 先进先出(FIFO)--------java对应的类Queue

 

这两种均可用Linkedlist进行封装和实现,下面是我本身写的一个栈的例子

LinkedList<String> linkedList = new LinkedList<>();
 

  1. /** 
  2.  * 
  3.  * --------->>>>>>队列的实现-------------- 
  4.  */  
  5. public class MyStack<T> {  
  6.     private LinkedList<T> storage = new LinkedList<T>();  
  7.   
  8.     public synchronized void push(T e) {//须要加上同步  
  9.         storage.addFirst(e);  
  10.     }  
  11.   
  12.     public T peek() {  
  13.         return storage.getFirst();  
  14.     }  
  15.   
  16.     public void pop() {  
  17.         storage.removeFirst();  
  18.     }  
  19.   
  20.     public boolean empty() {  
  21.         return storage.isEmpty();  
  22.     }  
  23.   
  24.     @Override  
  25.     public String toString() {  
  26.         return storage.toString();  
  27.     }  
  28.   
  29. }  

 

 

Java利用Redis实现消息队列

应用场景

    • 为何要用redis?
      二进制存储、java序列化传输、IO链接数高、链接频繁

 

1、序列化

  这里编写了一个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 }

复制代码