Bootstrap

理解RocketMQ

目录

概念

1. low latency

2. high perference

3. Reliability

4. trillion-level capacity

5. flexible scalability

架构

四大组成部分

以上四大部分均可以水平扩展,不存在单点的问题

NameServer Cluster

Name Servers提供了轻量级的服务发现与路由功能。每个NameServer记录了全量的路由信息,并提供相应的读写服务,支持快速存储扩容

Broker Cluster

Brokers通过提供轻量级的Topic和Queue机制来管理消息存储。支持推和拉模型,容错机制(2 copys or 3 copys),提供了强大的消锋填谷和累计百亿级顺序消息堆积能力。另外,Brokers还提供了其他传统消息系统中缺少的灾难恢复、丰富的指标统计和告警机制等。

Producer Cluster

Producers支持分布式部署。分布式的生产者通过多种负载均衡方式发送消息至Broker。消息发送处理支持快速失败和低延时。

Consumer Cluster

Consumers支持分布式部署,即支持推模型也支持拉模型。Consumers同样支持集群消费和广播。Consumers提供了实时消息订阅机制且能满足大部分Consumer需求。

Name Server

NameServer是一个完全的基础性服务,提供了两大特性:

1. Broker管理,NameServer接收Broker Cluster的注册请求并提供了心跳监测机制对Broker判活

2. Routing管理,每个NameServer包含了Broker集群的所有路由信息和客户端查询的队列信息。

客户端如何获取NameServer的地址信息?有四种方式:

1. 硬编码:producer.setNamesrvAddr("ip:port”)

2. Java Options:rocketmq.namesrv.addr

3. 环境变量:NAMESRV_ADDR

4. Http endpoint

Programmatic Way > Java Options > Environment Variable > HTTP Endpoint

详情见:http://rocketmq.apache.org/rocketmq/four-methods-to-feed-name-server-address-list/

Broker Server

Broker负责消息存储、发送、查询、HA等,主要包含如下几个模块:

1. Rmoting Module:borker入口,负责处理请求

2. Client Manager:管理客户端(Produer & Consumer)和客户端订阅Topic信息

3. Store Service:提供简易API从物理硬盘存储和查询消息

4. HA Service:提供了主从之间的数据同步特性

5. Index Service:针对消息特定的key构建索引,方便快速查询

部署

Broker

Brokers根据角色划分可以分为两大类:Master & Slave

Master提供读写访问操作而Slave只提供读操作。

为了搭建没有单点故障的高可用Broker集群,需要部署几个Broker集。一个Broker集包含一个Master(brokerId=0)和几个brokerId不重复的slaves(brokerId!=0),一个broker set中的所有broker拥有相同的brokerName。在一些场景中, 一个broker set一般至少包含两个broker。每个Topic至少在两个或两个以上的broker存在。

NameServer

建议至少部署两台NameServer,以确保在一个实例crash后整个集群可以继续提供服务。只要有一台NameServer存活,整个集群即可用。

NameServer遵循各自独立不共享的设计模式。所有Broker发送信息数据到所有NameServer。Producer/Consumer当发送或接收消息的时候可以从任何一个存活的NameServer获取meta data。

##Broker配置

客户端工具CLI Admin Tool

复制模式

1. 为了确保成功发送的消息不丢失,RocketMQ提供了Sync & Async两种复制模式

2. 像很多其他系统一样,sync brokers等待commit log成功复制到slave后再确认。而Async brokers,消息被master处理后立即返回。

最佳实践

##核心概念

生产者发送业务系统产生的消息到brokers。RocketMQ提供了多重发送方式:同步、异步、one-way(比如日志)

相同角色的生产者聚集成组。为了防止原来的生产者crash after transaction,同组下的另一个生产者实例会被broker通知coomit or role back transaction。

注意:一般一个组下一个producer实例已经足够可靠,减少不必要的开销

消费者从brokers获取消息反馈给应用。RocketMQ提供了两种类型的comsumers

1. PullConsumer

2. PushConsumer

封装pulling,消费处理,提供消费接口供Consumer实现处理逻辑

1. 与前面提到的Producer Group概念非常类似,完全相同角色的comsumers聚集成组为Consumer Group

2. Consumer Goup是一个广泛的概念,在消息消费方面,达到负载均衡,容错处理非常简单。

3. 同组下的消费者实例必须拥有完全相同的Topic订阅

Topic是生产者发送消息和消费者拉去消息的范畴。Topics与producers & consumers之间松耦合。可以有0,1或多个producers发送消息到一个Topic;反过来,一个producer发送消息到不同的topics。从消费端开来,一个topic可以被0,1或多个consumer groups。而一个consumer group,类似的可以订阅1或多个topics只要这个consuer group下的实例保持一致的订阅。

Message是被传送的信息。一个message必须包含一个topic(可以理解为邮件发送地址)。一个消息可以包含一个可选择的tag和一些额外的key-value属性。比如,在开发过程中你可以设置一个业务key在你的消息并且在broker上查找消息来定位问题。

Topic被分为1到多个sub-topics,”message queues”

Tag,换句话说sub-topic,为用户提供了额外的弹性。With tag,相同业务模块的不同用途的消息可以拥有相同的topic和不同的tag。Tags对我们代码的整洁性和清晰度是有益的,并且tags可以完善RocketMQ提供的查询机制

Broker是RocketMQ系统的一个重要组件。它接收来自producers发来的消息,存储并处理来自consumers端的拉取请求。Broker也存储了消息关联的meta data,包括consumer groups,consuming progress offsets 以及topic/queue信息。

NameServer作为路由信息提供者服务。Producer/Consumer客户端查询topics找到相应的broker list。

Cluster

Broadcasting

Oderly

Concurrently

Broker Role:Broker分为ASYNCMASTER,SYNCMASTER和SLAVE.如果不能容忍消息丢失,建议m-s-sync模式部署。如果可以接受消息丢失,但希望高可用,建议m-s-async模式部署。如果想简单点,可以as-no-s部署。

FlushDiskType:建议ASYNCFLUSH,因为SYNCFLUSH带来高昂的开销而损失性能。如果期望可靠性高,建议使用m-s-sync。

ReentrantLock VS CAS

os.sh

SendStatus

FLUSHDISKTIMEOUT

FLUSHSLAVETIMEOUT

SLAVENOTAVAILABLE

SEND_OK

Duplication or Missing

消息重试

消息幂等,防止Consumer重复消费

Timeout

缺省超市时间为3秒,可以自定义send(msg, timeout),不建议超时时间太长

Message Size

建议不超过512k,一批不超过1M

Async Sending

Producer Group

在同一个jvm中在一个producer group只能创建一个producer实例,一个就足够了

Thread Safety

Performance

3~5个producers,异步发送

为每个producer设置实例名字

不同Consumer Group可以独自消费相同的topic,并且各自有各自的消费offsets。确保下同Group的Consumer订阅了相同的topics

MessageListener

Orderly

消费者锁定消息队列确保顺序消费。这样会带来性能开销,但如果你关心消息的是有帮助的。不建议抛出异常,可返回SUSPENDCURRENTQUEUEAMoment。

Concurrently

并发访问,高性能。同样不建议抛出异常,建议返回RECOMSUME_LATER。

Consume Status

Blocking

不建议阻塞监听,因为这样会阻塞线程池,甚至停止消费进程

Thread Number

Consumer内部使用线程池处理消费,可以设置setConsumeThreadMin和setConsumeThreadMax

ConsumeFromWhere

CONSUMEFROMLAST_OFFSET

CONSUMEFROMFIRST_OFFSET

CONSUMEFROMTIMESTAMP

Duplication

原因

Producer消息重发

Consumer停止导致一些offsets没有及时更新到Broker

解决方案

幂等

在RocketMQ中,NameServers被设计用来协调分布式系统中的组件,协调工作主要通过管理topic路由信息完成。

两大协调工作

1. Brokers定期同步更新meta data到每个name server

2. NameServers用最新的路由信息服务于producers,consumers和命令行。

JVM Options

Version jdk1.8

-server -Xms8g -Xmx8g -Xmn4g

如果不关心Broker的启动时长,可以设置

-XX:+AlwaysPreTouch

关闭biased locking 减少jvm停顿,可以设置:

-XX:-UseBiasedLocking

Use G1

-XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:G1ReservePercent=25 -XX:InitiatingHeapOccupancyPercent=30

Rolling GC log file

-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=30m

GC log file指向内存文件系统

-Xloggc:/dev/shm/mqgc%p.log

Linux Kernel Parameters

os.sh

vm.extrafreekbytes

RocketMQ使用此值降低内存分配延迟

vm.minfreekbytes

低于1024k,系统容易宕机,在高负载下容易死锁

vm.maxmapcount

RokcetMQ使用mmqp加载CommitLog和ConsumeQueue,建议调高这个参数

vm.swappiness

建议10

File descriptor limits 建议设置为655350

Disk scheduler 建议deadline IO

附录

附录1

Linux磁盘IO调度策略

1. cfq(Complete Fairness Queueing),这是一个复杂的调度策略,按进程创建多个队列,试图保持对多个进程的公平(忽略了读、写操作的不同消耗)

2. deadline,这是一个比较单间的策略,只分了读和写两个队列(加速读取量比较大的系统),内核为每个IO操作设置了一个超时时间

3. noop,这个策略最简单,只有单个队列,只有一些简单合并操作

附录2

文件句柄数(文件描述符)设置

shell级,ulimit –n num

用户级,修改/etc/security/limitis.conf

root soft nofile 65535

root hard nofile 65535

备注:

1、soft数小于等于hard数

2、系统会给出一个建议值/proc/sys/fs/file-max,但是limits.conf设定可以超过建议值

附录3

MMAP VS DMA

MMAP:将磁盘文件映射到内存,通过修改内存就能达到修改磁盘文件的目的。利用操作系统的Page实现文件到物理内存的映射,之后对物理内存的操作会在适当的时候同步到硬盘上。适合大量小数据块高效传输,依赖于cpu,不太适合大数据块传输。

DMA:Direct Memory Access,是一种硬件机制,降低对cpu的依赖,适合大数据块传输。