-
Notifications
You must be signed in to change notification settings - Fork 692
Faq chinese
Metamorphosis在消费端采用pull的模型,consumer主动去broker拉取数据,而不是类似大多数MQ那样由broker主动push数据给消费者。可能很多人担心采用pull模型后,会不会消息的实时性降低了,从发送到消费的整个时间周期拉长了。
实际上,meta中消息的实时性受很多因素影响,不能简单地说实时性一定会降低,主要影响因素如下
- broker上配置的批量force消息的阈值,默认是1000条force一次。这个值越大,则实时性越低。
- 消费者每次抓取的数据大小,这个值越大,则实时性越低,但是吞吐量越高。
- Topic的分区数目对实时性也有较大影响,分区数目越多,则磁盘压力越大,导致消息投递的实时性降低。
- 消费者重试抓取的时间间隔,越长则延迟越严重。
- 消费者抓取数据的线程数
可见,消息实时性在meta里受到很多因素的影响,meta可以让用户自己决定如何在响应性和吞吐量之间做平衡,通过配置来合理设置参数,达到应用方需要的实时性,实际测试,消息消费的延迟可以在几毫秒到几秒之间。
服务器相关参数见服务器管理配置
客户端相关参数见javadoc
不同环境使用不同的zookeeper即可实现隔离,或者使用同一个zookeeper集群,但是设置不同的zkRoot(zk根路径名)也可以实现隔离。
- Meta的所有消息都将写入磁盘,没有区分所谓持久消息和非持久消息,所有消息都是持久的
- 生产者在发送消息的时候,服务端只在将消息写入磁盘的情况下才会返回应答给生产者告知消息写入成功
- 消费者在消费消息后,消息也不会删除,而是按照设定的过期处理策略进行批量处理,与任何消费者无关。消费者可在任何时候进行消费,也就是没有区分持久订阅和非持久订阅,都是持久订阅。
- 写入磁盘的消息,其实是写入os缓冲区,可根据你对数据可靠性的要求设定sync策略。参考《服务端配置管理》
- 单机broker可能因为磁盘损坏等硬件故障永久丢失消息,meta还提供了高可用的HA复制方案,通过将消息复制到多个broker来提高数据可靠性。参考HA复制配置。
消息生产者在发送消息前必须publish要发送的topic,这是为了从zookeeper查找到提供该topic服务的broker。如果你想发送任意的topic类型到broker,你可以这样做:
-
定义一个topic为
*
-
保证
*
的numPartitions
跟[system]模块配置的一致,生产者发送的任意topic都将默认使用[system]配置的分区数,而发送端在发送前选择分区依赖的是*
的分区数,因此需要保证两者相等。 -
消息生产者设置默认topic为
*
,设置的方法是MessageProducer
的setDefaultTopic
方法,但是Message的topic即可为任意topic:producer.setDefaultTopic("*");
切记:不要publish任何要发送消息的topic,否则将进入正常发送流程,导致找不到分区可用。
Broker集群配置非常容易,假设你已经按照如何开始和服务器配置管理配置好并启用了你第一台broker,某一天你发现这个单台broker无法支撑更大的消息量,那么你可能就需要引入更多的broker作为集群来提供服务,你要做的事情很简单:
- 拷贝broker1的配置文件conf/server.ini到新的broker,假设为broker2。
- 修改broker2的server.ini中的brokerId配置,赋一个不同于broker1的brokerId。
- 启动broker2,这样一来broker2将和broker1组成一个服务器集群
- 在这个过程中你不需要重启任何现有的服务,包括生产者、消费者和broker1,他们都将自动感知到新的broker2
可见,配置一个集群唯一要做的就是使用同一份配置文件并定义不同的brokerId即可。
默认服务器会绑定到所有网卡上的IP,但是只会注册一个地址到zookeeper,这个注册地址可以通过server.ini配置文件里的hostName
指定:
hostName = x.x.x.x
不会,因为pusblish内部有做缓存,如果判断是重复publish会立刻返回。
参考HA复制配置
在新增或者删除topic并保存server.ini之后,可以通过下列命令热加载新的配置文件并生效:
bin/metaServer.sh reload
参考meta介绍
删除消息数据,可以简单地删除MetaQ的数据目录,但是如果没有更新zookeeper上的offset(默认消费者信息是保存做zookeeper上),那么消费者将无法消费到新的消息。通常不建议人工删除数据目录,但是做开发的时候可能常常需要手工清理环境,MetaQ支持Broker告诉消费者最新的offset信息并更新,通过加入broker的环境变量(修改env.sh或者env.bat的JVM参数):
-Dmeta.get.tellMaxOffset=true
将启用此功能。默认该选项是关闭的,主要原因是考虑到master-slave配置下,很可能消费者先从master消费,做重新负载均衡后可能从slave消费,因为master的消息可能比slave多(因为复制延迟的存在),那么消费者的offset在master上的会比在slave上的大,从slave消费的时候会被更新offset(缩小),导致消息的重复消费,因此这个选项默认被关闭。
MetaQ并不保证消息不会被重复消费,因此消费端需要自己处理消息重复的问题。通常有这么几种解决方案,都是基于message id的唯一性做去重:
- 内存内维护一个LRU map,保存最近消费的message id,消费成功的消息id放入缓存,每次消费前判断消息id是否在缓存内存在。
- 不使用LRU map,而是使用布隆过滤器。
- 不使用内存内缓存,而是使用集中式缓存,比如memcached,redis等。
从1.4.6开始,我们提供了MessageIdCache
接口用于统一做消息去重,具体见Java客户端高级主题一节。
我只是想消费topic下的部分满足条件的消息,也就是消息过滤,具体见 Java客户端高级主题一节
TODO