kafka原理

kafka 原理

1.topic下面分partition,每个partition的offset是这个在partition里面的偏移量
2.具体选择那个partition会根据算法来选择,基本上会平均分配
3.zookeeper和kafka的关系是zookeeper用来管理kafka内部的分区和选择leader
4.ISR是用来管理副本的,有一个HW的水位线,Leader和Follower都复制完成,水位线就到这个位置。
选择follwer现在是基于时间的值来判断的,延迟时间超过这个值就剔除ISR,没有选用relica.lag.max.message的原因是,如果设置数量为4,如果follower正常工作,leader接收到的producer发送过来的条数就是4,那么follower肯定小于4,那么就会被剔除ISR,但是事实是他follower能够正常工作,过一段时间有加回来,浪费资源。
5.topic是在Kafka broker里面,Producer消息的生产者是在向broker发送信息,Consumer是在从Broker里面读取信息。

不使用group的话,启动10个consumer消费一个topic,这10个consumer都能得到topic的所有数据,相当于这个topic中的任一条消息被消费10次。

KafkaTemplate

1.Kafka 生产者

@Slf4j
@Component
public class KafkaConsumer {

    //@KafkaListener(topics = "#{'${kafka.consumer.topics}'.split(',')}")
        @KafkaListener(//必须设置groupId,没有就设置默认的group.id
                 topics = "my_log",
                groupId = "group.id",
                //会在日志前面加上前缀
                clientIdPrefix = "abc",
                containerFactory = "kafkaListenerContainerFactory")
                //containerFactory = "ackSingleContainerFactory")
        //如果输入的部分要设置ack,那么必须要有手动获取ack偏移量节点
        public void inputPersonfileNewCluster(List<ConsumerRecord> consumerRecords) {
            log.info(String.valueOf(consumerRecords));
        }


}

2.设置取数据的参数

@Configuration
public class ConfigKafka {
    @Bean
    public ConcurrentKafkaListenerContainerFactory<String,byte[]> kafkaListenerContainerFactory(ConsumerFactory<String,byte[]> consumerFactory){
        ConcurrentKafkaListenerContainerFactory<String,byte[]> factory=new ConcurrentKafkaListenerContainerFactory<>();
       //相当于同时多少个客户端在取数据,2说明有两个客户端同时取数据
        factory.setConcurrency(2);
        factory.setConsumerFactory(consumerFactory);
        //设置为批量消费,每个批次数量在Kafka配置参数中设置ConsumerConfig.MAX_POLL_RECORDS_CONFIG,每次取MAX_POLL_RECORDS_CONFIG个数据
        factory.setBatchListener(true);
        return factory;

    }
}

3.在配置文件里面加入批量消费的数据个数在这里插入图片描述
4.kafka生产者

@Slf4j
@Component
public class KafkaProducer {
    @Resource
    private KafkaTemplate<String,String> kafkaTemplate;

    public void send(String topic, String obj){

        log.info("准备发送消息",obj);

        ListenableFuture<SendResult<String,String>> future = kafkaTemplate.send(topic,obj);
        future.addCallback(new ListenableFutureCallback<SendResult<String, String>>() {
            @Override
            public void onFailure(Throwable throwable) {
                log.info(topic+"生产者消费失败"+throwable.getMessage());
            }

            @Override
            public void onSuccess(SendResult<String, String> stringStringSendResult) {
                log.info(topic+"生产者发送消息成功"+stringStringSendResult.toString());
            }
        });

    }
}

5.调用KafkaProducer

@Component
public class KafkaProducerService {
    @Resource
    KafkaProducer kafkaProducer;
    public void test(){
        kafkaProducer.send("my_log","abc");
    }
}
@RestController
public class ProducerController {
    @Resource
    KafkaProducerService kafkaProducerService;
    @Resource
    KafkaTransactionService kafkaTransactionService;

    @PostMapping("/hby")
    public void test(){
        kafkaProducerService.test();
    }

    @PostMapping("/hby1")
    public void test1(){
        kafkaTransactionService.sendToKafka("error");
    }


    @PostMapping("/hby2")
    public void test2(@RequestParam String input){
        kafkaTransactionService.sendToTrans(input);
    }
}

Kafka事务

Kafka处理事务的两种方法,加注解和用template.executeInTransaction,当中间有报错,数据都进行回滚,不进行传输。输入是error不发送数据。

@Component
public class KafkaTransactionService {
    @Resource
    private KafkaTemplate template;

    public String sendToKafka(String input){
        template.executeInTransaction(t->{
                    t.send("my_log",input);
                    if("error".equals(input)){
                        throw new RuntimeException("input is error");
                    }
                    t.send("my_log",input+"other");
                    return true;
                });
        return "Send success"+input;
    }

    @Transactional
    public String sendToTrans(String input){
            template.send("my_log",input);
            if("error".equals(input)){
                throw new RuntimeException("input is error");
            }
            template.send("my_log",input+"other");
        return "Send success"+input;
    }
}

kafka单元测试

这部分还需学习,虽然能够跑通过,但是没有对应到对应的方法中。

@SpringBootTest
@DirtiesContext
@ActiveProfiles("junit")
@RunWith(SpringRunner.class)
@EmbeddedKafka(controlledShutdown = true,topics = "my_log")
@Slf4j
public class KafkaConsumerTest {

    @Resource
    private EmbeddedKafkaBroker kafkaEmbeded;

    @Before
    public void setUp() {
        Map<String,Object> senderProperties = KafkaTestUtils.producerProps(kafkaEmbeded.getBrokersAsString());
        ProducerFactory<String,String> producerFactory=new DefaultKafkaProducerFactory<>(senderProperties);
        KafkaTemplate<String,String> template=new KafkaTemplate<>(producerFactory);
        String topic="my_log";
        template.send(topic,"and sec");
    }
   @Test
    public void onMessage() throws InterruptedException{
        TimeUnit.SECONDS.sleep(5);
        System.out.println("finish");
      // log.info(String.valueOf(consumerRecords));
    }
}

Linux grep 管道

Linux提供的管道符号,|左面命令的输出会作为右面命令的输入,第二个管道符号,做不命令的输出,同样作为右面命令的输入,以此类推。

 ps -ef|grep java
  501  1794  1018   0  9:34上午 ?? 

每个字段的含义
UID PID PPID C STIME TTY TIME CMD

zzw 14124 13991 0 00:38 pts/0 00:00:00 grep --color=auto dae

UID :程序被该 UID 所拥有
PID :就是这个程序的 ID
PPID :则是其上级父程序的ID
C :CPU使用的资源百分比
STIME :系统启动时间
TTY :登入者的终端机位置
TIME :使用掉的CPU时间
CMD :所下达的是什么指令

从当前目录开始查找所有扩展名为 .rtf 的文本文件,并找出包含 “Abc” 的行

crystaldeMacBook-Pro:javahby crystal$ find . -name "*.rtf" | xargs grep "Abc"
\f0\fs24 \cf0 Abc}

在一个类里面主函数调用方法

https://blog.csdn.net/qq_35389417/article/details/84024470

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值