资讯详情

多线程、Redis、rabbitmq面试题

设计模式: 1.简单的工厂模式:根据不同的输入参数,定义实例对象类 2.单例模式:确保一个类只有一个例子,并提供一个公共方法来获取对象的例子 3.原型模式:复制现有实例,创建新对象 4.外观模式:隐藏系统的复杂性,并为客户端提供可访问系统的接口。 5.命令模式:将一个请求包装成一个对象,将发出请求的责任与执行请求的责任分开。这样,两者之间就可以通过命令对象进行沟通,以便于存储、传输、呼叫、增加和管理命令对象。

多线程 1.缓存一致性,解决缓存不一致性; 当程序运行时,从主存复制到 CPU 的高速 缓存,所以 CPU 进行计算时就可以直接从它的高速缓存读取数据和向其中 将数据写入数据将高速缓存中的数据刷新到主存中。

这在单线程中没有问题,但在多线程中会遇到缓存一致性的问题,因为每个线程CPU都有自己的高度缓存,比如主存中有x值,然后每个高速缓存中的值都是x,如果此时y个线程需要x 1, 那么这个时候运行完2,不是结果x y。

缓存不一致的解决办法是缓存一致性协议。缓存一致性协议要求其他方法是在线程改变高度缓存中的共享变量时cpu如果缓存中有这个副本,其他副本将被放置CPU因此,其他变量处于无效状态CPU当需要读取该变量时,会发现该变量无效,然后从主存重读。

2.volatile关键词的作用是什么? 使用 volatile 如果共享变量被强制将修改后的值立即写入主存;volatile修改后,这个新值立即可见于不同的线程。 同时volatile 禁止重新排序关键字指令。

3.内存内存模型; 每个线程都有自己的工作内存(类似于之前的高速缓存)。线程对变量的所有操作都必须在工作内存中进行,而不是直接操作主存,每个线程不能访问其他线程的工作内存。 4.Thread和task的区别; Task和Thread可以创建多线程执行代码,Task线程池(默认)不仅可以创建新的线程,还可以使用,Thread创建新的线程。 5.死、活、饥饿; 死锁是多线程中最糟糕的情况。多线程占用对方资源的锁,等待对方释放锁。此时,如果没有外力干预,这些线程总是处理堵塞的假死状态,形成死锁。 活锁,与死锁相反,死锁是线程不能获得资源,并占用对方的资源,活锁是获得资源,但相互释放不执行。当多线程相互谦逊时,他们主动向其他线程释放资源。缺点:该资源在多线程之间跳动,但无法执行,即活锁。 在多线程执行中存在线程优先级,高优先级线程可以插队并优先执行。因此,如果高优先级线程总是占用低优先级线程的资源,导致低优先级线程无法执行,那就是饥饿。当然,也有饥饿的情况。一条线程总是占用一个资源,导致其他线程无法执行。与死锁不同,饥饿仍然可以在未来一段时间内执行,例如,占用资源的线程执行结束并释放资源。 6.线程和过程 线程是程序运行的基本单位,过程是资源分配的最小单位。在同一过程中,每个线程都有自己的程序计数器、虚拟堆栈和堆栈内存。

7.什么是线程池,线程池的工作原理,使用线程池有什么好处; 一组工作线程由一个线程池管理。默认情况下,创建线程池后,线程池中的线程数为 0.提交任务时 线程池后的处理策略如下: 1)如果此时线程池中的数量小于 corePoolSize(核心池的大小),即 使线程池中的线程处于空闲状态,并创建新的线程来处理添加的任务(也 每个任务都需要创建一个执行任务的线程)。 2).如果此时线程池中的数量大于等于 corePoolSize,但是缓冲队列 workQueue 未满,任务被放入缓冲队列,任务将等待空闲线程 取出执行。 3) 如 果 此 时 线 程 池 中 的 数 量 大 于 等 于 corePoolSize , 缓 冲 队 列 workQueue 满,线程池数量小于 maximumPoolSize(线程池 最大线程数),构建新的线程来处理添加的任务。 4) 如果 此时 线程 池中 的数量 大 于 等 于 corePoolSize, 缓 冲 队列 workQueue 满,线程池中的数量等于 maximumPoolSize,那么通 过 RejectedExecutionHandler 处理此任务的策略(任务拒绝策略)。 也就是说,处理任务的优先级是:核心线程 corePoolSize、任务队列 workQueue、最大线程 maximumPoolSize,如果三者都满了,就用 handler

8.如何解决网站高并发; .HTML 页面静态化 .图片服务器与应用服务器分离 .缓存(用户缓存,cdn缓存,反向代理) .负载均衡(f服务器集群) .消息队列

网络协议 1.三次握手 1.第一次握手:建立连接。客户端发送连接请求报文段,将SYN位置为1,Sequence Number为x;然后,客户端进入SYN_SEND状态,等待服务器确认;

2.第二次握手:服务器收到SYN报文段。接收客户端的服务器SYN报文段,需要这个SYN确认报文段,设置Acknowledgment Number为x 1;同时,你必须发送它SYN请求信息,将SYN位置为1,Sequence Number为y;服务器端将上述所有信息放入报文段(即SYN ACK报文段)中,一并发送给客户端,此时服务器进入SYN_RECV状态;

3.第三次握手:客户端收到服务器SYN ACK报文段。然后将Acknowledgment Number设置为y 发送到服务器ACK报文段发送后,客户端和服务器端进入报文段ESTABLISHED状态,完成TCP三次握手。

2.四次分手 1.第一次分手:设置主机1(客户端或服务器端)Sequence Number和Acknowledgment Number,向主机2发送一个FIN报文段;此时,主机1进入FIN_WAIT_1状态;这意味着主机1没有数据发送给主机2;

2.第二次分手:主机2收到主机1发送的信息FIN报文段,一个一个回到主机ACK报文段,Acknowledgment Number为Sequence Number加1;主机1进入FIN_WAIT_2状态;主机2告诉主机1,我知道;

3.第三次分手:主机2发送给主机1FIN报文段,请求关闭连接,同时主机2进入CLOSE_WAIT状态;

4.第四次分手:主机1收到主机2的发送FIN报文段发送给主机2ACK然后主机1进入报文段,TIME_WAIT状态;主机2收到主机1的ACK报文段后,关闭连接;此时,主机1等待2MSL后来还没有收到回复,证明了Server端子已经正常关闭,好吧,主机1也可以关闭连接。

http 和 socket 两个协议哪个更高效? 创建 Socket 连接时,可指定传输层协议,Socket 它可以支持不同的传输层 议(TCP 或 UDP),当使用 TCP 该协议连接时 Socket 连接就是一个 TCP 连接。 Socket 一旦建立了连接,通信双方可以开始相互发送数据内容,直到连接断开。请注意, 同 HTTP 不同的是 http 只能基于 tcp,socket 不仅能走 tcp,而且还能走 udp,这个是 socket 第一个特点

Redis Redis相比memcached有哪些优势? (1) memcached所有值都是简单的字符串,redis作为替代品,支持更丰富的数据类型 (2) redis的速度比memcached快很多 (3) redis数据可以持久

Redis集群方案应该怎么做?有哪些方案? 1.codis。 目前使用最多的集群方案,基本和twemproxy一致的效果,但它支持它 当节点数量发生变化时,旧节点 数据可以恢复到新的hash节点。 2.redis cluster3.特点是他的分布式算法不一致hash,而是hash以及槽的概念 从节点设置自己的支持节点。详见官方文档介绍。 3.在业务代码层实现,起几个无关紧要的redis例子,在代码层,是的key 进行hash计算,然后对应 redis实例操作数据。 这种方式对hash层代码要求较高,包括节点故障后的替代算法 案例、数据震荡后自动脚本恢复、实例监控等。

Redis在什么情况下,集群方案会导致整个集群不可用? 有A,B,C如果节点B在没有复制模型的情况下失败,整个集群将认为缺乏 5501-11000的槽不可用。

Redis合适的场景有哪些? (1)会话缓存(Session Cache) 最常用的使用Redis会话缓存是场景(session cache)。用Redis与其他存储(如缓存会话)相比 Memcached)优点在于:Redis提供持久性。如果用户的缓存没有严格要求一致性,则维护用户的缓存 购物车信息全部丢失,大多数人都会不高兴,现在,他们还会这样吗? 幸运的是,随着 Redis 近年来的改进,很容易找到如何正确使用Redis缓存会话文件。甚至广泛使用 知名商业平台Magento也提供Redis的插件。 (2)全页缓存(FPC) 除基本会话外token之外,Redis还提供了非常简单的服务FPC平台。回到一致性问题,即使重启Redis实例, 由于磁盘的持久性,用户不会看到页面加载速度的下降,这是一个很大的改进,类似于PHP本地FPC。 再次以Magento为例,Magento为使用提供插件Redis作为全页缓存后端。 此外,对WordPress对于用户,Pantheon有一个很好的插件 wp-redis,这个插件可以帮助你尽快 加载你浏览过的页面的速度 (3)队列 Reids在内存存储引擎领域的一大优点是提供 list 和 set 操作,这使得Redis能作为一个很好的消息队列 平台来使用。Redis作为队列使用的操作,就类似于本地程序语言(如Python)对 list 的 push/pop 操 作。 如果你快速的在Google中搜索“Redis queues”,你马上就能找到大量的开源项目,这些项目的目的就是 利用Redis创建非常好的后端工具,以满足各种队列需求。例如,Celery有一个后台就是使用Redis作为 broker,你可以从这里去查看。 (4)排行榜/计数器 Redis在内存中对数字进行递增或递减的操作实现的非常好。集合(Set)和有序集合(Sorted Set)也 使得我们在执行这些操作的时候变的非常简单,Redis只是正好提供了这两种数据结构。 所以,我们要从排序集合中获取到排名最靠前的10个用户–我们称之为“user_scores”,我们只需要像下 面一样执行即可: 当然,这是假定你是根据你用户的分数做递增的排序。如果你想返回用户及用户的分数,你需要这样执 行: ZRANGE user_scores 0 10 WITHSCORES Agora Games就是一个很好的例子,用Ruby实现的,它的排行榜就是使用Redis来存储数据的,你可以 在这里看到。 (5)发布/订阅 最后(但肯定不是最不重要的)是Redis的发布/订阅功能。发布/订阅的使用场景确实非常多。我已看见 人们在社交网络连接中使用,还可作为基于发布/订阅的脚本触发器,甚至用Redis的发布/订阅功能来建 立聊天系统!

简单说说缓存雪崩及解决方法 缓存雪崩我们可以简单的理解为:由于原有缓存失效,新缓存未到期间 (例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访 问缓存的请求都去查询数据库了,而对数据库CPU和内存造成巨大压力,严重的会造成数据库宕机。从 而形成一系列连锁反应,造成整个系统崩溃。) 解决办法: 大多数系统设计者考虑用加锁( 最多的解决方案)或者队列的方式保证来保证不会有大量的线程对数据 库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。还有一个简单方案就时讲缓 存失效时间分散开。

缓存穿透怎么导致的? 在高并发下查询key不存在的数据,会穿过缓去存查询数据库。导致数据库压力过大而宕机。 解决方法:

  1. 对查询结果为空的情况也进行缓存,缓存时间(ttl)设置短一点,或者该key对应的数据insert了 之后清理缓存。 缺点:缓存太多空值占用了更多的空间
  2. 使用布隆过滤器。在缓存之前在加一层布隆过滤器,在查询的时候先去布隆过滤器查询 key 是否 存在,如果不存在就直接返回,存在再查缓存和DB。 布隆过滤器原理: 当一个元素被加入集合时,将这个元素通过n次Hash函数结果映射成一个数组中的n 个点,把它们置为1。检索时,我们只要看看这些点是不是都是1就(大约)知道集合中有没有它了:如 果这些点有任何一个0,则被检元素一定不在;如果都是1,则被检元素很可能在。总之布隆过滤器是一 个很大二进制的位数组,数组里面只存0和1。

Redis的内存淘汰策略有哪些? Redis的内存淘汰策略是指在Redis的用于缓存的内存不足时,怎么处理需要新写入且需要申请额外空间 的数据。 1、全局的键空间选择性移除 noeviction:当内存不足以容纳新写入数据时,新写入操作会报错。 allkeys-lru:当内存不足以容纳新写入数据时,在键空间中,移除最近最少使用的key。(这个是 最常用的) allkeys-random:当内存不足以容纳新写入数据时,在键空间中,随机移除某个key。 2、设置过期时间的键空间选择性移除 volatile-lru:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,移除最近最少使用 的key。 volatile-random:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,随机移除某 个key。 volatile-ttl:当内存不足以容纳新写入数据时,在设置了过期时间的键空间中,有更早过期时间的 key优先移除。

什么时候需要缓存降级? 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然 需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开 关实现人工降级。 缓存降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物 车、结算)。 在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪 些可降级;比如可以参考日志级别设置预案:

  1. 一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;
  2. 警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级, 并发送告警;
  3. 错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最 大阀值,此时可以根据情况自动降级或者人工降级;
  4. 严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。 服务降级的目的,是为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。因此,对于不重要 的缓存数据,可以采取服务降级策略,例如一个比较常见的做法就是,Redis出现问题,不去数据库查 询,而是直接返回默认值给用户。

如何保证缓存与数据库双写时的数据一致性? 你只要用缓存,就可能会涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问 题,那么你如何解决一致性问题? 一般来说,就是如果你的系统不是严格要求缓存+数据库必须一致性的话,缓存可以稍微的跟数据库偶 尔有不一致的情况,最好不要做这个方案,读请求和写请求串行化,串到一个内存队列里去,这样就可 以保证一定不会出现不一致的情况 串行化之后,就会导致系统的吞吐量会大幅度的降低,用比正常情况下多几倍的机器去支撑线上的一个 请求。 还有一种方式就是可能会暂时产生不一致的情况,但是发生的几率特别小,就是先更新数据库,然后再 删除缓存

消息队列有什么缺点 4.1. 系统可用性降低 本来系统运行好好的,现在你非要加入个消息队列进去,那消息队列挂了,你的系统不是呵呵了。因 此,系统可用性会降低; 4.2. 系统复杂度提高 加入了消息队列,要多考虑很多方面的问题,比如:一致性问题、如何保证消息不被重复消费、如何 保证消息可靠性传输等。因此,需要考虑的东西更多,复杂性增大。 4.3. 一致性问题 A 系统处理完了直接返回成功了,人都以为你这个请求就成功了;但是问题是,要是 BCD 三个系统那 里,BD 两个系统写库成功了,结果 C 系统写库失败了,咋整?你这数据就不一致了。

Rabbitmq一般用在什么场景 (1)服务间异步通信 (2)顺序消费 (3)定时任务 (4)请求削峰

RabbitMQ有几种工作模式 simple模式(即最简单的收发模式) 消息产生消息,将消息放入队列 消息的消费者(consumer) 监听 消息队列,如果队列中有消息,就消费掉,消息被拿走后,自动从队列中 删除(隐患 消息可能没有被消费者正确处理,已经从队列中消失了,造成消息的丢失,这里可以设置成 手动的ack,但如果设置成手动ack,处理完后要及时发送ack消息给队列,否则会造成内存溢出)。

7.2 work工作模式(资源的竞争) 消息产生者将消息放入队列消费者可以有多个,消费者1,消费者2同时监听同一个队列,消息被消费。 C1 C2共同争抢当前的消息队列内容,谁先拿到谁负责消费消息(隐患:高并发情况下,默认会产生某 一个消息被多个消费者共同使用,可以设置一个开关(syncronize) 保证一条消息只能被一个消费者使 用)

publish/subscribe发布订阅(共享资源) 每个消费者监听自己的队列; 生产者将消息发给broker,由交换机将消息转发到绑定此交换机的每个队列,每个绑定交换机的队 列都将接收到消息。

routing路由模式 消息生产者将消息发送给交换机按照路由判断,路由是字符串(info) 当前产生的消息携带路由字符(对 象的方法),交换机根据路由的key,只能匹配上路由key对应的消息队列,对应的消费者才能消费消息; 根据业务功能定义路由字符串 从系统的代码逻辑中获取对应的功能字符串,将消息任务扔到对应的队列中。 业务场景:error 通知;EXCEPTION;错误通知的功能;传统意义的错误通知;客户通知;利用key路由,可 以将程序中的错误封装成消息传入到消息队列中,开发者可以自定义消费者,实时接收错误;

topic 主题模式(路由模式的一种)

  • , # 代表通配符
  • 代表多个单词, # 代表一个单词 路由功能添加模糊匹配 消息产生者产生消息,把消息交给交换机 交换机根据key的规则模糊匹配到对应的队列,由队列的监听消费者接收消息消费

如何保证RabbitMQ消息的顺序性

将原来的一个queue拆分成多个queue,每个queue都有一个自己的consumer。该种方案的核心 是生产者在投递消息的时候根据业务数据关键值(例如订单ID哈希值对订单队列数取模)来将需要 保证先后顺序的同一类数据(同一个订单的数据) 发送到同一个queue当中。 一个queue就一个consumer,在consumer中维护多个内存队列,根据业务数据关键值(例如订 单ID哈希值对内存队列数取模)将消息加入到不同的内存队列中,然后多个真正负责处理消息的线 程去各自对应的内存队列当中获取消息进行消费。

如何保证消息不被重复消费

分析重复消费原因 生产时消息重复 由于生产者发送消息给MQ,在MQ确认的时候出现了网络波动,生产者没有收到确认,实际上MQ 已经接收到了消息。这时候生产者就会重新发送一遍这条消息。生产者中如果消息未被确认,或确 认失败,我们可以使用定时任务+(redis/db)来进行消息重试。 消费时消息重复 消费者消费成功后,再给MQ确认的时候出现了网络波动,MQ没有接收到确认,为了保证消息被 消费,MQ就会继续给消费者投递之前的消息。这时候消费者就接收到了两条一样的消息。 解决方案 让每个消息携带一个全局的唯一ID,即可保证消息的幂等性 消费者获取到消息后先根据id去查询redis/db是否存在该消息。 如果不存在,则正常消费,消费完毕后写入redis/db。 如果存在,则证明消息被消费过,直接丢弃。

、如何确保消息接收方消费了消息? 发送方确认模式 将信道设置成 confirm 模式(发送方确认模式),则所有在信道上发布的消息都会被指派一个唯一 的 ID。 一旦消息被投递到目的队列后,或者消息被写入磁盘后(可持久化的消息),信道会发送一个确认 给生产者(包含消息唯一 ID)。 如果 RabbitMQ 发生内部错误从而导致消息丢失,会发送一条 nack(notacknowledged,未确 认)消息。 发送方确认模式是异步的,生产者应用程序在等待确认的同时,可以继续发送消息。当确认消息到 达生产者应用程序,生产者应用程序的回调方法就会被触发来处理确认消息。 接收方确认机制 消费者接收每一条消息后都必须进行确认(消息接收和消息确认是两个不同操作)。只有消费者确 认了消息,RabbitMQ 才能安全地把消息从队列中删除。 这里并没有用到超时机制,RabbitMQ 仅通过 Consumer 的连接中断来确认是否需要重新发送消 息。也就是说,只要连接不中断,RabbitMQ 给了 Consumer 足够长的时间来处理消息。保证数据 的最终一致性; 下面罗列几种特殊情况 如果消费者接收到消息,在确认之前断开了连接或取消订阅,RabbitMQ 会认为消息没有被分发, 然后重新分发给下一个订阅的消费者。(可能存在消息重复消费的隐患,需要去重) 如果消费者接收到消息却没有确认消息,连接也未断开,则 RabbitMQ 认为该消费者繁忙,将不会 给该消费者分发更多的消息。

如何保证RabbitMQ消息的可靠传输? 题型分析: 消息不可靠的情况可能是消息丢失,劫持等原因; 丢失又分为:生产者丢失消息、消息列表丢失消息、消费者丢失消息; 生产者丢失消息: 从生产者弄丢数据这个角度来看,RabbitMQ提供transaction和confirm模式来确保生产者不丢消 息; 事务机制:发送消息前,开启事务(channel.txSelect()),然后发送消息,如果发送过程中出现什 么异常,事务就会回滚(channel.txRollback()),如果发送成功则提交事务 (channel.txCommit())。然而,这种方式有个缺点:吞吐量下降; confirm模式:一旦channel进入confirm模式,所有在该信道上发布的消息都将会被指派一个唯一 的ID(从1开始),一旦消息被投递到所有匹配的队列之后;rabbitMQ就会发送一个ACK给生产者 (包含消息的唯一ID),这就使得生产者知道消息已经正确到达目的队列了;如果rabbitMQ没能 处理该消息,则会发送一个Nack消息给你,你可以进行重试操作。 消息队列丢数据: 处理消息队列丢数据的情况,一般是开启持久化磁盘的配置。这个持久化配置可以和confirm机制 配合使用,你可以在消息持久化磁盘后,再给生产者发送一个Ack信号。这样,如果消息持久化磁 盘之前,rabbitMQ阵亡了,那么生产者收不到Ack信号,生产者会自动重发。

RabbitMQ 是比较有代表性的,因为是基于主从(非分布式)做高可用性的,我们就以 RabbitMQ 为例子讲解第一种 MQ 的高可用性怎么实现。RabbitMQ 有三种模式:单机模式、普通集群模 式、镜像集群模式。 单机模式,就是 Demo 级别的,一般就是学习时候用的,没人在生产环境使用单机模式 普通集群模式: 意思就是在多台机器上启动多个 RabbitMQ 实例,每个机器启动一个。 你创建的 queue,只会放在一个 RabbitMQ 实例上,但是每个实例都同步 queue 的元数据 (元数据可以认为是 queue 的一些配置信息,通过元数据,可以找到 queue 所在实例)。你 消费的时候,实际上如果连接到了另外一个实例,那么那个实例会从 queue 所在实例上拉取 数据过来。这方案主要是提高吞吐量的,就是说让集群中多个节点来服务某个 queue 的读写 操作。 镜像集群模式: 这种模式,才是所谓的 RabbitMQ 的高可用模式。跟普通集群模式不一样的是,在镜像集群 模式下,你创建的 queue,无论元数据还是 queue 里的消息都会存在于多个实例上,就是 说,每个 RabbitMQ 节点都有这个 queue 的一个完整镜像,包含 queue 的全部数据的意 思。然后每次你写消息到 queue 的时候,都会自动把消息同步到多个实例的 queue 上。 RabbitMQ 有很好的管理控制台,就是在后台新增一个策略,这个策略是镜像集群模式的策 略,指定的时候是可以要求数据同步到所有节点的,也可以要求同步到指定数量的节点,再次 创建 queue 的时候,应用这个策略,就会自动将数据同步到其他的节点上去了。 这样的好处在于,你任何一个机器宕机了,没事儿,其它机器(节点)还包含了这个 queue 的完整数据,别的 consumer 都可以到其它节点上去消费数据。坏处在于,第一,这个性能 开销也太大了吧,消息需要同步到所有机器上,导致网络带宽压力和消耗很重!RabbitMQ 一 个 queue 的数据都是放在一个节点里的,镜像集群下,也是每个节点都放这个 queue 的完整 数据。

如何解决消息队列的延时以及过期失效问题?消息队 列满了以后该怎么处理?有几百万消息持续积压几小时,说 说怎么解决? 线上挺常见的,一般不出,一出就是大 case。一般常见于,举个例子,消费端每次消费之后要写 mysql,结果 mysql 挂了,消费端 hang 那儿了,不动了;或者是消费端出了个什么岔子,导致消 费速度极其慢。 一般这个时候,只能临时紧急扩容了,具体操作步骤和思路如下: 先修复 consumer 的问题,确保其恢复消费速度,然后将现有 consumer 都停掉。 新建一个 topic,partition 是原来的 10 倍,临时建立好原先 10 倍的 queue 数量。 然后写一个临时的分发数据的 consumer 程序,这个程序部署上去消费积压的数据, 消费之后不 做耗时的处理,直接均匀轮询写入临时建立好的 10 倍数量的 queue。 接着临时征用 10 倍的机器来部署 consumer,每一批 consumer 消费一个临时 queue 的数据。这 种做法相当于是临时将 queue 资源和 consumer 资源扩大 10 倍,以正常的 10 倍速度来消费数 据。 等快速消费完积压数据之后, 得恢复原先部署的架构, 重新用原先的 consumer 机器来消费消 息。

消息过期失效了 假设你用的是 RabbitMQ,RabbtiMQ 是可以设置过期时间的,也就是 TTL。如果消息在 queue 中积压 超过一定的时间就会被 RabbitMQ 给清理掉,这个数据就没了。那这就是第二个坑了。这就不是说数据 会大量积压在 mq 里,而是大量的数据会直接搞丢。 这个情况下,就不是说要增加 consumer 消费积压的消息,因为实际上没啥积压,而是丢了大量的消 息。我们可以采取一个方案,就是批量重导,这个我们之前线上也有类似的场景干过。就是大量积压的 时候,我们当时就直接丢弃数据了,然后等过了高峰期以后,比如大家一起喝咖啡熬夜到晚上12点以 后,用户都睡觉了。这个时候我们就开始写程序,将丢失的那批数据,写个临时程序,一点一点的查出 来,然后重新灌入 mq 里面去,把白天丢的数据给他补回来。也只能是这样了。 假设 1 万个订单积压在 mq 里面,没有处理,其中 1000 个订单都丢了,你只能手动写程序把那 1000 个订单给查出来,手动发到 mq 里去再补一次。 都快写满了 如果消息积压在 mq 里,你很长时间都没有处理掉,此时导致 mq 都快写满了,咋办?这个还有别的办 法吗?没有,谁让你第一个方案执行的太慢了,你临时写程序,接入数据来消费,消费一个丢弃一个, 都不要了,快速消费掉所有的消息。然后走第二个方案,到了晚上再补数据吧。

1.MongoDB 分片机制; 2.MongoDB有哪些优势; 3.MongoDB的使用场景;

标签: fpc补强连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台