Kafka -- 动态配置
背景 Kafka安装目录的config路径下,有server.properties文件 通常情况下,会指定server.properties来启动Broker 如果要设置Broker端的任何参数,必须要显式修改server.properties,然后重启Broker,让参数生效 但在生产环境,不能随意重启Broker,因此需要能够动态修改Broker端参数 社区于1.1.0正式引入了动态Broker参数 动态指的是修改参数后,无需重启Broker就能立即生效,而之前server.properties中配置的参数称为静态参数 并非所有Broker端参数都可以动态调整的,官方文档中有Dynamic Update Mode一列 read-only 与原来的参数行为一样,只有重启Broker,才能令修改生效 per-broker 动态参数,修改之后,只会在对应的Broker上生效 cluster-wide 动态参数,修改之后,会在整个集群范围内生效 使用场景 动态调整Broker端各种线程池大小,实时应对突发流量 – 比较常用 动态调整Broker端连接信息或安全配置信息 动态更新...
Java性能 -- 高性能SQL
慢SQL诱因 无索引、索引失效 锁等待 InnoDB支持行锁,MyISAM支持表锁 InnoDB支持行锁更适合高并发场景,但行锁有可能会升级为表锁 一种情况是在批量更新时 行锁是基于索引加的锁,如果在更新操作时,条件索引失效,那么行锁会升级为表锁 基于表锁的数据库操作,会导致SQL阻塞等待,影响执行速度 在写大于读的情况下,不建议使用MyISAM 行锁相对于表锁,虽然粒度更细,并发能力提升,但也带来了新的问题,那就是死锁 不恰当的SQL SELECT * SELECT COUNT(*) 大表中使用LIMIT M,N 对非索引字段进行排序 SQL诊断EXPLAIN id:每个执行计划都有一个id,如果是一个联合查询,会有多个id select_type SIMPLE:普通查询,即没有联合查询、子查询 PRIMARY:主查询 UNION:UNION中后面的查询 SUBQUERY:子查询 table:当前执行计划查询的表,如果表有别名,则显示别名 partitions:分区表信息 type 从表中查询到行所执行的方式 由好到坏:_**system > const > eq...
Kafka -- 主题管理
日常管理创建主题1$ kafka-topics --bootstrap-server localhost:9092 --create --topic t1 --partitions 1 --replication-factor 1 从Kafka 2.2版本开始,推荐使用--bootstrap-server代替--zookeeper(标记为已过期) 原因 使用--zookeeper会绕过Kafka的安全体系,不受认证体系的约束 使用--bootstrap-server与集群交互是未来的趋势 查询主题列表12345$ kafka-topics --bootstrap-server localhost:9092 --list__consumer_offsets_schemast1transaction 查询单个主题1234567$ kafka-topics --bootstrap-server localhost:9092 --describe --topic __consumer_offsetsTopic:__consumer_offsets PartitionCount:50 Repl...
Java性能 -- 生产者消费者模式 + 装饰器模式
生产者消费者模式实现方式Object的wait/notify/notifyAll 基于Object的wait/notify/notifyAll与对象监视器(Monitor)实现线程间的等待和通知 这种方式实现的生产者消费者模式是基于内核实现的,可能会导致大量的上下文切换,性能不是最理想的 Lock中Condition的await/signal/signalAll 相对于Object的wait/notify/notifyAll,更推荐JUC包提供的Lock && Condition实现的生产者消费者模式 Lock && Condition实现的生产者消费者模式,是基于Java代码层实现的,在性能和扩展性方面更有优势 BlockingQueue 简单明了 限流算法漏桶算法通过限制容量池大小来控制流量,而令牌桶算法则通过限制发放令牌的速率来控制流量 漏桶算法 请求如果要进入业务层,就必须经过漏桶,而漏桶出口的请求速率是均衡的 如果漏桶已经满了,请求将会溢出,不会因为入口的请求量突然增加而导...
Java性能 -- 并发设计模式
线程上下文模式 线程上下文指的是贯穿线程整个生命周期的对象中的一些全局信息,如Spring中的ApplicationContext 可以使用ThreadLocal实现上下文 ThreadLocal是线程本地变量,可以实现多线程的数据隔离,每个线程只能访问各自内部的副本变量 Thread-Per-Message模式 一个消息一个线程 在Socket通信中,一个线程监听IO事件,每当监听到一个IO事件,就交给另一个处理线程执行IO操作 如果遇到高并发,就会出现严重的性能问题,因为线程在操作系统中也是昂贵的资源,不能无限制地创建 如果针对每个IO请求都创建一个线程来处理,在有大量请求同时进来时,就会创建大量线程 每次请求都需要创建和销毁线程,性能开销很大 可以使用线程池来代替线程的创建和销毁 ServerHandler1234567891011121314151617181920212223242526272829303132333435363738@AllArgsConstructorpublic class ServerHandler implements Runnable {...
Kafka -- 高水位 + Leader Epoch
高水位水位的定义 经典教科书 在时刻T,任意创建时间(Event Time)为T',且T'<=T的所有事件都已经到达,那么T就被定义为水位 《Streaming System》 水位是一个单调增加且表征最早未完成工作的时间戳 上图中标注为Completed的蓝色部分代表已经完成的工作,标注为In-Flight的红色部分代表正在进行中的工作 两者的边界就是水位线 在Kafka中,水位不是时间戳,而是与位置信息绑定的,即用消息位移来表征水位 Kafka中也有低水位(Low Watermark),是与Kafka删除消息相关联的概念 高水位的作用 两个作用 定义消息可见性,即用来标识分区下的哪些消息可以被消费者消费的 帮助Kafka完成副本同步 上图是某个分区Leader副本的高水位图,在分区高水位以下的消息被认为是已提交消息,反之为未提交消息 消费者只能消费已提交消息,即位移小于8的所有消息 暂不讨论Kafka事务,Kafka的事务机制会影响消费者所能看到的消息的范围,不只是简单依赖高水位来判断 而是依靠LSO(Log Stable Offset)的位移...
Java性能 -- 原型模式 + 享元模式
原型模式 原型模式:通过给出一个原型对象来指明所创建的对象的类型,然后使用自身实现的克隆接口来复制这个原型对象 使用这种方式创新的对象的话,就无需再通过new实例化来创建对象了 Object类的clone方法是一个Native方法,可以直接操作内存中的二进制流,所以相对new实例化来说,性能更佳 实现原型模式12345678910111213141516171819202122232425262728class Prototype implements Cloneable { @Override public Prototype clone() { Prototype prototype = null; try { prototype = (Prototype) super.clone(); } catch (CloneNotSupportedException e) { e.printStackTrace(); } ...
Kafka -- 控制器
控制器 控制器(Controller)是Kafka的核心组件,主要作用是在ZK的帮助下管理和协调整个Kafka集群 集群中任一Broker都能充当控制器的角色,但在运行过程中,只能有一个Broker成为控制器,行使管理和协调的职责 12345678910111213[zk: localhost:2181(CONNECTED) 1] get /controller{"version":1,"brokerid":0,"timestamp":"1571311742367"}cZxid = 0xd68ctime = Thu Oct 17 19:29:02 CST 2019mZxid = 0xd68mtime = Thu Oct 17 19:29:02 CST 2019pZxid = 0xd68cversion = 0dataVersion = 0aclVersion = 0ephemeralOwner = 0x1000209974b0000dataLength = 54numChildren = 0 Zo...
Java性能 -- 单例模式
饿汉模式class1234567891011// 饿汉模式public final class Singleton { private static Singleton instance = new Singleton(); private Singleton() { } public static Singleton getInstance() { return instance; }} 使用了static修饰了成员变量instance,所以该变量会在类初始化的过程中被收集进_类构造器<clinit>_ 在多线程场景下,JVM会保证只有一个线程能够执行该类的<clinit>方法,其它线程将会被阻塞等待 等到唯一的一次<clinit>方法执行完成后,其它线程将不会再执行<clinit>方法,转而执行自己的代码 因此,static修饰的成员变量instance,在多线程的情况下能保证只实例化一次 在类初始化阶段就已经在堆内存中开辟了一块内存,用...
Kafka -- 重平衡
触发重平衡 组成员数量发生变化 – 最常见 订阅主题数量发生变化 订阅主题的分区数发生变化 通知 重平衡过程是通过消费者的心跳线程通知到其它消费者实例的 Kafka Java消费者需要定期地发送心跳请求到Broker端的协调者,表明它还活着 在Kafka 0.10.1.0之前,发送心跳请求是在消费者主线程完成的,即调用poll方法的那个线程 弊端 消息处理逻辑是也在主线程完成的 一旦消息处理消耗了很长时间,心跳请求将无法及时发送给协调者,导致协调者误以为消费者已死 从Kafka 0.10.1.0开始,社区引入了单独的心跳线程 重平衡的通知机制是通过心跳线程来完成的 当协调者决定开启新一轮重平衡后,会将REBALANCE_IN_PROGRESS封装进心跳请求的响应中 当消费者实例发现心跳响应中包含REBALANCE_IN_PROGRESS,就知道重平衡要开始了,这是重平衡的通知机制 heartbeat.interval.ms的真正作用是控制重平衡通知的频率 消费者组状态机 状态 描述 Empty 组内没有任何成员,但消费者组可能存在已提交的位移数据,而且这些位移尚未过期 ...













