kafka学习总结(简化个人版)(2)

第四篇章:Springboot中使用Kafka
1.引入依赖

    <dependency>
         <groupId>org.springframework.kafka</groupId>
         <artifactId>spring-kafka</artifactId>
    </dependency>


2.配置文件:
 

server:
    port: 8080
spring:
    kafka:
        bootstrap-servers: 192.168.56.10:9092,192.168.56.10:9093,192.168.56.10:9094
        producer: # 生产者
            retries: 3 # 重试配置:设置大于 0 的值,则客户端会将发送失败的记录重新发送
            batch-size: 16384
            buffer-memory: 33554432   #★ 消息缓冲区配置
            acks: 1  #ack配置
            # 指定消息key和消息体的编解码方式
            key-serializer: org.apache.kafka.common.serialization.StringSerializer
            value-serializer: org.apache.kafka.common.serialization.StringSerializer
        consumer:
            group-id: default-group
            enable-auto-commit: false    #手动提交
            auto-offset-reset: earliest   # 新消费组的消费offset规则
            key-deserializer: org.apache.kafka.common.serialization.StringDeserializer
            value-deserializer: org.apache.kafka.common.serialization.StringDeserializer
            max-poll-records: 500    #一次最多拉500条
        listener:
        # 当每一条记录被消费者监听器(ListenerConsumer)处理之后提交
        # RECORD
        # 当每一批poll()的数据被消费者监听器(ListenerConsumer)处理之后提交
        # BATCH
        # 当每一批poll()的数据被消费者监听器(ListenerConsumer)处理之后,距离上次提交时间大于TIME时提交
        # TIME
        # 当每一批poll()的数据被消费者监听器(ListenerConsumer)处理之后,被处理record数量大于等于COUNT时提交
        # COUNT
        # TIME | COUNT 有一个条件满足时提交
        # COUNT_TIME
        # 当每一批poll()的数据被消费者监听器(ListenerConsumer)处理之后, 手动调用Acknowledgment.acknowledge()后提交
        # MANUAL
        # 手动调用Acknowledgment.acknowledge()后立即提交,一般使用这种
        # MANUAL_IMMEDIATE
            ack-mode: MANUAL_IMMEDIATE
#     redis:
#         host: 172.16.253.21

3. Controller撰写
消息生产者:

     @RestController
     @RequestMapping("/msg")
     public class MyKafkaController {

           private final static String TOPIC_NAME = "my-replicated-topic";

          @Autowired
          private KafkaTemplate<String, String> kafkaTemplate; //如果自动注入错误,可能是springboot版本错误,去pom.xml中修改springboot版本,可改成 <version>2.3.7.RELEASE</version>


          @RequestMapping("/send")
          public String sendMsg(){
                  kafkaTemplate.send(TOPIC_NAME, 0, "my_key", "this is a message");
                  return "send success";
         }
    }


当调用localhost:8080/msg/send  消息就发送了,发送到了my-replicated-topic主题

4.消息消费者:
 

@KafkaListener(topics = "my-replicated-topic",groupId = "MyGroup1")
  public void listenGroup(ConsumerRecord<String, String> record,Acknowledgment ack) {    //也可以ConsumerRecords<String, String> records  一次性poll的多条消息进行操作
       String value = record.value();
       System.out.println(value);
       System.out.println(record);
       //手动提交offset
       ack.acknowledge();
}

 设置消费组、多topic、指定分区、指定偏移量消费及设置消费者个数:
        

    @KafkaListener(groupId = "testGroup", topicPartitions = {
            @TopicPartition(topic = "topic1", partitions = {"0", "1"}),
            @TopicPartition(topic = "topic2", partitions = "0", partitionOffsets = @PartitionOffset(partition = "1", initialOffset = "100"))}
            , concurrency = "3")//concurrency就是同组下的消费者个数,就是并发消费数,建议小于等于分区总数
            public void listenGroup(ConsumerRecord<String, String> record, Acknowledgment ack) {
                     String value = record.value();
                     System.out.println(value);
                     System.out.println(record);
                     //手动提交offset
                    ack.acknowledge();
            }

Kafka集群Controller、Rebalance和HW,LEO:
Controller:


       Kafka集群中的broker在zk中创建临时序号节点,序号最小的节点(最先创建的节点)将作为集群的controller,负责管理整个集群中的所有分区和副本的状态:
        当某个分区的leader副本出现故障时,由控制器负责为该分区选举新的leader副本。
        检测到某个分区的ISR集合发生变化时,由控制器负责通知所有broker更新其元数据信息。
        当使用kafka-topics.sh脚本为某个topic增加分区数量时,同样还是由控制器负责让新分区被其他节点感知到。
Rebalance机制:


       前提是:消费者没有指明分区消费。当消费组里消费者和分区的关系发生变化,那么就会触发rebalance机制。
       这个机制会重新调整消费者消费哪个分区。
       在触发rebalance机制之前,消费者消费哪个分区有三种策略:
       range:通过公示来计算某个消费者消费哪个分区
       轮询:大家轮着消费
       sticky:在触发了rebalance后,在消费者消费的原分区不变的基础上进行调整。
HW,LEO:
      LEO(log-end-offset)是某个副本最后消息的位置。

 

      HW(HighWatermark)是已完成同步的位置。leader和follower都会保存有自己的HW。消息写入leader且每个副本都同步完这个消息后,hw才会变化,在这之前消费者是消费不到这条消息的。同步完成之后,HW才会更新,消费者才能消费这个最新消息,这是为了防止消息的重复消费(消费者消费完最新的还没有同步到其它broker的消息后,leader把消息同步给其它副本,然后leader挂了,其它副本成为新的leader,消费者就会重复读取这个最新的消息)

第五篇章:优化相关问题,消息队列内容面试常问问题
  ★1.如何防止消息丢失
          生产者:使用同步发送,把ack设为1或者all,并且设置同步的分区数>=2;
          消费者:设置为手动提交。
  ★2. 如何防止消息的重复消费


          一条消息被消费者消费多次。如果为了消息的不重复消费,而把生产端的重试机制关闭、消费端的手动提交改成自动提交,这样反而会出现消息丢失,那么可以直接在防治消息丢失的手段上再加上消        费消息时的幂等性保证,就能解决消息的重复消费问题。
          幂等性如何保证:
          mysql 插入业务id作为主键,主键是唯一的,所以一次只能插入一条
          使用redis或zk的分布式锁(主流的方案)  (使用redis判重:使用redis存放已经消费的消息的order_id,再次消费时直接判断redis是否包含该order_id)

视频图片中老师针对联合主键讲解有误
(联合主键 :联合主键就是用2个或2个以上的字段组成主键。
                     用这个主键包含的字段作为主键,这个组合在数据表中是唯一,且加了主键索引。
                     可以这么理解,比如,你的订单表里有很多字段,一般情况只要有个订单号bill_no做主键就可以了,但是,现在要求可能会有补 充订单,使用相同的订单号,
                     那么这时单独使用订单号就不可以了,因为会有重复。那么你可以再使用个订单序列号bill_seq来 作为区别。把bill_no和bill_seq设成联合主键。
                     即使bill_no相同,bill_seq不同也是可以的。
                     商品品牌 商品型号
                     诺基亚 920
                     三星 NOTE2
                     诺基亚 8088
                     建立方法如下:
                     create table product( pro_name varchar(20), pro_type varchar(20), primary key (pro_name,pro_type) );           )
 ★3.如何做到顺序消费RocketMQ
       发送方:在发送时将ack不能设置 0 ,使用同步发送(保证消息按顺序发送,且消息不丢失),等到发送成功再发送下一条。确保消息是顺序发送的。
       接收方:消息是发送到一个分区中,只能有一个消费组的消费者来接收消息。因此,kafka的顺序消费会牺牲掉性能。

 ★4. 消息积压问题:


       消费积压:消费者的消费速度远小于生产者生产消息的速度,导致kafka中有大量的数据没有被消费。随着没有被消费的数据积累越多,消费者寻址的性能会越来越差,最后导致整个kafka对外提供的                          服务性能很差,从而造成其它服务也访问变慢,造成服务雪崩。
       解决方案:
            在这个消费者中使用多线程,充分利用机器的性能进行消费消息;
            通过业务的架构设计,提升业务层面消费的性能;
            创建多个消费组,多个消费者,部署到其它机器上,一起消费,提高消费者的消费速度
            创建一个消费者,该消费者在kafka另建一个主题,配上多个分区,多个分区再配上多个消费者。该消费者将poll下来的消息,不进行消费,直接转发到新建的主题上,此时,新的主题的多个分区的多个消费者就开始一起消费了-----不常用

 

 

 

  ★5.延迟队列


     场景:订单超过30分钟未支付,自动取消订单。
           kafka中创建相应的主题
           消费者轮询消费该主题的消息
           消费者消费时判断该消息的创建时间和当前时间是否超过30分钟(前提是订单未支付)
                  如果是,去数据库中修改订单状态未已取消
                  如果否,记录当前消息的offset,并不再继续消费之后的消息。等待1分钟后,再次向kafka中拉取该offset及之后的消息,继续进行判断,依次反复。


第六篇章:Kafka-eagle监控平台
        1.去kafka-eagle官网下载安装包
        2.在虚拟机中安装(要有jdk)
        3.配置环境变量 
            vi /etc/profile 
            #添加下面这两条
           export KE_HOME=/usr/local/kafka-eagle
           export PATH=$PATH:$KE_HOME/bin
           //刷新配置
           source  /etc/profile 
        
        4.修改kafka-eagle内部的配置文件:
             vi system-config.properties
             修改里面的zk地址和mysql地址
        5.进入到bin中,启动
              ./ke.sh start

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值