1、Topic的分片和副本机制
分片作用:
解决单台节点容量有限的问题,节点多,效率提升,吞吐量提升。通过分片,将一个大的容器分解为多个小的容器,分布在不同的节点上,从而实现分布式存储。
分片的数量没有限制,与节点数量没有关系,分片数量不会超过总节点数量的三倍。
副本作用:
提升数据的可靠性,副本越多数据越可靠,但是数据冗余越高。
副本数量有限制,最多和节点的数量相等,但是一般构建1~3个之间。
2、Kafka如何保证数据不丢失
数据传输的三个阶段:
生产者生产是数据到broker
broker存储数据
消费者从broker上消费数据
<1> 生产端如何保证数据不丢失:
生产数据到broker之后的响应机制
当生产者生产数据到Broker后,Broker应该给于确认响应(ack)。
ack 确认机制,主要有三种方案,分别为0 1 -1(ALL)
0:生产者只管将数据生产到Borker ,不等待Broker返回的ack 信息
1:生产者将数据生产到Broker,需要等待Broker端Topic的对应分片上的主副本接收到消息后,即为成功发送消息。
-1: 生产者将数据生产到broker,需要等待broker端Topic的对应分片所有副本都接收到消息,即为成功发送
生产中一般根据消息重要情况以及生成和消费速率来选择相应的级别。一般来说,重要程度越高的,安全级别越高,速率越高,优先保证安全性,在此基础上,保持平衡。
相关问题思考:
1-生产者发送一条数据到Broker,Broker给于一次响应,如果Broker迟迟不予响应,怎么办?
先等待,然后重试,最后报错,先等待一段时间,当超时后,然后触发充重试策略,进行重试擦擦操作,当重试后依然没有响应,最后程序报错,停止发送。
2-生产者发送一条数据,Broker就要给予一次响应,那么这样是否会占用更多的带宽,如果占用,如何解决?
肯定会影响,可以引入缓存池,生产者在生产数据的时候,底层先将其放置到一个缓存池,当池子中消息数据达到一批数据大小后,会专门有一个子线程,触发执行,将数据生产到Broker,此时Broker只需要对这一批数据给予一次响应即可,异步发送。
3- 如果采用一批一批的发送,如果Broker又没有给予响应,但是,此时缓存池中数据已经满了,如何解决?
可以选择直接清空缓存池或者不清空,如果数据可以重复读,直接报错清空即可,后续重新读取数据即可,如果数据不可重复读,可以提前设置处理方案,将每一个消息提前先找一个容器进行备份存储,自己维护数据,当发送成功,删除一部分数据,如果出错,重启后,先从这个容器将剩余的数据发送即可,当然如果选择不清空,那么一直等待即可。
相关的一些参数设置:
buffer.memory 设置缓存池大小,默认值33554432(32M)
retries 重试的次数,默认值2147483647,最终的重试策略取决于超时设置
batch.size 表示一批数据大小,默认值16384(16KB)
delivery.timeout.ms 总超时时间,默认值120000(120S)
requesst.timeout.ms 每一次请求后的超时时间(等待时间),默认值 30000(30s )
<2>Broker 如何保证数据不丢失
Broker可以将每个分片的副本数量设置为多个,提供数据的可靠性同时还需要生产端将ACK设置为-1
<3>消费端如何保证数据不丢失
消费者连接kafka集群,kafka收到请求后,首先会根据group_id 查询上一次消费到了哪个消息偏移量,如果没有找到,默认从当前的位置开始消费数据,之前的消息默认不处理,如果找到了,就从记录的消息偏移量位置继续消费数据即可
消费者消费完数据后,会把对应的消息的偏移量信息重新提交给Broker记录
在提交偏移量的时候有两种提交方式:自动提交偏移量,手动提交偏移量
配置自动提交:
python
consumer = KafkaConsumer(
"test",
bootstrap_servers=['localhost:9092'],
group_id='g_2',
enable_auto_commit=True,
auto_commit_interval_ms=1000
)
手动提交:
python
consumer = KafkaConsumer(
"test",
bootstrap_servers=['localhost:9092'],
group_id='g_2',
enable_auto_commit=False,
auto_commit_interval_ms=1000
)
consumer.commit() #同步提交
consumer.commit_async() #手动提交