[实习篇]kafka以及向talos的转移,druid数据库(持续更新)

1. Kafka

首先要先明白kafka是什么要先了解一下中间件的概念。
中间件
中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提供的基础服务(功能),衔接网络上应用系统的各个部分或不同的应用,能够达到资源共享、功能共享的目的。目前,它并没有很严格的定义,但是普遍接受IDC的定义:中间件是一种独立的系统软件服务程序,分布式应用软件借助这种软件在不同的技术之间共享资源,中间件位于客户机服务器的操作系统之上,管理计算资源和网络通信。从这个意义上可以用一个等式来表示中间件:中间件=平台+通信,这也就限定了只有用于分布式系统中才能叫中间件,同时也把它与支撑软件和实用软件区分开来。(摘自百度百科)

对应于Kafka,他作为中间件主要起到的是缓存消息,缓解过载的情况。具体分析看下面图
(图片摘自知乎kafka解决了什么问题?张琪大神的回答)
在这里插入图片描述
首先,最简单的信息处理模式就是用户端将消息或者请求发送到应用(这里其实可以是各种应用,可以部署于云端以及其他地方)。然后应用进行信息或者请求的处理,做数据库访问或是其他操作。但是如果数据量变大,用户基数变大,需要的操作几何倍增长,就会出现很多情况,因此上图细化会变成如下
在这里插入图片描述
用户将消息或是请求发送到app,所有的访问都直接通过SQL数据库使得它不堪重负,不得不加上缓存服务以降低SQL数据库的荷载;为了理解用户行为,开始收集日志并保存到Hadoop上离线处理,同时把日志放在全文检索系统中以便快速定位问题;由于需要给投资方看业务状况,也需要把数据汇总到数据仓库中以便提供交互式报表。(张琪大佬原话)
看图上其实所有操作都有对应的两两操作,因此复杂度是O(n2)。

而这时候Kafka出马了。Kafka是一个分布式,可划分的,冗余备份的持久性的日志服务,它主要用于处理流式数据。他的功能是作为一个缓存式的消息队列。当上游数据时有突发流量,下游可能扛不住,或者下游没有足够多的机器来保证冗余,kafka在中间可以起到一个缓冲的作用,把消息暂存在kafka中,下游服务就可以按照自己的节奏进行慢慢处理。
同时除了缓存和削峰这个功能,他还有以下的特点:
解耦和扩展性:项目开始的时候,并不能确定具体需求。消息队列可以作为一个接口层,解耦重要的业务流程。只需要遵守约定,针对数据编程即可获取扩展能力。
冗余:可以采用一对多的方式,一个生产者发布消息,可以被多个订阅topic的服务消费到,供多个毫无关联的业务使用。
健壮性:消息队列可以堆积请求,所以消费端业务即使短时间死掉,也不会影响主要业务的正常进行。
异步通信:很多时候,用户不想也不需要立即处理消息。消息队列提供了异步处理机制,允许用户把一个消息放入队列,但并不立即处理它。想向队列中放入多少消息就放多少,然后在需要的时候再去处理它们。
简述图

Kafka核心概念和角色Broker:Kafka集群包含一个或多个服务器,每个服务器被称为broker。
Topic:每条发布到Kafka集群的消息都有一个分类,这个类别被称为Topic(主题)。
Producer:指消息的生产者,负责发布消息到kafka broker。
Consumer:指消息的消费者,从kafka broker拉取数据,并消费这些已发布的消息。
Partition:Partition是物理上的概念,每个Topic包含一个或多个Partition,每个partition都是一个有序的
队列。partition中的每条消息都会被分配一个有序的id(offset)。
Consumer Group:消费者组,可以给每个Consumer指定消费组,若不指定消费者组,则属于默认的group。
Message:消息,通信的基本单位,每个producer可以向一个topic发布一些消息。

在这里插入图片描述
更详细的kafka设置如图所示,对应于kafka queue,里面的每一个列其实就是一个broker。这里面topic分布不是很对,详情参考下面。
还有在这里提一嘴:一开始我以为kafka是很传统的消息队列,所有消息放在一个队列里,就是最上面的Kafka简述图。但是其实不是的。早期消息处理引擎就是按照队列模型设计的,所谓队列模型,跟队列数据结构类似,生产者产生消息,就是入队,消费者接收消息就是出队,并删除队列中数据,消息只能被消费一次。但这种模型有一个问题,那就是只能由一个消费者消费,无法直接让多个消费者消费数据。基于这个缺陷,后面又演化出发布-订阅模型。
发布-订阅模型:发布订阅模型中,多了一个主题。消费者会预先订阅主题,生产者写入消息到主题中,只有订阅了该主题的消费者才能获取到消息。这样一来就可以让多个消费者消费数据。 一般来说消费者组内的所有成员一起订阅某个主题的所有分区,注意一个消费者组中,每一个分区只能由组内的一消费者订阅。

Kafka好处很多,坏处就是经费开销大,因此公司自己生产了talos并且在做业务过度,这也是我实习的主要工作。

Kafka内部还有副本的概念。Kafka broker的归属会通过从zookeeper里的配置查询是否属于同一个cluster。同时producer会创建多个topic,而每个topic内部会有多个partition。除此之位 还会定义一个副本数量,副本的数量是指每个partition有多少个一模一样的复制。比如副本=3,那么就是一个partition有三个实例。
下图情况topic=1, replica=3, broker=5。分布的算法一般是随机选择一个数(0≤ random ≤ broker-1),从random开始,再选一个随机变量nextReplicaShift,根据这个参数放下一个replica。这样可以保证均衡分布。最上面的架构图其实有点不太正确
在这里插入图片描述
但是消费者并不会对每个partition以及它们的replica进行消费。partition和replica之中其实也存在leader和follower。每个 Partition 可以有多个副本,这多个副本之中,只有一个是 leader,其他都是 follower,所有的读写请求都通过 leader 来完成,follower 只负责备份数据。follow 会均匀分配到多个 Broker 上,当 leader 所在的机器挂掉之后,会从 follower 中重新选出一个副本作为 leader 继续提供服务。

那么为什么有这么多的副本却只使用 leader 来提供服务呢?如果都用上不是可以提高性能吗?这其实就是一致性和可用性之间的取舍了,如果多个副本同时进行读写操作,很容易出现问题。例如在读取消息时,一个消费者没有读取到,而另一个消费者却读取到了,因为这个消费者读取的是 leader 副本,显然这样是不行的。所以为了保证一致性,只使用一个 leader 副本来提供服务。

注意一个partition可以对应多个非同组的consumer(换句话说就是一个consumer group里有且只能有一个consumer消费同一个partition。),一个consumer可以同时消费多个partition。如果分区数大于或者等于组中的消费者实例数,那自然没有什么问题,无非一个消费者会负责多个分区,(PS:当然,最理想的情况是二者数量相等,这样就相当于一个消费者负责一个分区);但是,如果消费者实例的数量大于分区数,那么按照默认的策略(PS:之所以强调默认策略是因为你也可以自定义策略),有一些消费者是多余的,一直接不到消息而处于空闲状态。

Zookeeper

官方文档上这么解释zookeeper,它是一个分布式服务框架,是Apache Hadoop 的一个子项目,它主要是用来解决分布式应用中经常遇到的一些数据管理问题,如:统一命名服务、状态同步服务、集群管理、分布式应用配置项的管理等。简单来说zookeeper=文件系统+监听通知机制。

Zookeeper不是严格意义上的Kafka的组件,它是一个独立于Kafka的中间件。Kafka通过Zookeeper管理集群配置,选举leader,以及在Consumer Group发生变化时进行rebalance。
Kakfa Broker Leader的选举: Kakfa Broker集群受Zookeeper管理。所有的Kafka Broker节点一起去Zookeeper上注册一个临时节点,因为只有一个Kafka Broker会注册成功,其他的都会失败,所以这个成功在Zookeeper上注册临时节点的这个Kafka Broker会成为Kafka Broker Controller,其他的Kafka broker叫Kafka Broker follower。(这个过程叫Controller在ZooKeeper注册Watch)。这个Controller会监听其他的Kafka Broker的所有信息,如果这个kafka broker controller宕机了,在zookeeper上面的那个临时节点就会消失,此时所有的kafka broker又会一起去 Zookeeper上注册一个临时节点,因为只有一个Kafka Broker会注册成功,其他的都会失败,所以这个成功在Zookeeper上注册临时节点的这个Kafka Broker会成为Kafka Broker Controller,其他的Kafka broker叫Kafka Broker follower 。例如:一旦有一个broker宕机了,这个kafka broker controller会读取该宕机broker上所有的partition在zookeeper上的状态,并选取ISR列表中的一个replica作为partition leader(如果ISR列表中的replica全挂,选一个幸存的replica作为leader; 如果该partition的所有的replica都宕机了,则将新的leader设置为-1,等待恢复,等待ISR中的任一个Replica“活”过来,并且选它作为Leader;或选择第一个“活”过来的Replica(不一定是ISR中的)作为Leader),这个broker宕机的事情,kafka controller也会通知zookeeper,zookeeper就会通知其他的kafka broker。
zookpeer对于Kafka来说也可以看成是一个一致性的k-v存储系统,而不是直接管理Kafka的系统。Kafka把自己的一些信息存在了zk上,比如各个kafka会把各个topic与partition的信息存在zk上,以此来管理集群配置。比如我们的程序是分布式部署在多台机器上,如果我们要改变程序的配置文件,需要逐台机器去修改,非常麻烦,现在把这些配置全部放到zookeeper上去,保存在 zookeeper 的某个目录节点中,然后所有相关应用程序对这个目录节点进行监听,一旦配置信息发生变化,每个应用程序就会收到 zookeeper 的通知,然后从 zookeeper 获取新的配置信息应用到系统中。

这里要先介绍一下传统主从分布式系统。主从分布式系统就是说有多个Server,但是其中有一个是master,其他都是follower。master负责任务的处理,如果master发生故障(单点故障),那么整个系统就会崩溃。因此需要有方法来解决单点故障问题。
最简单最传统的解决方式是采用一个备用节点,定期向master发送ping包,master回复ack来响应备用节点。如果master故障,备用节点将顶替主节点完成晋升。但是如果发生网络故障ack丢失,就会出现双master的情况,一样会有很大的问题。这时候zookeeper就可以来完成调节的作用。

下面通过三种情形来讲解zookeeper的调节能力:

(1)master启动

在分布式系统中引入Zookeeper以后,就可以配置多个主节点,这里以配置两个主节点为例,假定它们是 主节点A 和 主节点B,当两个主节点都启动后,它们都会向ZooKeeper中注册节点信息。我们假设 主节点A 锁注册的节点信息是 master00001 , 主节点B 注册的节点信息是 master00002 ,注册完以后会进行选举,选举有多种算法,这里以编号最小作为选举算法,那么编号最小的节点将在选举中获胜并获得锁成为主节点,也就是 主节点A 将会获得锁成为主节点,然后 主节点B 将被阻塞成为一个备用节点。这样,通过这种方式Zookeeper就完成了对两个Master进程的调度。完成了主、备节点的分配和协作。

(2)master故障
  
如果 主节点A 发生了故障,这时候它在ZooKeeper所注册的节点信息会被自动删除,而ZooKeeper会自动感知节点的变化,发现 主节点A 故障后,会再次发出选举,这时候 主节点B 将在选举中获胜,替代 主节点A 成为新的主节点,这样就完成了主、被节点的重新选举。

(3)master恢复

如果主节点恢复了,它会再次向ZooKeeper注册自身的节点信息,只不过这时候它注册的节点信息将会变成 master00003 ,而不是原来的信息。ZooKeeper会感知节点的变化再次发动选举,这时候 主节点B 在选举中会再次获胜继续担任 主节点 , 主节点A 会担任备用节点。

zookeeper就是通过这样的协调、调度机制如此反复的对集群进行管理和状态同步的。
在这里插入图片描述

Leader:领导者角色,主要负责投票的发起和决议,以及更新系统状态。
follower:跟随着角色,用于接收客户端的请求并返回结果给客户端,在选举过程中参与投票。
observer:观察者角色,用户接收客户端的请求,并将写请求转发给leader,同时同步leader状态,但是不参与
投票。Observer目的是扩展系统,提高伸缩性。
client:客户端角色,用于向zookeeper发起请求。

Zookeeper集群中每个Server在内存中存储了一份数据,在Zookeeper启动时,将从实例中选举一个Server作为leader,Leader负责处理数据更新等操作,当且仅当大多数Server在内存中成功修改数据,才认为数据修改成功。

Zookeeper写的流程为:客户端Client首先和一个Server或者Observe通信,发起写请求,然后Server将写请求转发给Leader,Leader再将写请求转发给其它Server,其它Server在接收到写请求后写入数据并响应Leader,Leader在接收到大多数写成功回应后,认为数据写成功,最后响应Client,完成一次写操作过程。这里用Kafka作为例子,就是Kafka是client。每台server保存的数据其实都是一致的。这么做的原因是因为集群需要能承受相当大的访问流量,因此当流量大的时候就要有多台server来支撑,换句话说就是我Kafka要去访问zookeeper或者提出写的request的时候有多台server才能高效完成工作

Druid

德鲁伊是一种特殊数据库,从mentor的讲述中个人目前的感觉就觉得是一个以时间单位为主键进行查询的数据库(后期更新,我也没太懂)


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部