数据安全
** producer delivery guarantee(生产者机制) **
1)Producers可以选择是否为数据的写入接收ack,request.required.acks
- acks = 0:Producer在ISR中的Leader已成功收到的数据并得到确认后发送下一条Messa。
- acks = 1:这意味着Producer无需等待来自Broker的确认而继续发送下一条消息。
- acks = all:Producer需要等待ISR中的所有Follower都确认接收到数据后才算一次发送完成,可靠性最高。
2)我们备份数据就是防止数据丢失,当主节点挂掉时,可以启用备份节点:过程如下:
- producer ----->push--------->leader
- leader--------->pull---------->follower
- Follower每间隔一定时间去Leader拉去数据,来保证数据的同步。
3)ISR(副本使用机制),
当主节点挂掉,并不是去Follower选择主,而是从ISR中选择主;
判断标准:
数据同步时间:relica.lag.time.max.ms
主副节点相差消息数: rerplica.lag.max.messages
** Broker数据存储机制**
无论消息是否被消费,kafka都会保留所有消息。有两种策略可以删除旧数据:
1)基于时间,log.retention.hours
2) 基于大小,log.retention.bytes
** consumer delivery guarantee**
- 如果将consumer设置为autocommit,consumer一旦读到数据立即自动commit。如果只讨论这一读取消息的过程,那kafka确保了Exactly once。
- 读完消息先commit再处理消息。
-
- 如果consumer在commit后还没来得及处理消息就crash了,下次重新开始工作后就无法读到刚刚已提交而为处理的消息;
-
- 这就对应于At most once;
- 读完消息先处理再commit;
-
- 如果再处理完消息之后commit之前consumer crash了,下次重新开始工作时还会处理刚刚未commit的消息实际上该消息已经被处理过了;
-
- 这对应于At least once;
- 如果一定要做到Exactly once,就需要协调offset和实际操作的输出;
-
- 经典的做法时引入两阶段提交;
- Kafka默认保证At least once,并且允许通过设置producer异步提交来实现At most once
数据的消费
- parttion_num = 2,启动一个consumer进程订阅这个topic,对应的,steam_num设置为2,也就是说启用两个线程并行处理message。
- 如果auto.commit.enable = true.
-
- 当consumer fetch了一些数据但还没有完全处理掉的时候,
-
- 刚好到commit interval 触发了提交offset操作,接着consumer crash 掉了;
-
- 这时已经fetch的数据还没有处理完成但已经被commit 掉,因此没有机会再次被处理,数据丢失;
- 如果auto.commit.enable = false.
-
- 假设consumer的两个fetcher 各自拿了一条数据,并且由两个线程同时处理
-
- 这时线程t1处理完p1的数据,手动提交offset,这里需要着重说明的是,当手动执行commit的时候,
-
- 实际上是对这个consumer进程所占有的所有parttion进行commit,kafka暂时还没有提供更细粒度的commit方式;
-
- 也就是说,即使t2没有处理完parttion2的数据,offset也被t1提交掉了,如果这时consumer crash掉了,t2正在处理的这条数据也就丢失了;
- 方法1:(将多线程问题转成单线程)
-
- 手动commit offset。并针对partition_num启同样数目的sonsumer进程,这样就能保证一个consumer进程占有一个partition,commit offset 的时候不会影响别的partition的offset,但这个方法比较局限,因此parttion和consumer进程的数目必须严格对应;
- 方法2:
-
- 手动commit offset,另外在consumer 端再将所有fetch到的数据缓存到queue里。当把queue里所有的数据处理完之后,再批量提交offset,这样就能保证只有处理完的数据才被commit;
kafka优化:
partition数目:
一般来说每个partition能处理的吞吐为几MB/s,增加更多的partition意味着:
- 更高的并行度与吞吐;
- 可以扩展更多的(同一个consumer Group中)consumer;
- 但是会造成ZK的更多选举;
- 也会在ZK中打开更多的文件;
调整准则:
- 1,若是集群小于6个brokers,则配置2xbroker的partition;
- 2,若是大于12个,则配置1xbroker个partition;
- 3,考虑最高峰吞吐需要的并行consumer数,调整partition的数目,若是应用场景中需要20个(一个CG中),consumer并行消费,则需设置20个partition;
Replication factor:
- 建议至少设置为2,一般是3,最高设置为4;
- 更高的replication factor 意味着:
- 系统更稳定,更多的副本,会造成较高的延迟;系统磁盘的使用率会更高;以3为起始;
批量写入:
为了大幅度提高producer写入吞吐量,需要定期批量写文件:
- 每当producer写入10000条消息时,刷数据到磁盘:log.flush.interval.messages = 10000;
- 每隔一秒时间,刷数据到磁盘:log.flush.interval.ms = 1000;