1.Topic的分片和副本机制
什么是分片呢?
分片: 逻辑概念 相当于将一个Topic(大容器)拆分为N多个小容器, 多个小的容器构建为一个Topic 目的: 1- 提高读写的效率: 分片可以分布在不同节点上, 在进行读写的时候, 可以让多个节点一起参与(提高并行度) 2- 分布式存储: 解决了单台节点存储容量有限的问题 分片的数量:分片是可以创建N多个, 理论上没有任何的限制
什么是副本呢?
副本: 物理的概念 针对每个分片的数据, 可以设置备份, 可以将其备份多个 目的: 提高数据的可靠性, 防止数据丢失 副本的数量: 副本的数量最多和集群节点数量保持一致, 但是一般设置为 2个 或者 3个
2.kafka如何保证数据不丢失
2.1 生产端是如何保证数据不丢失
当生产者将数据生产到Broker后, Broker应该给予一个ack确认响应,在Kafka中, 主要提供了三种ack的方案:
0: 生产者只管发送数据, 不关心不接收broker给予的响应
1: 生产者将数据发送到Broker端, 需要等待Broker端对应的topic上的对应的分片的主副本接收到消息后, 才认为发送成功了
-1(ALL): 生产者将数据发送到Broker端, 需要等待Broker端对应的topic上的对应的分片的所有的副本接收到消息后, 才认为发送成功了
效率角度: 0 > 1 > -1
安全角度: -1 > 1 > 0思考: 在实际使用中, 一般使用什么方案呢? 三种都有可能
一般要根据消息的重要程度, 来选择采用什么方案, 如果数据非常的重要, 不能丢失, 一般设置为 -1
相关的思考的点:
思考1: 如果Broker迟迟没有给予ACK响应, 如何解决呢? 解决方案: 设置超时时间, 如果超时触发重试策略, 如果多次重试依然无法给予响应, 此时程序报异常 思考2: 每发送一次,Broker就要给予一次响应, 请问这样是否会对网络带宽产生影响呢? 如果产生, 如何解决呢? 解决方案: 会, 引入缓存池, 满足了一批数据后, 异步发送给Broker端, Broker端只需要针对这一批数据给予一次响应即可 思考3:通过一批一批的异步发送方式, 如果Broker端对这一批数据没有给予响应, 但是缓存池中数据已经满了, 如何解决? 解决方案: 选择清空缓存池 / 不清空, 如果数据是可重复读的,那么直接让程序报错即可, 通知处理, 处理后, 重新获取发送即可, 如果数据是不可重复读,为了避免此种问题, 我们可以数据先在某个其他位置保存(备份), 当数据生产成功, 删除对应的数据, 生产不成功, 后续直接从保存的位置中获取生产即可
相关的参数:
buffer.memory : 缓存池的大小 默认值: 33554432(32M) retries: 重试次数 默认值: 2147483647 (此参数并不代表最终的重试次数, 取决于超时相关参数) delivery.timeout.ms: 一次发送数据总超时时间 默认值: 120000(120s) request.timeout.ms: 一次请求超时时间 默认值: 30000(30s) 一批数据的阈值: 时间 和 大小 batch.size : 一批数据大小 默认值: 16384 (16kb) linger.ms : 每一批次的间隔时间 默认值: 0
2.2 Broker端如何保证数据不丢失
保证方案: 磁盘存储 + 多副本 + ack为-1
2.3 消费端如何保证数据不丢失
第一步: 当Consumer启动后, 连接Kafka集群, 根据group.id 到Kafka中寻找上一次消费到了什么位置(偏移量)
第二步:
如果consumer找到了上次消费位置, 接着从这个位置开始消费数据
如果没有找到上一次消费的位置, 说明第一次来, 这个时候默认从当前时刻开始消费数据, 消费的位置也会从当前这个消息的偏移量位置开始消费
第三步: 消费者开始消费数据, 在消费的过程中, 每消费完数据后, 都要和kafka集群进行汇报, 汇报当前消费到了那一个偏移量信息汇报方式: 自动 / 手动
思考: 请问在这种方式下是否可以保证消费端不会发送数据丢失的问题呢?
可以保证, 但是可能会存在重复消费的问题
思考: 消费者消费的消息偏移量信息是存储在哪里呢?
在 0.8.x版本之前, 消费者的消息偏移量信息是被记录在zookeeper中
在 0.8.x版本之后, 将消费者的消息偏移量信息记录在kafka集群上, 通过一个topic来记录: __consumer_offsets
此topic默认有50个分片 1个副本