- 博客(281)
- 收藏
- 关注
原创 RocketMQ NameServer网络通信架构(基于Netty)
初始化Netty是负责监听、处理Broker和客户端发送的网络请求的,NameServer通过9876这个端口接收来自Broker、客户端的网络请求,如Broker注册自己、客户端拉取Broker路由数据等。在构建好NamesrvController后,会通过start方法来启动这一核心组件。首先要初始化NamesrvController//初始化NamesrvControllerboolean initResult = controller.initialize();在这个方法内,会构建Net
2021-07-05 15:17:02
258
原创 RocketMQ NameServer启动要初始化哪些参数
distribution/bin/mqnamesrv中启动NameServer进程的命令:sh ${ROCKETMQ_HOME}/bin/runserver.sh org.apache.rocketmq.namesrv.NamesrvStartup $@这行命令执行了runserver.sh,以此启动了NamesrvStartup这个Java类JAVA_OPT="${JAVA_OPT} -server -Xms4g -Xmx4g -Xmn2g -XX:MXX:MaxMetaspaceSize=320
2021-07-05 14:03:45
837
2
原创 Kafka Sender线程如何发送数据
文章目录1.内存缓冲中的Batch,如何被判定可发送出去2.标识那些元数据未拉取成功的3.检查筛选出来的Broker是否可以发送数据3.1 元数据是否已经就位3.2 是否可以发送请求3.3 跟Broker建立连接3.3.1 初始化SocketChannel3.3.2 发起连接请求3.3.3 将SocketChannel缓存起来3.4 筛选Broker4.将Broker分组5.淘汰超时的Batch6.为Batch以Broker为单位,构建Request7.将构建好的Request请求发送出去番外篇:完成最终的
2021-05-13 11:51:51
425
原创 谈谈对Kafka Accumulator的理解
文章目录前期准备1.获取分区队列Deque2.尝试将消息放到batch中3.基于Buffer Pool,给batch分配一块内存3.1 如何基于缓冲池中的ByteBuffer,复用内存空间3.2 不断申请内存导致可用内存被耗尽咋办?4. 基于double-check模式,再次尝试tryAppend4.1 一条消息是如何按照二进制协议写入到Batch中的ByteBuffer中的4.2 频繁写入消息,如何进入已有的分区的batch中?4.3 如果1个Batch被写满了,如何申请内存构建下一个Batch?5.总结
2021-05-07 16:03:44
572
原创 一条消息是如何按照二进制协议写入到Batch中的ByteBuffer中的
double-check模式中会将消息放到Batch中://将消息放到batch中去FutureRecordMetadata future = Utils.notNull(batch.tryAppend(timestamp, key, value, callback, time.milliseconds()));实际调用的是MemoryRecords的的append方法,将消息写入到MemoryRecords的ByteBuffer中://调用MemoryRecord#append方法,将消息放入
2021-05-07 13:17:38
159
原创 基于double-check模式尝试将消息放到batch中
多线程并发获取Deque,但只会有一个人会new。然后就会对获取到的Deque加锁,并尝试将消息放入到获取到的Deque的已有的batch中: //对分区队列加锁后,尝试将消息放到队列中的已有的batch中 synchronized (dq) { if (closed) throw new IllegalStateException("Cannot send after the produ
2021-05-07 11:09:12
158
2
原创 Kafka如何基于CopyOnWrite实现线程安全的Deque构建
执行getOrCreateDeque方法,拿着topic的partition,就去拿分区队列Deque(有就拿,没有就创建)。private Deque<RecordBatch> getOrCreateDeque(TopicPartition tp) { //分区作为key,从CopyOnWriteMap中拿分区队列Deque //如果有Deque就拿,没有就创建 Deque<RecordBatch> d = this.batches
2021-05-07 10:56:49
300
原创 Kafka将消息发往内存缓冲区
KafkaProducer是多线程并发安全的,多线程环境下也不会导致数据错乱。//将消息添加到内存缓冲里去,RecordAccumulator组件负责的RecordAccumulator.RecordAppendResult result = accumulator.append(tp, timestamp, serializedKey, serializedValue, interceptCallback, remainingWaitMs);首先要从内存缓冲区中找出这个partition对应的De
2021-05-03 16:17:31
990
原创 Kafka ProducerRecord的分区路由策略
分区路由策略把消息、序列化的key、序列化的value、元数据都传参给partition()方法。首先要获取消息的分区号://获取消息的分区Integer partition = record.partit
2021-04-29 21:18:30
833
原创 Kafka如何对Topic元数据进行细粒度的懒加载、同步等待?
首先确保Topic的元数据可用,否则消息根本没法往外发。如果以前从没加载过Topic元数据,就会在doSend发送消息时调用waitOnMetadata方法在此同步阻塞住,等待连接Broker成功后拉取元数据。max.block.ms决定了调用send()方法时,最多会被阻塞多长时间。send在一些异常情况下:拉取Topic元数据,连接不到Broker数据放到内存缓冲区,但内存缓冲区已经满了经历这段时间后,就必须得返回了。首先会判断目标Topic的元数据是否已经被加载过了。如果没有,就会把该T
2021-04-29 18:05:46
464
原创 客户端发送消息时,源码运行的大致流程
send消息: @Override public Future<RecordMetadata> send(ProducerRecord<K, V> record, Callback callback) { // 如果拦截器为null,就直接拿封装的ProducerRecord //否则就动用拦截器,对发送的消息进行拦截 ProducerRecord<K, V> interceptedRecord = this
2021-04-29 14:56:30
86
原创 KafkaProducer初始化时,是否会拉取集群元数据?
debug看一下://核心行为:初始化时,直接调用Metadata组件的方法,从Broker上拉取1次集群元数据,每隔5min刷新一次//在发送消息过程中,如果没找到某个Broker的元数据,也得去拉取一次this.metadata.update(Cluster.bootstrap(addresses), time.milliseconds());会将addresses传进去,并返回包装好的Cluster: //addresses就是我们配置的Broker:[localhost/127.0
2021-04-29 11:33:17
308
原创 Kafka Cluster元数据在客户端缓存采用的数据结构
看Cluster类的数据结构1个Node就代表1个Broker,也就代表了1台机器:private final List<Node> nodes;Set维护了Kafka没有被授权访问的Topic列表://没有被授权访问的Topic列表private final Set<String> unauthorizedTopics;由此可见Kafka支持权限控制,如果客户端没有授权访问某个Topic,它就会被放在此处对于Cluster,还通过一些数据结构,维护了客户端缓存的t
2021-04-29 11:30:25
202
原创 KafkaProducer初始化时涉及到哪些核心组件?
执行以下代码:KafkaProducer<String,String> producer = new KafkaProducer<String,String>(props);走构造:public KafkaProducer(Properties properties) { this(new ProducerConfig(properties), null, null);}先把我们的配置拿出来://拿到我们设置的参数Map<String, Object&
2021-04-29 10:35:54
266
原创 Spark自定义累加器
如果需求不仅仅是简单的对i累加,而是操作对象,那就得自定义累加器。首先定义好样例类case class PersonInfo(var personNum: Int, var ageSum: Int)自定义的累加器,需要继承AccumulatorV2,泛型分别表示进来的和出去的类。需要重写6个方法:isZero:每个partition内的累加器是否有初始值copy:复制累加器,Driver端到各个partitionreset:每个partition内,对象的初始值add:每个partition
2021-04-27 10:41:34
830
原创 Worker启动Executor源码
给Executor划分好资源后,Worker就要按此来启动Executor了。资源划分完毕后,会返回每个Executor实得多少core的数组,然后就是循环可用的Worker节点,给Executor划分资源。val assignedCores = scheduleExecutorsOnWorkers(app, usableWorkers, spreadOutApps)// Now that we've decided how many cores to allocate on each worker,
2021-04-26 12:36:56
147
原创 Spark Application资源调度源码
master的receive方法接收到RegisterApplication类型的消息,就要给application划分资源了。 //Driver 端提交过来的要注册Application case RegisterApplication(description, driver) => // TODO Prevent repeated registrations from some driver //如果Master状态是standby 忽略不提交任务
2021-04-25 15:18:33
120
原创 Spark任务提交源码
SparkSubmit的main方法执行,首先要设置一些参数://设置参数val appArgs = new SparkSubmitArguments(args)接着会进行模式匹配,匹配到submit,调用submit方法,做了两件事: //以下方法prepareSubmitEnvironment 返回四元组,重点注意childMainClass类 这里以standalone-cluster为例 // childMainClass:未来启动Driver的main class是谁
2021-04-25 04:08:24
202
原创 Spark Worker启动源码
worker的启动流程和master的启动流程相同,区别就是在worker启动完成后,要向Master注册、汇报资源。在Worker的onStart()方法中会调用registerWithMaster()方法来向Master注册: private def registerWithMaster() { // onDisconnected may be triggered multiple times, so don't attempt registration // if there ar
2021-04-24 11:40:08
142
原创 Spark Master启动源码分析
文章目录一、RPC通信环境二、注册EndPoint底层使用netty通信,先准备出RpcEnv环境来做通信架构,创建:收消息结构、处理消息结构。RpcEnv会处于一直启动的状态,不死不灭。Master启动的时候,会把通信地址(也叫通信邮箱,EndPoint)注册到RpcEnv中。别人想跟Master通信,只需要发送到RpcEnv中,Master的EndPoint刚刚才向RpcEnv注册,于是RpcEnv接收到别人的通信请求,并立刻发送消息给Master。首先,RpcEnv要先创建自己的Rpc环境和En
2021-04-24 10:56:19
156
原创 Spark任务提交流程
文章目录1.Standalone-Client2.Standalone-cluster3.Yarn-Client模式4.Yarn-Cluster1.Standalone-Client[root@node4 bin]# ./spark-submit --master spark://node1:7077 --class org.apache.spark.examples.SparkPi ../examples/jars/spark-examples_2.11-2.3.1.jar 1001.Cl
2021-04-21 09:09:14
2626
3
原创 用Spark实现简单的单词统计
用Scala实现RDD(可以简单理解为是一个list集合,里面放的就是读到的一行一行的数据)是spark中非常核心的内容,只有通过SparkContext才能创建出来RDD。package com.husky.sparkimport org.apache.spark.rdd.RDDimport org.apache.spark.{SparkConf, SparkContext}object SparkWordCount { def main(args: Array[String]): Un
2021-04-18 20:48:25
1869
原创 Redis哨兵机制
文章目录1.分布式哨兵的作用2.sdown和odown的转换机制3.哨兵集群的自动发现机制4.哨兵自动纠正slave5.slave ---> master选举算法哨兵本身也是分布式的,作为一个哨兵集群去运行,互相协同工作。判断一个master node是宕机了,需要大部分的哨兵都同意才行,涉及到了分布式选举的问题1.分布式哨兵的作用集群监控,监控master、slave进程是否正常工作故障转移,master故障(哨兵按照过半机制),自动转移到Slave上。并通知Client新的master地
2021-04-16 10:23:06
139
原创 Redis主从复制原理
文章目录1.主从复制原理2.断点续传3.无磁盘化复制1.主从复制原理启动slave时,它会给master发送PSYNC命令。如果slave第一次连接master,就触发full resynchronization;如果是重新连接,master仅仅会复制给slave缺失的部分。开始full resynchronization的时候,master会启动一个后台线程,开始生成一份RDB快照文件,同时还会将从客户端收到的所有写命令缓存在内存中。RDB文件生成完毕之后,master会将这个RDB发送给slav
2021-04-15 16:57:47
102
原创 RDB和AOF的持久化配置
文章目录RDB相关1.如何配置RDB持久化2.RDB持久化机制的工作流程3.基于RDB的数据恢复AOF相关1.如何配置AOF持久化2.AOF持久化机制的工作流程3.破损文件修复AOF和RDB同时工作RDB相关1.如何配置RDB持久化在redis.conf文件中:# 设置检查点save 900 1save 300 10save 60 10000# 配置 dir 指定 rdb 快照文件的位置dir /var/redis/6379# 配置 dbfilename 指定 rdb 快照文件的名称
2021-04-15 11:33:20
280
原创 数据如何从HBase读到MR
TableMapReduceUtil.initTableMapperJob是用来对内输入的,传递的参数之一,就是输入格式化类TableInputFormat.class,且会进行set操作:job.setInputFormatClass(inputFormatClass);TableInputFormat的父类TableInputFormatBase会创建TableRecordReader:if (trr == null) { trr = new TableRecordReader();}S
2021-04-12 08:41:07
114
原创 数据如何写入到HBase
TableMapReduceUtil.initTableReducerJob是用来向外输出的,传递的参数之一,就是tableName。该方法做的最主要的事,就是设置输出格式化类、配置表。 //设置输出格式化类 job.setOutputFormatClass(TableOutputFormat.class); if (reducer != null) job.setReducerClass(reducer); //输出到table中,table就是传进来的表名 con
2021-04-12 08:32:04
757
原创 垃圾回收机制
文章目录引入一、什么情况下JVM内存中的对象会被垃圾回收1.1 哪些变量引用的对象不能被回收?1.2 Java对象的引用类型1.3拯救者finalize()方法1.4 垃圾回收总结二、分代模型2.1 对象在JVM内存中的分配、流转2.2 内存分配总结三、垃圾回收算法3.1 复制算法四、垃圾回收器4.1 ParNew4.2 CMS引入以下面代码为例:public class Kafka { public static void main(String[] args) { load
2021-04-09 15:40:28
199
原创 JVM内存区域划分
文章目录1.存放类的方法区2.执行代码指令的程序计数器3.Java虚拟机栈4.堆内存5.其他内存区域总结1.存放类的方法区主要放的是 从“.class”加载进来的类public class Kafka { public static void main(String[] args) { ReplicaManager replicaManager = new ReplicaManager(); }}2.执行代码指令的程序计数器coder能看懂“.java”文件,
2021-04-08 10:01:18
141
原创 类加载
文章目录类加载过程1.加载2.验证3.准备4.解析5.初始化类加载器双亲委派机制“.java文件” 编译成“ .class字节码文件”,通过类加载器交给JVM运行。JVM会基于自己的字节码执行引擎,来执行加载到内存中的各种类。类加载过程一个类从加载到使用,要经历 加载—>验证—>准备—>解析—>初始化—>使用—>卸载1.加载代码中用到这个类了,类加载器就会将其加载到JVM内存,main()方法作为入口开始执行。public class User { p
2021-04-08 09:10:42
118
原创 LiveData原理分析
文章目录简述LiveData原理1.订阅、绑定2.setValue发送消息3.总结简述LiveData是一个可被观察的数据容器类,它将数据包装起来,使数据成为被观察者。当数据发生改变时,观察者能够及时得到通知。又是一个典型的观察者模式!ViewModel用来存放页面所需要的数据、和数据相关的处理逻辑(在ViewModel中对数据进行加工、获取),站在页面的角度上,它并不关心ViewModel的业务逻辑,只关心需要展示的数据是啥。它希望在数据发生改变时,能够及时的得到通知并作出更新。而LiveData的
2020-10-14 14:50:40
1315
1
原创 LifeCycle原理分析
文章目录简述LifeCycle的原理简述解耦是永恒不变的话题,但是又不得不做。平时在onCreate方法中初始化,在onDestory中回收资源,这样会使页面和组件之间的耦合度增加,不这样做又会造成内存泄漏。我们希望对组件的管理,不仅仅是依赖生命周期函数的管理方法。LifeCycle正是因此出现的,组件就能够在内部自己管理自己的生命周期,从而降低模块间的耦合度,并降低内存泄漏的可能性。LifeCycle的原理LifeCycle是通过观察者模式,实现对页面生命周期的监听。Jetpack提供了两个类:
2020-10-14 10:49:40
884
原创 解析RecyclerView的缓存机制
文章目录复用:layoutChunk(recycler, state, layoutState, layoutChunkResult)1. getChangedScrapViewForPosition方法--->mChangedScrap2.getScrapOrHiddenOrCachedHolderForPosition--->mAttachedScrap、mCachedViews3. getScrapOrCachedViewForId--->mAttachedScrap、mCached
2020-07-16 15:50:39
634
原创 事件分发机制并不是洪水猛兽
当MotionEvent产生后,系统总归要将其传递到某个View,这个过程就是事件分发。事件分发机制离不开3个重要方法:dispatchTouchEvent(分发)、onInterceptTouchEvent(拦截,在dispatchTouchEvent中调用。需要注意,View中没有该方法)、onInterceptTouchEvent(处理事件,在dispatchTouchEvent中调用。)这3个方法相爱相杀,紧密关联。ViewGroup收到点击事件后,它的dispatchTouchEvent方法首先
2020-07-13 18:23:21
246
原创 解析SharedPreferences
文章目录简介一、文件保存二、SP创建三、SP数据加载四、getxxx()操作五、putXXX()操作5.1 commit &&apply5.2 apply简介sp作为轻量级存储,数据最终都是以xml的形式进行存储的。一、文件保存SharedPreferences config = getSharedPreferences("config", Context.MODE_PRI...
2020-04-30 13:13:06
523
原创 9.0适配刘海屏
刘海屏适配,就是不让刘海遮挡住应用程序,不影响应用程序的正常使用。竖屏情况下,系统会根据刘海的高度,响应调整状态栏的高度。因此,刘海对竖屏模式没有影响。可是横屏模式下,刘海区域就会变成一条大黑边。Android 9.0系统中提供了3种layoutInDisplayCutoutMode属性来允许应用自主决定该如何对刘海屏设备进行适配:①LAYOUT_IN_DISPLAY_CUTOUT_M...
2020-04-27 15:49:17
698
原创 沉浸式学习
沉浸式就是利用系统状态栏,将背景图片延伸至系统状态栏区域内,效果就是和游戏应用画面那样。Action1 隐藏状态栏和ActionBar仅仅是隐藏状态栏和ActionBar,只是粗暴的隐藏了而已//获取当前界面的DecorView View decorView = getWindow().getDecorView(); //表示全屏,即隐藏状态栏 int option ...
2020-04-27 10:36:56
3283
原创 黑白屏解决方案
文章目录一、黑白屏原因二、解决方案2.1 修改AppTheme2.2 自定义AppTheme一、黑白屏原因在app启动流程中,当系统加载并启动app时,需要耗费一定的时间。即使这个时间非常短,但是用户依旧会感觉点击App图标的“延迟”。为解决这一问题,Google在App创建的过程中,先展示一个空白页面,让用户体会到点击图标后立马就会有响应。而这个空白页面的颜色,就是根据我们清单文件中配置的主...
2020-03-27 21:59:09
894
原创 刘海屏适配
文章目录一、简述二、实现三、手机厂商的适配四、工具类一、简述Android官方9.0刘海屏的适配策略是:如果非全屏模式(有状态栏),则app不受刘海屏的影响,刘海屏的高就是状态栏的高;如果全屏模式,app未适配刘海屏,系统会对界面做特殊处理,竖屏向下移动,横屏向右移动。二、实现必须在setContentView方法前调用 requestWindowFeature(Window.FEATU...
2020-03-18 15:40:26
524
空空如也
空空如也
TA创建的收藏夹 TA关注的收藏夹
TA关注的人
RSS订阅