win10建设网站,公司建设网站请示,建设大型的企业网站费用,东莞网站建设网对于kafka的架构原理我们先提出几个问题?1.Kafka的topic和分区内部是如何存储的#xff0c;有什么特点#xff1f;2.与传统的消息系统相比,Kafka的消费模型有什么优点?3.Kafka如何实现分布式的数据存储与数据读取?一、Kafka架构图1.kafka名词解释在一套kafka架构中有多个P…对于kafka的架构原理我们先提出几个问题?1.Kafka的topic和分区内部是如何存储的有什么特点2.与传统的消息系统相比,Kafka的消费模型有什么优点?3.Kafka如何实现分布式的数据存储与数据读取?一、Kafka架构图1.kafka名词解释在一套kafka架构中有多个Producer多个Broker,多个Consumer每个Producer可以对应多个Topic每个Consumer只能对应一个ConsumerGroup。整个Kafka架构对应一个ZK集群通过ZK管理集群配置选举Leader以及在consumer group发生变化时进行rebalance。名称解释Broker消息中间件处理节点一个Kafka节点就是一个broker一个或者多个Broker可以组成一个Kafka集群Topic主题Kafka根据topic对消息进行归类发布到Kafka集群的每条消息都需要指定一个topicProducer消息生产者向Broker发送消息的客户端Consumer消息消费者从Broker读取消息的客户端ConsumerGroup每个Consumer属于一个特定的Consumer Group一条消息可以发送到多个不同的Consumer Group但是一个Consumer Group中只能有一个Consumer能够消费该消息Partition物理上的概念一个topic可以分为多个partition每个partition内部是有序的2.Topic和Partition在Kafka中的每一条消息都有一个topic。一般来说在我们应用中产生不同类型的数据都可以设置不同的主题。一个主题一般会有多个消息的订阅者当生产者发布消息到某个主题时订阅了这个主题的消费者都可以接收到生产者写入的新消息。kafka为每个主题维护了分布式的分区(partition)日志文件每个partition在kafka存储层面是append log。任何发布到此partition的消息都会被追加到log文件的尾部在分区中的每条消息都会按照时间顺序分配到一个单调递增的顺序编号也就是我们的offset,offset是一个long型的数字我们通过这个offset可以确定一条在该partition下的唯一消息。在partition下面是保证了有序性但是在topic下面没有保证有序性。在上图中在我们的生产者会决定发送到哪个Partition。1.如果没有Key值则进行轮询发送。2.如果有Key值对Key值进行Hash然后对分区数量取余保证了同一个Key值的会被路由到同一个分区如果想队列的强顺序一致性可以让所有的消息都设置为同一个Key。3.消费模型消息由生产者发送到kafka集群后会被消费者消费。一般来说我们的消费模型有两种:推送模型(psuh)和拉取模型(pull)基于推送模型的消息系统由消息代理记录消费状态。消息代理将消息推送到消费者后标记这条消息为已经被消费但是这种方式无法很好地保证消费的处理语义。比如当我们把已经把消息发送给消费者之后由于消费进程挂掉或者由于网络原因没有收到这条消息如果我们在消费代理将其标记为已消费这个消息就永久丢失了。如果我们利用生产者收到消息后回复这种方法消息代理需要记录消费状态这种不可取。如果采用push消息消费的速率就完全由消费代理控制一旦消费者发生阻塞就会出现问题。Kafka采取拉取模型(poll)由自己控制消费速度以及消费的进度消费者可以按照任意的偏移量进行消费。比如消费者可以消费已经消费过的消息进行重新处理或者消费最近的消息等等。4.网络模型4.1 KafkaClient --单线程Selector单线程模式适用于并发链接数小逻辑简单数据量小。在kafka中consumer和producer都是使用的上面的单线程模式。这种模式不适合kafka的服务端在服务端中请求处理过程比较复杂会造成线程阻塞一旦出现后续请求就会无法处理会造成大量请求超时引起雪崩。而在服务器中应该充分利用多线程来处理执行逻辑。4.2 Kafka--server -- 多线程Selector在kafka服务端采用的是多线程的Selector模型Acceptor运行在一个单独的线程中对于读取操作的线程池中的线程都会在selector注册read事件负责服务端读取请求的逻辑。成功读取后将请求放入message queue共享队列中。然后在写线程池中取出这个请求对其进行逻辑处理即使某个请求线程阻塞了还有后续的县城从消息队列中获取请求并进行处理在写线程中处理完逻辑处理由于注册了OP_WIRTE事件所以还需要对其发送响应。5.高可靠分布式存储模型在Kafka中保证高可靠模型的依靠的是副本机制有了副本机制之后就算机器宕机也不会发生数据丢失。5.1高性能的日志存储kafka一个topic下面的所有消息都是以partition的方式分布式的存储在多个节点上。同时在kafka的机器上每个Partition其实都会对应一个日志目录在目录下面会对应多个日志分段(LogSegment)。LogSegment文件由两部分组成分别为“.index”文件和“.log”文件分别表示为segment索引文件和数据文件。这两个文件的命令规则为partition全局的第一个segment从0开始后续每个segment文件名为上一个segment文件最后一条消息的offset值数值大小为64位20位数字字符长度没有数字用0填充如下假设有1000条消息每个LogSegment大小为100下面展现了900-1000的索引和Log由于kafka消息数据太大如果全部建立索引即占了空间又增加了耗时所以kafka选择了稀疏索引的方式这样的话索引可以直接进入内存加快偏查询速度。简单介绍一下如何读取数据如果我们要读取第911条数据首先第一步找到他是属于哪一段的根据二分法查找到他属于的文件找到0000900.index和00000900.log之后然后去index中去查找 (911-900) 11这个索引或者小于11最近的索引,在这里通过二分法我们找到了索引是[10,1367]然后我们通过这条索引的物理位置1367开始往后找直到找到911条数据。上面讲的是如果要找某个offset的流程但是我们大多数时候并不需要查找某个offset,只需要按照顺序读即可而在顺序读中操作系统会对内存和磁盘之间添加page cahe也就是我们平常见到的预读操作所以我们的顺序读操作时速度很快。但是kafka有个问题如果分区过多那么日志分段也会很多写的时候由于是批量写其实就会变成随机写了随机I/O这个时候对性能影响很大。所以一般来说Kafka不能有太多的partition。针对这一点RocketMQ把所有的日志都写在一个文件里面就能变成顺序写通过一定优化读也能接近于顺序读。可以思考一下:1.为什么需要分区也就是说主题只有一个分区难道不行吗2.日志为什么需要分段5.2副本机制Kafka的副本机制是多个服务端节点对其他节点的主题分区的日志进行复制。当集群中的某个节点出现故障访问故障节点的请求会被转移到其他正常节点(这一过程通常叫Reblance),kafka每个主题的每个分区都有一个主副本以及0个或者多个副本副本保持和主副本的数据同步当主副本出故障时就会被替代。在Kafka中并不是所有的副本都能被拿来替代主副本所以在kafka的leader节点中维护着一个ISR(In sync Replicas)集合翻译过来也叫正在同步中集合在这个集合中的需要满足两个条件:节点必须和ZK保持连接在同步的过程中这个副本不能落后主副本太多另外还有个AR(Assigned Replicas)用来标识副本的全集,OSR用来表示由于落后被剔除的副本集合所以公式如下:ISR leader 没有落后太多的副本; AR OSR ISR;这里先要说下两个名词:HW(高水位)是consumer能够看到的此partition的位置LEO是每个partition的log最后一条Message的位置。HW能保证leader所在的broker失效该消息仍然可以从新选举的leader中获取不会造成消息丢失。当producer向leader发送数据时可以通过request.required.acks参数来设置数据可靠性的级别1(默认)这意味着producer在ISR中的leader已成功收到的数据并得到确认后发送下一条message。如果leader宕机了则会丢失数据。0这意味着producer无需等待来自broker的确认而继续发送下一批消息。这种情况下数据传输效率最高但是数据可靠性确是最低的。-1producer需要等待ISR中的所有follower都确认接收到数据后才算一次发送完成可靠性最高。但是这样也不能保证数据不丢失比如当ISR中只有leader时(其他节点都和zk断开连接或者都没追上)这样就变成了acks1的情况。以上就是我的分享看完的朋友记得点赞噢想学习更多的Java技术方面的知识的朋友们可以进我的Java高级架构师交流群里面有高可用、高并发、高性能及分布式、Jvm性能调优、Spring源码MyBatisNetty,Redis,Kafka,Mysql,Zookeeper,Tomcat,Docker,Dubbo,Nginx等多个知识点的架构资料群号680075317也可以进群一起交流比如遇到技术瓶颈、面试不过的大家一些交流学习