一切福田,不離方寸,從心而覓,感無不通。

Category Archives: Message Queue

分布式系统事务一致性解决方案

开篇 在 OLTP 系统领域,我们在很多业务场景下都会面临事务一致性方面的需求,例如最经典的 Bob 给 Smith 转账的案例。传统的企业开发,系统往往是以单体应用形式存在的,也没有横跨多个数据库。我们通常只需借助开发平台中特有数据访问技术和框架(例如 Spring、JDBC、ADO.NET),结合关系型数据库自带的事务管理机制来实现事务性的需求。关系型数据库通常具有 ACID 特性:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability)。 而大型互联网平台往往是由一系列分布式系统构成的,开发语言平台和技术栈也相对比较杂,尤其是在 SOA 和微服务架构盛行的今天,一个看起来简单的功能,内部可能需要调用多个“服务”并操作多个数据库或分片来实现,情况往往会复杂很多。单一的技术手段和解决方案,已经无法应对和满足这些复杂的场景了。 分布式系统的特性 对分布式系统有过研究的读者,可能听说过“CAP 定律”、“Base 理论”等,非常巧的是,化学理论中 ACID 是酸、Base 恰好是碱。这里笔者不对这些概念做过多的解释,有兴趣的读者可以查看相关参考资料。CAP 定律如下图: 在分布式系统中,同时满足“CAP 定律”中的“一致性”、“可用性”和“分区容错性”三者是不可能的,这比现实中找对象需同时满足“高、富、帅”或“白、富、美”更加困难。在互联网领域的绝大多数的场景,都需要牺牲强一致性来换取系统的高可用性,系统往往只需要保证“最终一致性”,只要这个最终时间是在用户可以接受的范围内即可。 分布式事务 提到分布式系统,必然要提到分布式事务。要想理解分布式事务,不得不先介绍一下两阶段提交协议。先举个简单但不精准的例子来说明: 第一阶段,张老师作为“协调者”,给小强和小明(参与者、节点)发微信,组织他们俩明天 8 点在学校门口集合,一起去爬山,然后开始等待小强和小明答复。 第二阶段,如果小强和小明都回答没问题,那么大家如约而至。如果小强或者小明其中一人回答说“明天没空,不行”,那么张老师会立即通知小强和小明“爬山活动取消”。 细心的读者会发现,这个过程中可能有很多问题的。如果小强没看手机,那么张老师会一直等着答复,小明可能在家里把爬山装备都准备好了却一直等着张老师确认信息。更严重的是,如果到明天 8 点小强还没有答复,那么就算“超时”了,那小明到底去还是不去集合爬山呢? 这就是两阶段提交协议的弊病,所以后来业界又引入了三阶段提交协议来解决该类问题。 两阶段提交协议在主流开发语言平台,数据库产品中都有广泛应用和实现的,下面来介绍一下 XOpen 组织提供的 DTP 模型图: XA 协议指的是 TM(事务管理器)和 RM(资源管理器)之间的接口。目前主流的关系型数据库产品都是实现了 XA 接口的。JTA(Java Transaction API) 是符合 X/Open DTP 模型的,事务管理器和资源管理器之间也使用了 XA 协议。 本质上也是借助两阶段提交协议来实现分布式事务的,下面分别来看看 XA 事务成功和失败的模型图: 在 JavaEE 平台下,WebLogic、Webshare 等主流商用的应用服务器提供了 JTA 的实现和支持。而在 Tomcat 下是没有实现的(其实笔者并不认为 Tomcat 能算是 JavaEE 应用服务器),这就需要借助第三方的框架Jotm、Automikos 等来实现,两者均支持 spring 事务整合。 而在 Windows .NET 平台中,则可以借助 ado.net 中的TransactionScop API 来编程实现,还必须配置和借助 Windows 操作系统中的 MSDTC 服务。如果你的数据库使用的 mysql,并且 mysql 是部署在 Linux 平台上的,那么是无法支持分布式事务的。 由于篇幅关系,这里不展开,感兴趣的读者可以自行查阅相关资料并实践。 […]

龙生   22 Dec 2018
View Details

RabbitMQ与AMQP协议详解

1. 消息队列的历史 了解一件事情的来龙去脉,将不会对它感到神秘。让我们来看看消息队列(Message Queue)这项技术的发展历史。 Message Queue的需求由来已久,80年代最早在金融交易中,高盛等公司采用Teknekron公司的产品,当时的Message queuing软件叫做:the information bus(TIB)。 TIB被电信和通讯公司采用,路透社收购了Teknekron公司。之后,IBM开发了MQSeries,微软开发了Microsoft Message Queue(MSMQ)。这些商业MQ供应商的问题是厂商锁定,价格高昂。2001年,Java Message queuing试图解决锁定和交互性的问题,但对应用来说反而更加麻烦了。 于是2004年,摩根大通和iMatrix开始着手Advanced Message Queuing Protocol (AMQP)开放标准的开发。2006年,AMQP规范发布。2007年,Rabbit技术公司基于AMQP标准开发的RabbitMQ 1.0 发布。 目前RabbitMQ的最新版本为3.5.7,基于AMQP 0-9-1。 RabbitMQ采用Erlang语言开发。Erlang语言由Ericson设计,专门为开发concurrent和distribution系统的一种语言,在电信领域使用广泛。OTP(Open Telecom Platform)作为Erlang语言的一部分,包含了很多基于Erlang开发的中间件/库/工具,如mnesia/SASL,极大方便了Erlang应用的开发。OTP就类似于Python语言中众多的module,用户借助这些module可以很方便的开发应用。 2. AMQP messaging 中的基本概念 Broker: 接收和分发消息的应用,RabbitMQ Server就是Message Broker。 Virtual host: 出于多租户和安全因素设计的,把AMQP的基本组件划分到一个虚拟的分组中,类似于网络中的namespace概念。当多个不同的用户使用同一个RabbitMQ server提供的服务时,可以划分出多个vhost,每个用户在自己的vhost创建exchange/queue等。 Connection: publisher/consumer和broker之间的TCP连接。断开连接的操作只会在client端进行,Broker不会断开连接,除非出现网络故障或broker服务出现问题。 Channel: 如果每一次访问RabbitMQ都建立一个Connection,在消息量大的时候建立TCP Connection的开销将是巨大的,效率也较低。Channel是在connection内部建立的逻辑连接,如果应用程序支持多线程,通常每个thread创建单独的channel进行通讯,AMQP method包含了channel id帮助客户端和message broker识别channel,所以channel之间是完全隔离的。Channel作为轻量级的Connection极大减少了操作系统建立TCP connection的开销。 Exchange: message到达broker的第一站,根据分发规则,匹配查询表中的routing key,分发消息到queue中去。常用的类型有:direct (point-to-point), topic (publish-subscribe) and fanout (multicast)。 Queue: 消息最终被送到这里等待consumer取走。一个message可以被同时拷贝到多个queue中。 Binding: exchange和queue之间的虚拟连接,binding中可以包含routing key。Binding信息被保存到exchange中的查询表中,用于message的分发依据。 3. 典型的“生产/消费”消息模型 生产者发送消息到broker server(RabbitMQ)。在Broker内部,用户创建Exchange/Queue,通过Binding规则将两者联系在一起。Exchange分发消息,根据类型/binding的不同分发策略有区别。消息最后来到Queue中,等待消费者取走。 4. Exchange类型 Exchange有多种类型,最常用的是Direct/Fanout/Topic三种类型。 Direct Message中的“routing key”如果和Binding中的“binding key”一致, Direct exchange则将message发到对应的queue中。 Fanout 每个发到Fanout类型Exchange的message都会分到所有绑定的queue上去。 Topic 根据routing key,及通配规则,Topic exchange将分发到目标queue中。 Routing key中可以包含两种通配符,类似于正则表达式:

这里也推荐给想要了解RabbitMQ的同学一个网站,http://tryrabbitmq.com ,它提供在线RabbitMQ 模拟器,可以帮助理解Exchange/queue/binding概念。 至此,我们对于消息队列的发展,RabbitMQ的产生,以及AMQP协议中的重要概念做了一个完整的介绍。   from:https://www.cnblogs.com/frankyou/p/5283539.html

龙生   01 Sep 2018
View Details

RabbitMQ使用分析和高可用集群搭建

一、RabbitMQ 基础理解     RabbitMQ,是一个使用 erlang 编写的 AMQP(高级消息队列协议)的服务实现,简单来说,就是一个功能强大的消息队列服务。     概念理解: Producer: 消息发送者 RabbitMQ: Vhost: 相当于分组,每个vhost下数据是隔离的 Exchange: 路由器,接收消息,本根据RoutingKey分发消息 headers:消息头类型 路由器,内部应用 direct:精准匹配类型 路由器 topic:主题匹配类型 路由器,支持正则 模糊匹配 fanout:广播类型 路由器,RoutingKey无效 RoutingKey: 路由规则 Queue: 队列,用于存储消息(消息的目的地) Consumer: 消息消费者 持久化: 一个好的消息队列当然需要消息持久化功能,服务宕机,未消费消息不丢失,RabbitMQ持久化分为Exchange、Queue、Message Exchange 和 Queue 持久化 指持久化Exchange、Queue 元数据,持久化的是自身,服务宕机,Exchange 和 Queue 自身就没有了 Message 持久化 顾名思义 把每一条消息体持久化,服务宕机,消息不丢失 Durable 持久、Transient 临时,Queue新建类似 分析理解: 便于更直观的理解,把 RabbitMQ 的消息流对比与Http Rest接口更家熟悉形象 www.xxx.com/webappPath/trade/getOrder -> getOrder(message) GET RabbitMQ Server:同比 域名 www.xxx.com,只有通过域名才能到达 Server Vhost:同比 /webappPath,一个域名可能指向多个app Exchange:同比 /trade,trade/* 下有多个method,但是需要先到达这个Class RoutingKey:同比 /getOrder,只有完成的 URL 才是有效的,才能确定到具体的方法                  Queue:同比 getOrder(message) 消息的最终目的地 Exchange Type:  同比 GET,但是Rest MethodType是整个URL的Type,而不是 Queue 以上只是为了更好理解,千万不要混淆 Producer / Consumer 就很好理解了,基于AMQP协议链接RabbitMQ Server,发送消息 / 接收消息 二、RabbitMQ 消息确认策略分析 Confrim / Transaction 概念应用 RabbitMQ 提供了两种可靠性的确认策略 Confrim / Transaction,Producer […]

龙生   05 Jul 2018
View Details