聊一聊Kafka分区的隐藏属性——二次归类

在使用Kafka的过程当中,分区是一个不可忽视的概念。不少时候你会带着这样的疑问:Kafka的分区该怎么划分?按什么划分?分多少个?撰稿之时,我在《深刻理解Kafka》一书中搜索了一下“分区”这个词,结果发现出现的频率至少有4位数之多。Kafka中分区的概念涉猎不少,好比:分区分配、分区重分配、失效分区等。在本公众号里也发表过几篇文章来说述Kafka分区中的某些知识点:算法

本文并不延续讲解这些内容,而是要剑走偏锋,聊一聊Kafka分区被你们所忽视的一个隐藏属性——消息的归类。微信

在Kafka中主题和分区是两个很是重要的概念。Kafka中的消息向来以“主题”来进行归类(划分),一个主题能够包含若干个分区,一个分区只属于单个主题。同一主题下的不一样分区所包含的消息不一样的(若是须要数据冗余,那么涉及到的是Kafka的多副本机制,这里不展开论述)。对于单个分区而言,消息是顺序追加的,也所以为Kafka提供了分区内的顺序特性,这一点在RabbitMQ不是太好保证(其实RabbitMQ也不是不能够,就是有点麻烦)。性能

使用分区最主要的做用仍是提升可扩展性。若是一个主题只有一个分区,那么全部的数据读写都通过这一个分区的话势必会形成性能瓶颈。固然,若是规定主题只能有一个分区的话,那么分区这个概念就能够去除掉了。若是主题有多个分区,那么能够将这种读写的压力分散开来。主题中的多个分区不必定要在同一个broker上,彻底能够分布在多个broker上,特殊状况下还能够一个分区一个broker。设计

“消息的归类”并非不是主题所独有的特性,其实分区也能够,分区能够看作是消息的二次归类,让分区变得有意义。举个例子,咱们建立了一个主题用来存储人员信息,这我的员信息就是对数据的一种归类。因为人员众多,咱们想着是要用多个分区来分摊一下读写压力,那么咱们能够依据什么来划分呢?第一种,按照生肖,这样就能够建立12个分区,分区编号从0开始分别表明鼠、牛、虎、兔、牛等等,这样的分区规则就是对人员信息的二次归类。第二种,咱们估算12个分区的压力也有点顶不住,那么咱们能够按照姓名拼音的首字母来划分,这也是二次归类。3d

在实际实践时能够将消息(ProducerRecord<生肖,人员信息>)对应的key设置为与其对应分区的“归类类别”便可。好比,按生肖分,那么“属牛的肥朝”能够这一条消息(人员信息)能够表示为:key=“牛”,value=“姓名:肥朝,特长:帅”。cdn

聪明的同窗还会接着想到用姓氏来归类。。也不是不可行,中国百家姓(其实何止)。可是要考虑到一种状况就是数据倾斜,“赵钱孙李”所对应的分区确定比“令狐”、“独孤”、“上官”之类的分区所承担的数据负载要多不少,这样严重的数据倾斜会致使服务总体效能的下降。“赵钱孙李”能够视为热点数据,而“令狐”、“独孤”、“上官”能够视为冷数据,咱们能够这样划分,参考下图: blog

在这里插入图片描述
对于大姓来讲能够独占一个分区,而对于中等姓氏来讲能够合用一个分区,而对于生僻姓氏来讲能够共用一个分区。

在某些时候,按照字面的类别划分也很难避免数据倾斜。沿用上面的例子,宋朝时期,姓赵的人实在太多,划分到一个分区仍是会有严重的数据倾斜,那么就须要对这一姓氏作多一些处理,多化几个分区给它。token

举这些例子是为了说明:若是要让分区得到“二次归类”的特性,就须要作好“二次归类”的准备,也就是须要应对数据热点问题。为了尽量的数据分布均匀而弱化热点问题应该根据归类的特性作好合理的规划。图片

在Kafka中建立消息的时候,若是不指定分区,那么就会根据消息的key来进行计算。get

若是key不为null,那么默认的分区器会对key进行哈希(采用MurmurHash2算法,具有高运算性能及低碰撞率),最终根据获得的哈希值来计算分区号,拥有相同key的消息会被写入同一个分区。若是key为null,那么消息将会以轮询的方式发往主题内的各个可用分区。前者根据key进行计算,潜在的使用了“二次归类”这个特性,后者采用轮询的方式,潜在的丢弃了“二次归类”的特性。

固然,咱们还能够自定义Kafka中的分区器来实现随机的分类,这个实现很简单,从[0,分区数)中挑选一个整数而已,如此也一样会丢弃“二次归类”的特性。

关于分区的这个属性,你还有什么须要补充的吗?不妨在留言去留言来一块儿探讨。


欢迎支持笔者小册:《图解Kafka之实战指南》和《图解Kafka之核心原理


欢迎支持笔者新做:《深刻理解Kafka:核心设计与实践原理》和《RabbitMQ实战指南》,同时欢迎关注笔者的微信公众号:朱小厮的博客。

相关文章
相关标签/搜索