消息队列有哪些 消息队列( 五 )


kafka集群几乎不需要维护任何consumer和producer状态信息 , 这些信息有zookeeper保存;因此producer和consumer的客户端实现非常轻量级 , 它们可以随意离开 , 而不会对集群造成额外的影响 。
partitions的设计目的有多个 。最根本原因是kafka基于文件存储 。通过分区 , 可以将日志内容分散到多个server上 , 来避免文件尺寸达到单机磁盘的上限 , 每个partiton都会被当前server(kafka实例)保存;可以将一个topic切分多任意多个partitions , 来消息保存/消费的效率 。此外越多的partitions意味着可以容纳更多的consumer , 有效提升并发消费的能力 。(具体原理参见下文) 。
一个Topic的多个partitions , 被分布在kafka集群中的多个server上;每个server(kafka实例)负责partitions中消息的读写操作;此外kafka还可以配置partitions需要备份的个数(replicas) , 每个partition将会被备份到多台机器上 , 以提高可用性 。
基于replicated方案 , 那么就意味着需要对多个备份进行调度;每个partition都有一个server为"leader";leader负责所有的读写操作 , 如果leader失效 , 那么将会有其他follower来接管(成为新的leader);follower只是单调的和leader跟进 , 同步消息即可 。由此可见作为leader的server承载了全部的请求压力 , 因此从集群的整体考虑 , 有多少个partitions就意味着有多少个"leader" , kafka会将"leader"均衡的分散在每个实例上 , 来确保整体的性能稳定 。
Producers
Producer将消息发布到指定的Topic中 , 同时Producer也能决定将此消息归属于哪个partition;比如基于"round-robin"方式或者通过其他的一些算法等 。
Consumers
本质上kafka只支持Topic 。每个consumer属于一个consumer group;反过来说 , 每个group中可以有多个consumer 。发送到Topic的消息 , 只会被订阅此Topic的每个group中的一个consumer消费 。
如果所有的consumer都具有相同的group , 这种情况和queue模式很像;消息将会在consumers之间负载均衡 。
如果所有的consumer都具有不同的group , 那这就是"发布-订阅";消息将会广播给所有的消费者 。
在kafka中 , 一个partition中的消息只会被group中的一个consumer消费;每个group中consumer消息消费互相独立;我们可以认为一个group是一个"订阅"者 , 一个Topic中的每个partions , 只会被一个"订阅者"中的一个consumer消费 , 不过一个consumer可以消费多个partitions中的消息 。kafka只能保证一个partition中的消息被某个consumer消费时 , 消息是顺序的 。事实上 , 从Topic角度来说 , 消息仍不是有序的 。
Kafka的设计原理决定 , 对于一个topic , 同一个group中不能有多于partitions个数的consumer同时消费 , 否则将意味着某些consumer将无法得到消息 。
Guarantees
Kafka就比较适合高吞吐量并且允许少量数据丢失的场景 , 如果非要保证“消息可靠传输” , 可以使用JMS 。
Kafka Producer 消息发送有两种方式(配置参数 producer.type):
对于同步方式(producer.type=sync)?Kafka Producer 消息发送有三种确认方式(配置参数 acks):
kafka的设计初衷是希望作为一个统一的信息收集平台 , 能够实时的收集反馈信息 , 并需要能够支撑较大的数据量 , 且具备良好的容错能力 。
持久性
kafka使用文件存储消息 , 这就直接决定kafka在性能上严重依赖文件系统的本身特性 。且无论任何OS下 , 对文件系统本身的优化几乎没有可能 。文件缓存/直接内存映射等是常用的手段 。因为kafka是对日志文件进行append操作 , 因此磁盘检索的开支是较小的;同时为了减少磁盘写入的次数 , broker会将消息暂时buffer起来 , 当消息的个数(或尺寸)达到一定阀值时 , 再flush到磁盘 , 这样减少了磁盘IO调用的次数 。
性能
需要考虑的影响性能点很多 , 除磁盘IO之外 , 我们还需要考虑网络IO , 这直接关系到kafka的吞吐量问题 。kafka并没有提供太多高超的技巧;对于producer端 , 可以将消息buffer起来 , 当消息的条数达到一定阀值时 , 批量发送给broker;对于consumer端也是一样 , 批量fetch多条消息 。不过消息量的大小可以通过配置文件来指定 。对于kafka broker端 , 似乎有个sendfile系统调用可以潜在的提升网络IO的性能:将文件的数据映射到系统内存中 , socket直接读取相应的内存区域即可 , 而无需进程再次copy和交换 。其实对于producer/consumer/broker三者而言 , CPU的开支应该都不大 , 因此启用消息压缩机制是一个良好的策略;压缩需要消耗少量的CPU资源 , 不过对于kafka而言 , 网络IO更应该需要考虑 。可以将任何在网络上传输的消息都经过压缩 。kafka支持gzip/snappy等多种压缩方式 。

秒懂生活扩展阅读