面试

Nginx 有哪些优点?

  • 跨平台、配置简单。

  • 非阻塞、高并发连接
    处理 2-3 万并发连接数,官方监测能支持 5 万并发。

  • 内存消耗小
    开启 10 个 Nginx 才占 150M 内存。

  • 成本低廉,且开源。

  • 稳定性高,宕机的概率非常小。

Nginx 有哪些负载均衡策略?

负载均衡,即是代理服务器将接收的请求均衡的分发到各服务器中。

  1. 轮询(默认)round_robin
    每个请求按时间顺序逐一分配到不同的后端服务器,如果后端服务器 down 掉,能自动剔除。
  2. weight
    权重方式,在轮询策略的基础上指定轮询的几率。例子如下:
    server localhost:8080 weight=2;
    在该例子中,weight参数用于指定轮询几率,weight的默认值为1,;weight的数值与访问比率成正比,被访问的几率为其他服务器的两倍。
  3. IP 哈希 ip_hash
    每个请求按访问 ip 的 hash 结果分配,这样每个访客固定访问一个后端服务器,可以解决 session 共享的问题。
  4. 最少连接 least_conn
    下一个请求将被分派到活动连接数量最少的服务器

通过 Nginx 插件,我们还可以引入 fair(按照服务器端的响应时间来分配请求)、url_hash ( 按访问url的hash结果来分配请求)等负载均衡策略。

线程的几种状态

  • 新建状态:
    使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。
  • 就绪状态:
    当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。
  • 运行状态:
    如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。
  • 阻塞状态:
    如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:
    等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。
    同步阻塞:线程在获取 synchronized同步锁失败(因为同步锁被其他线程占用)。
    其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。
  • 死亡状态:
    一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。

Spring中监听器,过滤器,拦截器区别

  • 监听器(Listener):
    监听项目启动和关闭,只在项目启动和关闭时触发,一般用于处理项目的初始化工作

  • 过滤器(Filter):
    在Controller执行之前,对请求和响应进行预处理,比如设置编码格式等

  • 拦截器(Interceptor):
    可以在Controller执行前修改拦截请求,比如统一替换请求参数名称
    可以阻止Controller执行,直接回复响应给客户端,比如拦截token错误的请求
    可以在Controller回复响应后,做后续业务处理,比如记录日志等

Zookeeper的实现机制

简单的说,zookeeper=文件系统+通知机制。

1、 文件系统
Zookeeper维护一个类似文件系统的数据结构:
每个子目录项都被称作为 znode,和文件系统一样,我们能够自由的增加、删除znode,在一个znode下增加、删除子znode,唯一的不同在于znode是可以存储数据的。

有四种类型的znode:

  1. PERSISTENT-持久化目录节点
    客户端与zookeeper断开连接后,该节点依旧存在

  2. PERSISTENT_SEQUENTIAL-持久化顺序编号目录节点
    客户端与zookeeper断开连接后,该节点依旧存在,只是Zookeeper给该节点名称进行顺序编号

  3. EPHEMERAL-临时目录节点
    客户端与zookeeper断开连接后,该节点被删除

  4. EPHEMERAL_SEQUENTIAL-临时顺序编号目录节点
    客户端与zookeeper断开连接后,该节点被删除,只是Zookeeper给该节点名称进行顺序编号

2、 通知机制
客户端注册监听它关心的目录节点,当目录节点发生变化(数据改变、被删除、子目录节点增加删除)时,zookeeper会通知客户端。

JVM常用命令

  1. jps   显示系统中所有Hotspot虚拟机进程

  2. jinfo   显示虚拟机的配置信息,可观察进程运行环境参数,包括Java System属性和JVM命令行参数

  3. jstack  显示虚拟机的线程栈信息,用于生成当前JVM的所有线程快照

  4. jstat   实时显示本地或远程JVM进程中类装载、内存、垃圾收集、JIT编译等数据

  5. jmap   用于生成虚拟机的内存快照信息

  6. jconsole 内置 Java 性能分析器,可以从命令行或在 GUI shell 中运行。可使用 JConsole来监控 Java 应用程序性能和跟踪 Java 中的代码

什么是Redis持久化?Redis有哪几种持久化方式?优缺点是什么?

持久化就是把内存的数据写到磁盘中去,防止服务宕机了内存数据丢失。

Redis 提供了两种持久化方式:RDB(默认) 和AOF

  • RDB
    RDB持久性以指定的时间间隔执行数据集的时间点快照。
    优点:
    RDB最大限度地提高了Redis的性能,父进程不需要参与磁盘I/O
    与AOF相比,RDB允许使用大数据集更快地重启
    缺点:
    如果您需要在Redis停止工作时(例如断电后)将数据丢失的可能性降至最低,则RDB并不好
    RDB经常需要fork()才能使用子进程持久存储在磁盘上。如果数据集很大,Fork()可能会非常耗时
  • AOF
    AOF持久性记录服务器接收的每个写入操作,将在服务器启动时再次播放,重建原始数据集。使用与Redis协议本身相同的格式以仅追加方式记录命令。当Redis太大时,Redis能够重写日志背景。
    优点:
    数据更加安全
    当Redis AOF文件太大时,Redis能够在后台自动重写AOF ## INCRE 1 执行10万 = INCREBY10万执行一次
    AOF以易于理解和解析的格式一个接一个地包含所有操作的日志 # flushdb类似于rm -rf /*
    缺点:
    AOF文件通常比同一数据集的等效RDB文件大
    根据确切的fsync策略,AOF可能比RDB慢

在线上我们到底该怎么做?

RDB持久化与AOF持久化同步使用

如果Redis中的数据并不是特别敏感或者可以通过其它方式重写生成数据,可以关闭持久化,如果丢失数据可以通过其它途径补回;

自己制定策略定期检查Redis的情况,然后可以手动触发备份、重写数据;

采用集群和主从同步

使用Redis做异步队列

方式一:生产者消费者模式
使用list结构作为队列,rpush生产消息,lpop消费消息,当lpop没有消息的时候,要适当sleep一会再重试。
或者,不用sleep,直接用blpop指令,在没有消息的时候,它会阻塞住直到消息到来。

方式二:发布订阅者模式
使用pub/sub主题订阅者模式,可以实现1:N的消息队列。

缺点:在消费者下线的情况下,生产的消息会丢失。此场景,建议用MQ。

什么是缓存穿透?如何避免?什么是缓存雪崩?何如避免?

缓存穿透

一般的缓存系统,都是按照key去缓存查询,如果不存在对应的value,就应该去后端系统查找(比如DB)。一些恶意的请求会故意查询不存在的key,请求量很大,就会对后端系统造成很大的压力。这就叫做缓存穿透。

如何避免?

1:对查询结果为空的情况也进行缓存,缓存时间设置短一点,或者该key对应的数据insert了之后清理缓存。

2:对一定不存在的key进行过滤。可以把所有的可能存在的key放到一个大的Bitmap中,查询时通过该bitmap过滤。

缓存雪崩

当缓存服务器重启或者大量缓存集中在某一个时间段失效,这样在失效的时候,会给后端系统带来很大压力。导致系统崩溃。

如何避免?

1:在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

2:做二级缓存,A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置为长期

3:不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

读写锁中如何避免写线程饿死

在读写锁中,当读锁远远多余写锁时,可能出现一直是读锁获取锁,写锁一直阻塞饿死。ReadWriteLock的构造方法支持公平锁。

并发编程中实现生产者消费者模式

简单的方式就是使用内置条件队列wait和notify去阻塞唤醒,还可以使用可重入锁(ReentrantLock),使用锁计数器(CountdownLatch)等

RocketMQ保证消息不丢失

分别从Producer发送机制、Broker的持久化机制,以及消费者的offSet机制来最大程度保证消息不易丢失

  • 从Producer的视角来看:如果消息未能正确的存储在MQ中,或者消费者未能正确的消费到这条消息,都是消息丢失。
  • 从Broker的视角来看:如果消息已经存在Broker里面了,如何保证不会丢失呢(宕机、磁盘崩溃)
  • 从Consumer的视角来看:如果消息已经完成持久化了,但是Consumer取了,但是未消费成功且没有反馈,就是消息丢失

从Producer分析:如何确保消息正确的发送到了Broker?

  • 默认情况下,可以通过同步的方式阻塞式的发送,check SendStatus,状态是OK,表示消息一定成功的投递到了Broker,状态超时或者失败,则会触发默认的2次重试。此方法的发送结果,可能Broker存储成功了,也可能没成功

  • 采取事务消息的投递方式,并不能保证消息100%投递成功到了Broker,但是如果消息发送Ack失败的话,此消息会存储在CommitLog当中,但是对ConsumerQueue是不可见的。可以在日志中查看到这条异常的消息,严格意义上来讲,也并没有完全丢失

  • RocketMQ支持 日志的索引,如果一条消息发送之后超时,也可以通过查询日志的API,来check是否在Broker存储成功

从Broker分析:如果确保接收到的消息不会丢失?

  • 消息支持持久化到Commitlog里面,即使宕机后重启,未消费的消息也是可以加载出来的
  • Broker自身支持同步刷盘、异步刷盘的策略,可以保证接收到的消息一定存储在本地的内存中
  • Broker集群支持 1主N从的策略,支持同步复制和异步复制的方式,同步复制可以保证即使Master 磁盘崩溃,消息仍然不会丢失

从Cunmser分析:如何确保拉取到的消息被成功消费?

  • 消费者可以根据自身的策略批量Pull消息
  • Consumer自身维护一个持久化的offset(对应MessageQueue里面的min offset),标记已经成功消费或者已经成功发回到broker的消息下标
    如果Consumer消费失败,那么它会把这个消息发回给Broker,发回成功后,再更新自己的offset
  • 如果Consumer消费失败,发回给broker时,broker挂掉了,那么Consumer会定时重试这个操作
  • 如果Consumer和broker一起挂了,消息也不会丢失,因为consumer 里面的offset是定时持久化的,重启之后,继续拉取offset之前的消息到本地

什么是一致性Hash算法

一致性Hash算法

MySQL语句的执行顺序

SQL Select 语句完整的执行顺序:
1、from 子句组装来自不同数据源的数据;
2、where 子句基于指定的条件对记录行进行筛选;
3、group by 子句将数据划分为多个分组;
4、使用聚集函数进行计算;
5、使用 having 子句筛选分组;
6、计算所有的表达式;
7、select 的字段;
8、使用 order by 对结果集进行排序。
SQL 语言不同于其他编程语言的最明显特征是处理代码的顺序。在大多数据库语言中,代码按编码顺序被处
理。但在 SQL 语句中,第一个被处理的子句式 FROM,而不是第一出现的 SELECT。SQL 查询处理的步骤序号:
(1) FROM <left_table>
(2) <join_type> JOIN <right_table>
(3) ON <join_condition>
(4) WHERE <where_condition>
(5) GROUP BY <group_by_list>
(6) WITH {CUBE | ROLLUP}
(7) HAVING <having_condition>
(8) SELECT
(9) DISTINCT
(9) ORDER BY <order_by_list>

cookie和session

session和cookie的作用有点类似,都是为了存储用户相关的信息。不同的是,cookie是存储在本地浏览器,而session存储在服务器。存储在服务器的数据会更加的安全,不容易被窃取。但存储在服务器也有一定的弊端,就是会占用服务器的资源,但现在服务器已经发展至今,一些session信息还是绰绰有余的。
cookie和session结合使用
存储在服务端:通过cookie存储一个session_id,然后具体的数据则是保存在session中。如果用户已经登录,则服务器会在cookie中保存一个session_id,下次再次请求的时候,会把该session_id携带上来,服务器根据session_id在session库中获取用户的session数据。就能知道该用户到底是谁,以及之前保存的一些状态信息。这种专业术语叫做server side session。

dubbo服务中zookeeper挂掉了 消费者还可以正常消费吗

启动时 dubbo服务端会从服务端拉取接口信息缓存到本地 调用时直接调用本地缓存的地址,但是由于zk挂掉了 是无法注册新的服务的。

mysql主键和唯一索引的区别

1)主键一定会创建一个唯一索引,但是有唯一索引的列不一定是主键;
2)主键不允许为空值,唯一索引列允许空值;
3)一个表只能有一个主键,但是可以有多个唯一索引;
4)主键可以被其他表引用为外键,唯一索引列不可以;
5)主键是一种约束,而唯一索引是一种索引,是表的冗余数据结构,两者有本质的差别

hashmap为什么不用平衡树,用红黑树

RB-Tree是功能、性能、空间开销的折中结果。
5.1 AVL更平衡,结构上更加直观,时间效能针对读取而言更高;维护稍慢,空间开销较大。
5.2 红黑树,读取略逊于AVL,维护强于AVL,空间开销与AVL类似,内容极多时略优于AVL,维护优于AVL。
基本上主要的几种平衡树看来,红黑树有着良好的稳定性和完整的功能,性能表现也很不错,综合实力强,在诸如STL的场景中需要稳定表现。

红黑树的查询性能略微逊色于AVL树,因为其比AVL树会稍微不平衡最多一层,也就是说红黑树的查询性能只比相同内容的AVL树最多多一次比较,但是,红黑树在插入和删除上优于AVL树,AVL树每次插入删除会进行大量的平衡度计算,而红黑树为了维持红黑性质所做的红黑变换和旋转的开销,相较于AVL树为了维持平衡的开销要小得多

redis单线程为什么快

  1. 完全基于内存,绝大部分请求是纯粹的内存操作,非常快速。因为Redis是基于内存的操作,CPU不是Redis的瓶颈,Redis的瓶颈最有可能是机器内存的大小或者网络带宽。既然单线程容易实现,而且CPU不会成为瓶颈,那就顺理成章地采用单线程的方案了。

  2. 数据结构简单,对数据操作也简单,Redis中的数据结构是专门进行设计的;

  3. 采用单线程,避免了不必要的上下文切换和竞争条件,也不存在多进程或者多线程导致的切换而消耗 CPU,不用去考虑各种锁的问题,不存在加锁释放锁操作,没有因为可能出现死锁而导致的性能消耗;

  4. 使用多路I/O复用模型,非阻塞IO;

  5. 使用底层模型不同,它们之间底层实现方式以及与客户端之间通信的应用协议不一样,Redis直接自己构建了VM 机制 ,因为一般的系统调用系统函数的话,会浪费一定的时间去移动和请求;

以上几点都比较好理解,下边我们针对多路 I/O 复用模型进行简单的探讨:

多路 I/O 复用模型

这里“多路”指的是多个网络连接,“复用”指的是复用同一个线程。采用多路 I/O 复用技术可以让单个线程高效的处理多个连接请求(尽量减少网络 IO 的时间消耗),且 Redis 在内存中操作数据的速度非常快,也就是说内存内的操作不会成为影响Redis性能的瓶颈,主要由以上几点造就了 Redis 具有很高的吞吐量。

Redis数据淘汰策略

Redis 内存数据集大小上升到一定大小的时候,就会施行数据淘汰策略来释放内存。
Redis提供6种数据淘汰策略:

  1. volatile-lru:从已设置过期时间的数据集(server.db[i].expires)中挑选最近最少使用的数据淘汰

  2. volatile-ttl:从已设置过期时间的数据集(server.db[i].expires)中挑选将要过期的数据淘汰

  3. volatile-random:从已设置过期时间的数据集(server.db[i].expires)中任意选择数据淘汰

  4. allkeys-lru:从数据集(server.db[i].dict)中挑选最近最少使用的数据淘汰

  5. allkeys-random:从数据集(server.db[i].dict)中任意选择数据淘汰

  6. no-enviction(驱逐):禁止驱逐数据

你对 Namesrv 的了解?

Name Server 为 producer 和 consumer 提供路由信息

请说说你对 Broker 的了解?

Broker 接收来自生产者的消息,储存以及为消费者拉取消息的请求做好准备。

topic

Topic 是一种消息的逻辑分类,比如说你有订单类的消息,也有库存类的消息,那么就需要进行分类,一个是订单 Topic 存放订单相关的消息,一个是库存 Topic 存储库存相关的消息。

RocketMQ 由哪些角色组成?

生产者(Producer):负责产生消息,生产者向消息服务器发送由业务应用程序系统生成的消息。

消费者(Consumer):负责消费消息,消费者从消息服务器拉取信息并将其输入用户应用程序。

消息服务器(Broker):是消息存储中心,主要作用是接收来自 Producer 的消息并存储, Consumer 从这里取得消息。

名称服务器(NameServer):用来保存 Broker 相关 Topic 等元信息并给 Producer ,提供 Consumer 查找 Broker 信息。

RocketMQ执行流程

1、启动 Namesrv,Namesrv起 来后监听端口,等待 Broker、Producer、Consumer 连上来,相当于一个路由控制中心。

2、Broker 启动,跟所有的 Namesrv 保持长连接,定时发送心跳包。

3、收发消息前,先创建 Topic 。创建 Topic 时,需要指定该 Topic 要存储在 哪些 Broker上。也可以在发送消息时自动创建Topic。

4、Producer 发送消息。

5、Consumer 消费消息。

请说说你对 Producer 的了解?

  1. 获得 Topic-Broker 的映射关系。
    Producer 启动时,也需要指定 Namesrv 的地址,从 Namesrv 集群中选一台建立长连接。
    生产者每 30 秒从 Namesrv 获取 Topic 跟 Broker 的映射关系,更新到本地内存中。然后再跟 Topic 涉及的所有 Broker 建立长连接,每隔 30 秒发一次心跳。

  2. 生产者端的负载均衡。
    生产者发送时,会自动轮询当前所有可发送的broker,一条消息发送成功,下次换另外一个broker发送,以达到消息平均落到所有的broker上。

说说你对 Consumer 的了解?

  1. 获得 Topic-Broker 的映射关系。
    Consumer 启动时需要指定 Namesrv 地址,与其中一个 Namesrv 建立长连接。消费者每隔 30 秒从 Namesrv 获取所有Topic 的最新队列情况,
    Consumer 跟 Broker 是长连接,会每隔 30 秒发心跳信息到Broker .

  2. 消费者端的负载均衡。根据消费者的消费模式不同,负载均衡方式也不同。

消费者消费模式有几种?

消费者消费模式有两种:集群消费和广播消费。

  1. 集群消费
    消费者的一种消费模式。一个 Consumer Group 中的各个 Consumer 实例分摊去消费消息,即一条消息只会投递到一个 Consumer Group 下面的一个实例。

  2. 广播消费
    消费者的一种消费模式。消息将对一 个Consumer Group 下的各个 Consumer 实例都投递一遍。即即使这些 Consumer 属于同一个Consumer Group ,消息也会被 Consumer Group 中的每个 Consumer 都消费一次。

消费者获取消息有几种模式?

消费者获取消息有两种模式:推送模式和拉取模式。

  1. PushConsumer
    推送模式(虽然 RocketMQ 使用的是长轮询)的消费者。消息的能及时被消费。使用非常简单,内部已处理如线程池消费、流控、负载均衡、异常处理等等的各种场景。
    长轮询,就是push + pull 模式结合的方式。

  2. PullConsumer
    拉取模式的消费者。应用主动控制拉取的时机,怎么拉取,怎么消费等。主动权更高。但要自己处理各种场景。

什么是定时消息?如何实现?

定时消息,是指消息发到 Broker 后,不能立刻被 Consumer 消费,要到特定的时间点或者等待特定的时间后才能被消费。

mq消息的丢失、队列的使用策略,为什么要用mq

消息重复:造成消息的重复的根本原因是:网络不可达。只要通过网络交换数据,就无法避免这个问题。保证每条消息都有唯一编号且保证消息处理成功与去重表的日志同时出现

Dubbo是什么?

Dubbo是阿里巴巴开源的基于 Java 的高性能 RPC 分布式服务框架,现已成为 Apache 基金会孵化项目。

什么情况下适用dubbo协议,什么时候适用rmi协议?

Dubbo支持dubbo、rmi、hessian、http、webservice、thrift、redis等多种协议,但是dubbo协议是官网推荐使用的,dubbo 缺省协议是dubbo协议,采用单一长连接和 NIO 异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数远大于服务提供者机器数的情况。反之,Dubbo 缺省协议不适合传送大数据量的服务,比如传文件,传视频等,除非请求量很低。RMI协议采用阻塞式(同步)短连接和 JDK 标准序列化方式。适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。后面会对其他几种协议详细介绍,这里就不赘述了。

Dubbo里面有哪几种节点角色

在这里插入图片描述

Dubbo启动时如果依赖的服务不可用会怎样?

Dubbo 缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止 Spring 初始化完成,默认 check=“true”,可以通过 check=“false” 关闭检查

服务提供者暴露一个服务的详细过程:

如果你仔细观察dubbo的启动日志你会发现,dubbo的provider启动主要是以下几个过程

  1. 首先provider启动时,先把想要提供的服务暴露在本地。

  2. 然后再把服务暴露到远程。

  3. 启动netty服务,建立长连接。

  4. 连接到注册中心zk上。

  5. 然后监控zk上的消费服务。

redis哨兵

哨兵模式是一种特殊的模式,首先Redis提供了哨兵的命令,哨兵是一个独立的进程,作为进程,它会独立运行。其原理是哨兵通过发送命令,等待Redis服务器响应,从而监控运行的多个Redis实例。
在这里插入图片描述
这里的哨兵有两个作用

通过发送命令,让Redis服务器返回监控其运行状态,包括主服务器和从服务器。

当哨兵监测到master宕机,会自动将slave切换成master,然后通过发布订阅模式通知其他的从服务器,修改配置文件,让它们切换主机。

然而一个哨兵进程对Redis服务器进行监控,可能会出现问题,为此,我们可以使用多个哨兵进行监控。各个哨兵之间还会进行监控,这样就形成了多哨兵模式。

hashcode()和equals()

  1. 如果两个对象相同,那么它们的hashCode值一定要相同;

  2. 如果两个对象的hashCode相同,它们并不一定相同(这里说的对象相同指的是用eqauls方法比较。

  3. equals()相等的两个对象,hashcode()一定相等;equals()不相等的两个对象,却并不能证明他们的hashcode()不相等。

用equals比较说明对象相同,但是在HashMap中却以不同的对象存储(没有重写hascode值,两个hascode值,在他看来就是两个对象)。
到底这两个对象相等不相等????
说明必须重写hashCode()的重要性,

mysql大数据量分页如何查

limit s,n 在大数据量的时候很慢。
解决办法:基于索引再排序

语句样式:可用如下方法: SELECT * FROM 表名称 WHERE id_pk > (pageNum*10) ORDER BY id_pk ASC LIMIT M

适应场景: 适用于数据量多的情况(元组数上万),最好ORDER BY后的列对象是主键或唯一索引,使得ORDER BY操作能利用索引被消除但结果集是稳定的

原因:索引扫描,速度会很快。

push和pul

MQ的消费模式分两种:push和pull。

所谓push就是服务端主动推送消息给客户端,而pull则是客户端需要主动到服务端取数据。

push优点:

服务端主动推送给客户端,及时性很高

push缺点:

  1. 当客户端消费能力远低于服务端生产能力,那么一旦服务端推送大量消息到客户端时,就会导致客户端消息堆积,处理缓慢,甚至服务崩溃。(那么如何解决这个问题呢?需要mq提供流控制,也就是依据客户端消费能力做流控。比如rabbitmq设置Qos,限制消费数量。)

  2. 服务端需要维护每次传输状态,以防消息传递失败进行重试。

pull模式优点:

  1. 客户端可以依据自己的消费能力进行消费

  2. 传输失败时不需要重试,反正数据还在服务端。

pull模式缺点:

  1. 主动到服务端拉取消息。这个拉取消息的间隔需要设置好,不太好设置。间隔太短,对服务器请求压力过大。间隔时间过长,那么必然会造成一部分数据的延迟。(也有一些解决方案,间隔时间指数级增长,5ms,10ms,20ms,40ms,80ms。。。然后再回到5ms,一定程度上解决,但是如果在41ms时来了数据,那么到80ms就有40ms左右的时间延迟。另外在腾讯的CMQ里有一套长轮询的解决方案,就是取数据时要是没有数据可消费,不是直接返回而是连接等待,一直有数据来了再返回)

push和pull模式不同适用场景

对于服务端生产消息数据比较大时,而消费端处理比较复杂,消费能力相对较低时,这种情况就适用pull模式。

对于数据实时性要求高的场景,就比较适用与push模式。

rocketMQ保证高可用

在这里插入图片描述

顺序消息

RocketMQ是支持顺序消费的。

但这个顺序,不是全局顺序,只是分区顺序。要全局顺序只能一个分区。
同一条queue里面,RocketMQ的确是能保证FIFO的。那么要做到顺序消息,应该怎么实现呢——把消息确保投递到同一条queue。

rocketmq消息生产端示例代码如下:
在这里插入图片描述
按照这个示例,把订单号取了做了一个取模运算再丢到selector中,selector保证同一个模的都会投递到同一条queue。

即: 相同订单号的—>有相同的模—>有相同的queue。

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页