工作中用了一段时间的Kafka,但主要是RabbitMQ用的比较多。今天主要讲一下RabbitMQ相关的一些知识。一些基本概念,以及实际使用场景和一些注意事项。1基本概念RabbitMQ是使用Erlang开发的,它实现了高级消息队列协议(AMQP),同时也支持MQTT、STOMP等。1.1核心概念Broker:消息队列服务宿主Exchange:消息交换机,可以将消息路由到特定的队列根据具体规则(上图中X为开关)Queue:消息队列,每条消息论必须放入一个或多个Queue(上图中红色矩形为队列)Binding:绑定关系,绑定Exchange和按照一定的路由规则排队RoutingKey:路由关键字,Exchange根据Key进行不同的路由Vhost:虚拟主机,在同一个物理资源主机上做逻辑隔离,类似于命名空间?Connection:客户端和宿主机之间建立的TCP连接Channel:消息通道,同一个Connection可以有多个Channel,每个Channel都有唯一的ID1.2开关有四种:DirectExchange,TopicExchange,FanoutExchange,HeadersExchange1.2.1DirectExchange直接交换,在没有复杂路由场景的时候,这种路由器用的比较多。特点是严格的RoutingKey路由。只有当RoutingKey完全相同时,路由才会在今天下发。1.2.2FanoutExchange广播开关,当一条消息需要不加区别地投递到所有绑定的队列时。无需设置RoutingKey,即使设置了也不会生效。1.2.3TopicExchange话题交换,类似于直接交换。不同的是可以根据RoutingKey进行模糊匹配(#表示一个或多个词,*表示一个词)。如果你这样看的话。当不使用#或*进行模糊匹配时,似乎与DirectExchange没有区别。只用#做模糊匹配的时候,好像和FanoutExchange没什么区别。可以看出:Q1可以匹配:x11.orange.x22,但是不能匹配x00.x11.orange.x22。Q2可以匹配:lazy.orange和lazy.orange.rabbit。1.2.4HeadersExchange请求头交换不使用RoutingKey路由,根据消息头中的key-value属性进行路由。或者,可以通过设置x-match:any,x-match:all来进行逻辑匹配。1.2.5其他性能Durability:Durable(耐用),Transiant(短)。自动删除:当一个队列或交换机与该交换机绑定时,该队列或交换机解除绑定后,将被自动删除。internal:是否供内部使用。true表示内部交换,客户端不能直接向其发送消息。参数:alternate-exchange:backupexchange,当消息不能路由到特定队列时,会交给backupexchange处理。1.3队列消息只能存在于队列中。我们来看看队列的属性。Type:Classic,QuorumDurability:Durable(持久),Transiant(短暂)Autodelete:当一个消费者订阅,然后所有消费者都断开连接时,自动删除Arguments:x-message-ttl:MessageinQueue中的生存时间,超时将被丢弃x-expires:Queue未被使用,过期时间x-max-length:Queue中可存储的最大消息数,超过x-max-length-bytes将被丢弃:最大消息体大小可以存入Queue,超过x-overflow将被丢弃:Queue溢出后的行为,drop-head,reject-publish,reject-publish-dlx。x-single-active-consumer:保证只有一个consumer订阅,异常时自动切换到另一个consumer。x-max-priority:队列支持的最大优先级,不设置则不支持。x-dead-letter-exchange:当Message被拒绝或过期时,会重新发布到哪个exchange。x-dead-letter-routing-key:当变成死信时,使用的RoutingKey,如果不设置,则使用原来的Key。x-queue-mode:设置为lazy时,消息会尽可能放在磁盘上,减少内存占用。x-queue-master-locator:设置队列为主定位器模式。2应用场景应用场景一般分为三类:异步、解耦、削峰填谷。2.1异步异步泛指:在同一个系统中,在不阻塞主线程的情况下,使用队列将请求和响应异步化,从而获得更高的处理速度,提高系统性能。我第一次从事购物中心项目。用户下单付款后,先更新本地订单记录,然后将待发货消息推送到第三方物流系统,将订单相关内信发送给用户,并可能触发积分赠送和推荐人返利2.2解耦解耦一般是指:不同的系统通过队列进行通信,使系统之间不会过度依赖,降低系统之间的耦合度。在最近的一个项目中,有一个事件上报系统,它实际上连接了所有系统。每个系统都可以是生产者或消费者。例如,用户下单后需要给推荐人积分,将商机的订单状态与外部CRM同步。2.3削峰填谷一般来说,削峰填谷是指:用队列作为缓冲区缓存短期大流量,让消费者决定处理速度。使系统负载趋于稳定,从而提高系统稳定性。在用户增长业务方面,用户从落地页向内部系统提交数据,内部系统将数据简单处理后推送至外部CRM系统。与客户沟通后,销售会将线索转化为商机。在此转换过程中,CRM会将数据推送到内部系统。内部系统会根据传入的数据进行各种操作,比如创建和更新家长,创建和更新学生,以及各种附加的业务信息。3常见问题3.1消息重复问题消息重复的场景有很多,比如系统错误、调用超时重试机制、消息消费异常时的ReQueue操作等,很多时候为了保证消息的可靠传递,消息将被保证至少一次。在这种情况下,基本无法保证不重复发送,所以消费者必须保证幂等性。既然提到了可重复性,那么就一定要有重复的基础。例如,订单号在同一个系统中不允许重复。可以使用数据库的唯一索引,也可以使用Redis来保证数据的唯一性。如果没有重复的依据,只能根据参数值按照一定的规则进行hash处理,但可能会出现误判、漏判的问题。3.2信息积累消费的积累无非就是消费的速度跟不上生产的速度。造成这种情况的原因有很多,比如消费者异常消费变慢,生产者流量突然变大等,解决方案要同时考虑生产者和消费者。当发生积累时,一些生产者将被降级,非核心业务将被关闭,消息生成将减少。消费者优化性能,将累积的消息暂时转移到新的队列中,并启用新的消费者进行消费。3.3从全流程考虑消息丢失的问题,包括生产者、队列、消费者。Producer:保证消息成功推送到队列中。队列:保证推送到队列的数据不会丢失。Consumer:保证消费的数据被正确处理。4后记系统设计没有灵丹妙药。在引入一个中间件的时候,需要综合考虑,权衡利弊。中间件的引入可以解决一些问题,但可能会带来更多的问题。做好系统监控。消费积累等一些场景是可以预见的,比如临时事件或低价促销导致的订单激增。而有些,比如系统故障,是无法提前预知的,需要监控系统及时报警,提前介入。回声'5Y6f5Yib5paH56ugOiDmjpjph5Eo5L2g5oCO5LmI5Zad5aW26Iy25ZWKWzkyMzI0NTQ5NzU1NTA4MF0pL+aAneWQpihscGUyMzQp'|base64-d
