谈谈Kafka中CAP定理的实践

如今绝大部分项目,大部分都是采用的分布式系统架构。分布式系统可以防止系统突然宕机导致服务整体不可用,可以从容的应对高并发请求,从而提高系统的可用性。但是如果实现一个分布式系统,经过一段时间的编码和设计,其实会发现并没有这么简单。

相比于单机系统,分布式系统需要多台服务器,而服务器之间的通信是需要绝对保障的;如果通信超时,会影响项目的正常运行;如果是分布式存储系统(不仅仅是),写入的数据也需要被同步到多台服务器上,数据更新肯定是有一定的延迟的,怎么权衡延迟时间和数据实时性的要求更需要被考虑;如果是Leader服务器宕机了,follower服务器需要立刻自动切换角色,提供服务,且要保证数据一致性等等,这些都是在分布式系统设计中需要被面对的问题。

有没有一个架构或框架,能够解决在分布式系统中面临的问题?答案是没有。这个问题起源于加州大学柏克莱分校(University of California, Berkeley)的计算机科学家埃里克·布鲁尔(Eric Brewer),在2000年的分布式计算原理研讨会(PODC)上提出的猜想。但在2002年,麻省理工学院的赛斯·吉尔伯特和南希·林奇证明了布鲁尔的猜想,使之成为一个定理,这个就是CAP定理(CAP theorem),也被称作布鲁尔定理(Brewer’s theorem)。

Kafka是一个典型的分布式系统,涉及到数据存储和数据传递(通信),Kafka在设计和开发的过程中,是怎么合理的解决分布式系统普遍面临的这些问题的呢?那么今天的这篇文章,来谈谈CAP理论在Kafka中的实践。

Kafka日志消息解析

我们知道,写入kafka的消息都需要指定一个Topic(主题),Kafka可以根据Topic来对消息进行区分,每个Topic分为多个Partition(分区)。

Partition的概念是为了实现高伸缩性和提供负载均衡的作用,可以很好的让一个比较大的(数据量级)Topic中的消息可以分布到多台broker机器上。不仅如此,也可以提高并行能力,因为水平扩展后可以以Partition为粒度进行读写,这样每个broker节点都能独立执行各自分区的读写请求;

Partition下就是Log的消息体,每条消息都只会保存在某一个分区中,而且在每个Partition下消息都是append模式写入的,也就是说,每个Partition下的消息都是顺序性的。

Kafka消息设计方式就是这样的三层结构:主题-分区-消息;说到设计,不同的分布式系统对分区的叫法也不大一样,在Kafka中的概念是Partition(分区),在ES中叫做Shard(分片),而在HBase中被称为Region。从表面上来看实现原理可能不尽相同,但对底层实现的思想却都是一致的。

话题扯回来,今天这篇文章分享的主题是:Kafka消息格式。

Kafka无消息丢失配置

今天这篇文章分享的主题是:Kafka无消息丢失配置,以及分析一些常见的消息丢失案例。

在这之前,我们需要清楚,Kafka丢失消息的几种场景。比如:producer生产者把消息写入topic中,broker端并没有接收到,消息在去的路上丢失了;broker端接收到了消息,但是consumer并没有消费到这条数据,消息在broker端丢失了;broker端接收到了消息,但是consumer消费者并没有消费到,消息在来的路上丢失了。

这几种场景其实就是Kafka架构决定的。

Kafka为什么快

今天这篇文章分享的主题是:Kafka为什么速度这么快?

快是基于比较得出来的,相对与其它消息队列或消息引擎,在很多讲解Kafka的文章都会提到这一点:Kafka可以很轻松的支持每秒百万级的TPS请求,其实在实际的基准测试中,每秒写入速率高达两百万,这远远高于其它消息队列的测试数据,Kafka在大数据消息队列组件中也是不二之选,并且绝大多数的大数据计算组件都与kafka进行集成。

但实际生产中的性能数据会受很多参数和环境的影响,比如acks设置:在保证数据不丢失的情况下,设置acks=all,吞吐量会明显降低;replication副本数量:副本数越多,吞吐量越低;batch大小:batch-size大小达到阈值时,会达到吞吐量峰值,超过阈值后,并不会提升性能;和压缩设置等等因素都可以影响Kafka吞吐量。

我们知道,Kafka的消息是保存或缓存在磁盘上的,一般认为在磁盘上读写是相对而言是较慢的,因为磁盘寻址是相对需要消耗大量的时间,那为什么Kafka速度还是这么快?我们得从Kafka写入为什么这么快Kafka消费为什么这么快两方面,深入解析下Kafka主要的技术原理。

SparkStreaming之解析mapWithState

最近经历挫折教育,今天闲得时间,整理状态管理之解析mapWithState。今天说道的mapWithState是从Spark1.6开始引入的一种新的状态管理机制,支持输出全量的状态和更新的状态,支持对状态超时的管理,和自主选择需要的输出。

SparkStreaming之解析updateStateByKey

说到Spark Streaming的状态管理,就会想到updateStateByKey,还有mapWithState。今天整理了一下,着重了解一下前者。

状态管理的需求

举一个最简单的需求例子来解释状态(state)管理,现在有这样的一个需求:计算从数据流开始到目前为止单词出现的次数。是不是看起来很眼熟,这其实就是一个升级版的wordcount,只不过需要在每个batchInterval计算当前batch的单词计数,然后对各个批次的计数进行累加。每一个批次的累积的计数就是当前的一个状态值。我们需要把这个状态保存下来,和后面批次单词的计数结果来进行计算,这样我们就能不断的在历史的基础上进行次数的更新。

SparkStreaming提供了两种方法来解决这个问题:updateStateByKey和mapWithState。mapWithState是1.6版本新增的功能,官方说性能较updateStateByKey提升10倍。